Blame view

drivers/acpi/processor_throttling.c 31.6 KB
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
  /*
   * processor_throttling.c - Throttling submodule of the ACPI processor driver
   *
   *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
   *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
   *  Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
   *  Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
   *  			- Added processor hotplug support
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   *
   *  This program is free software; you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation; either version 2 of the License, or (at
   *  your option) any later version.
   *
   *  This program is distributed in the hope that it will be useful, but
   *  WITHOUT ANY WARRANTY; without even the implied warranty of
   *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   *  General Public License for more details.
   *
   *  You should have received a copy of the GNU General Public License along
   *  with this program; if not, write to the Free Software Foundation, Inc.,
   *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
   *
   * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   */
  
  #include <linux/kernel.h>
  #include <linux/module.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
31
  #include <linux/slab.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
32
  #include <linux/init.h>
357dc4c3f   Zhao Yakui   ACPI: Delete the ...
33
  #include <linux/sched.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
34
  #include <linux/cpufreq.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
35
36
37
38
39
  
  #include <asm/io.h>
  #include <asm/uaccess.h>
  
  #include <acpi/acpi_bus.h>
89595b8f2   Bjorn Helgaas   ACPI: consolidate...
40
  #include <acpi/acpi_drivers.h>
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
41
  #include <acpi/processor.h>
a192a9580   Len Brown   ACPI: Move defini...
42
  #define PREFIX "ACPI: "
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
43
  #define ACPI_PROCESSOR_CLASS            "processor"
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
44
  #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
f52fd66d2   Len Brown   ACPI: clean up AC...
45
  ACPI_MODULE_NAME("processor_throttling");
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
46

56c213fa0   Zhang Rui   ACPI processor: i...
47
48
49
50
51
52
53
  /* ignore_tpc:
   *  0 -> acpi processor driver doesn't ignore _TPC values
   *  1 -> acpi processor driver ignores _TPC values
   */
  static int ignore_tpc;
  module_param(ignore_tpc, int, 0644);
  MODULE_PARM_DESC(ignore_tpc, "Disable broken BIOS _TPC throttling support");
e4aa5cb21   Zhao Yakui   ACPI : Add T-stat...
54
55
56
57
58
59
60
  struct throttling_tstate {
  	unsigned int cpu;		/* cpu nr */
  	int target_state;		/* target T-state */
  };
  
  #define THROTTLING_PRECHANGE       (1)
  #define THROTTLING_POSTCHANGE      (2)
ff55a9ceb   Len Brown   ACPI: Lindent pro...
61
  static int acpi_processor_get_throttling(struct acpi_processor *pr);
2a908002c   Frans Pop   ACPI processor: f...
62
63
  int acpi_processor_set_throttling(struct acpi_processor *pr,
  						int state, bool force);
01854e697   Luming Yu   ACPI: add ACPI 3....
64

1180509f6   Zhao Yakui   ACPI : Update T-s...
65
66
67
68
69
  static int acpi_processor_update_tsd_coord(void)
  {
  	int count, count_target;
  	int retval = 0;
  	unsigned int i, j;
2fdf66b49   Rusty Russell   cpumask: convert ...
70
  	cpumask_var_t covered_cpus;
1180509f6   Zhao Yakui   ACPI : Update T-s...
71
72
73
  	struct acpi_processor *pr, *match_pr;
  	struct acpi_tsd_package *pdomain, *match_pdomain;
  	struct acpi_processor_throttling *pthrottling, *match_pthrottling;
79f559977   Li Zefan   cpumask: use zall...
74
  	if (!zalloc_cpumask_var(&covered_cpus, GFP_KERNEL))
2fdf66b49   Rusty Russell   cpumask: convert ...
75
  		return -ENOMEM;
1180509f6   Zhao Yakui   ACPI : Update T-s...
76
77
  	/*
  	 * Now that we have _TSD data from all CPUs, lets setup T-state
33a2a529f   Zhao Yakui   ACPI: Update the ...
78
  	 * coordination between all CPUs.
1180509f6   Zhao Yakui   ACPI : Update T-s...
79
80
  	 */
  	for_each_possible_cpu(i) {
706546d02   Mike Travis   ACPI: change proc...
81
  		pr = per_cpu(processors, i);
1180509f6   Zhao Yakui   ACPI : Update T-s...
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
  		if (!pr)
  			continue;
  
  		/* Basic validity check for domain info */
  		pthrottling = &(pr->throttling);
  
  		/*
  		 * If tsd package for one cpu is invalid, the coordination
  		 * among all CPUs is thought as invalid.
  		 * Maybe it is ugly.
  		 */
  		if (!pthrottling->tsd_valid_flag) {
  			retval = -EINVAL;
  			break;
  		}
  	}
  	if (retval)
  		goto err_ret;
1180509f6   Zhao Yakui   ACPI : Update T-s...
100
  	for_each_possible_cpu(i) {
706546d02   Mike Travis   ACPI: change proc...
101
  		pr = per_cpu(processors, i);
1180509f6   Zhao Yakui   ACPI : Update T-s...
102
103
  		if (!pr)
  			continue;
2fdf66b49   Rusty Russell   cpumask: convert ...
104
  		if (cpumask_test_cpu(i, covered_cpus))
1180509f6   Zhao Yakui   ACPI : Update T-s...
105
106
107
108
  			continue;
  		pthrottling = &pr->throttling;
  
  		pdomain = &(pthrottling->domain_info);
2fdf66b49   Rusty Russell   cpumask: convert ...
109
110
  		cpumask_set_cpu(i, pthrottling->shared_cpu_map);
  		cpumask_set_cpu(i, covered_cpus);
1180509f6   Zhao Yakui   ACPI : Update T-s...
111
112
113
114
115
116
117
118
119
120
121
122
123
124
  		/*
  		 * If the number of processor in the TSD domain is 1, it is
  		 * unnecessary to parse the coordination for this CPU.
  		 */
  		if (pdomain->num_processors <= 1)
  			continue;
  
  		/* Validate the Domain info */
  		count_target = pdomain->num_processors;
  		count = 1;
  
  		for_each_possible_cpu(j) {
  			if (i == j)
  				continue;
706546d02   Mike Travis   ACPI: change proc...
125
  			match_pr = per_cpu(processors, j);
1180509f6   Zhao Yakui   ACPI : Update T-s...
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
  			if (!match_pr)
  				continue;
  
  			match_pthrottling = &(match_pr->throttling);
  			match_pdomain = &(match_pthrottling->domain_info);
  			if (match_pdomain->domain != pdomain->domain)
  				continue;
  
  			/* Here i and j are in the same domain.
  			 * If two TSD packages have the same domain, they
  			 * should have the same num_porcessors and
  			 * coordination type. Otherwise it will be regarded
  			 * as illegal.
  			 */
  			if (match_pdomain->num_processors != count_target) {
  				retval = -EINVAL;
  				goto err_ret;
  			}
  
  			if (pdomain->coord_type != match_pdomain->coord_type) {
  				retval = -EINVAL;
  				goto err_ret;
  			}
2fdf66b49   Rusty Russell   cpumask: convert ...
149
150
  			cpumask_set_cpu(j, covered_cpus);
  			cpumask_set_cpu(j, pthrottling->shared_cpu_map);
1180509f6   Zhao Yakui   ACPI : Update T-s...
151
152
153
154
155
  			count++;
  		}
  		for_each_possible_cpu(j) {
  			if (i == j)
  				continue;
706546d02   Mike Travis   ACPI: change proc...
156
  			match_pr = per_cpu(processors, j);
1180509f6   Zhao Yakui   ACPI : Update T-s...
157
158
159
160
161
162
163
164
165
166
167
168
  			if (!match_pr)
  				continue;
  
  			match_pthrottling = &(match_pr->throttling);
  			match_pdomain = &(match_pthrottling->domain_info);
  			if (match_pdomain->domain != pdomain->domain)
  				continue;
  
  			/*
  			 * If some CPUS have the same domain, they
  			 * will have the same shared_cpu_map.
  			 */
2fdf66b49   Rusty Russell   cpumask: convert ...
169
170
  			cpumask_copy(match_pthrottling->shared_cpu_map,
  				     pthrottling->shared_cpu_map);
1180509f6   Zhao Yakui   ACPI : Update T-s...
171
172
173
174
  		}
  	}
  
  err_ret:
2fdf66b49   Rusty Russell   cpumask: convert ...
175
  	free_cpumask_var(covered_cpus);
1180509f6   Zhao Yakui   ACPI : Update T-s...
176
  	for_each_possible_cpu(i) {
706546d02   Mike Travis   ACPI: change proc...
177
  		pr = per_cpu(processors, i);
1180509f6   Zhao Yakui   ACPI : Update T-s...
178
179
180
181
182
183
184
185
186
  		if (!pr)
  			continue;
  
  		/*
  		 * Assume no coordination on any error parsing domain info.
  		 * The coordination type will be forced as SW_ALL.
  		 */
  		if (retval) {
  			pthrottling = &(pr->throttling);
2fdf66b49   Rusty Russell   cpumask: convert ...
187
188
  			cpumask_clear(pthrottling->shared_cpu_map);
  			cpumask_set_cpu(i, pthrottling->shared_cpu_map);
1180509f6   Zhao Yakui   ACPI : Update T-s...
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
  			pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
  		}
  	}
  
  	return retval;
  }
  
  /*
   * Update the T-state coordination after the _TSD
   * data for all cpus is obtained.
   */
  void acpi_processor_throttling_init(void)
  {
  	if (acpi_processor_update_tsd_coord())
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  			"Assume no T-state coordination
  "));
  
  	return;
  }
e4aa5cb21   Zhao Yakui   ACPI : Add T-stat...
209
210
211
212
213
214
215
216
217
218
  static int acpi_processor_throttling_notifier(unsigned long event, void *data)
  {
  	struct throttling_tstate *p_tstate = data;
  	struct acpi_processor *pr;
  	unsigned int cpu ;
  	int target_state;
  	struct acpi_processor_limit *p_limit;
  	struct acpi_processor_throttling *p_throttling;
  
  	cpu = p_tstate->cpu;
706546d02   Mike Travis   ACPI: change proc...
219
  	pr = per_cpu(processors, cpu);
e4aa5cb21   Zhao Yakui   ACPI : Add T-stat...
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
  	if (!pr) {
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid pr pointer
  "));
  		return 0;
  	}
  	if (!pr->flags.throttling) {
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Throttling control is "
  				"unsupported on CPU %d
  ", cpu));
  		return 0;
  	}
  	target_state = p_tstate->target_state;
  	p_throttling = &(pr->throttling);
  	switch (event) {
  	case THROTTLING_PRECHANGE:
  		/*
  		 * Prechange event is used to choose one proper t-state,
  		 * which meets the limits of thermal, user and _TPC.
  		 */
  		p_limit = &pr->limit;
  		if (p_limit->thermal.tx > target_state)
  			target_state = p_limit->thermal.tx;
  		if (p_limit->user.tx > target_state)
  			target_state = p_limit->user.tx;
  		if (pr->throttling_platform_limit > target_state)
  			target_state = pr->throttling_platform_limit;
  		if (target_state >= p_throttling->state_count) {
  			printk(KERN_WARNING
  				"Exceed the limit of T-state 
  ");
  			target_state = p_throttling->state_count - 1;
  		}
  		p_tstate->target_state = target_state;
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PreChange Event:"
  				"target T-state of CPU %d is T%d
  ",
  				cpu, target_state));
  		break;
  	case THROTTLING_POSTCHANGE:
  		/*
  		 * Postchange event is only used to update the
  		 * T-state flag of acpi_processor_throttling.
  		 */
  		p_throttling->state = target_state;
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "PostChange Event:"
  				"CPU %d is switched to T%d
  ",
  				cpu, target_state));
  		break;
  	default:
  		printk(KERN_WARNING
  			"Unsupported Throttling notifier event
  ");
  		break;
  	}
  
  	return 0;
  }
c30c620ee   Len Brown   ACPI: quiet ACPI ...
278
279
280
  /*
   * _TPC - Throttling Present Capabilities
   */
01854e697   Luming Yu   ACPI: add ACPI 3....
281
282
283
  static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
  {
  	acpi_status status = 0;
27663c585   Matthew Wilcox   ACPI: Change acpi...
284
  	unsigned long long tpc = 0;
01854e697   Luming Yu   ACPI: add ACPI 3....
285

ff55a9ceb   Len Brown   ACPI: Lindent pro...
286
  	if (!pr)
01854e697   Luming Yu   ACPI: add ACPI 3....
287
  		return -EINVAL;
56c213fa0   Zhang Rui   ACPI processor: i...
288
289
290
  
  	if (ignore_tpc)
  		goto end;
01854e697   Luming Yu   ACPI: add ACPI 3....
291
  	status = acpi_evaluate_integer(pr->handle, "_TPC", NULL, &tpc);
c30c620ee   Len Brown   ACPI: quiet ACPI ...
292
293
294
295
  	if (ACPI_FAILURE(status)) {
  		if (status != AE_NOT_FOUND) {
  			ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TPC"));
  		}
01854e697   Luming Yu   ACPI: add ACPI 3....
296
297
  		return -ENODEV;
  	}
56c213fa0   Zhang Rui   ACPI processor: i...
298
299
  
  end:
01854e697   Luming Yu   ACPI: add ACPI 3....
300
301
302
303
304
305
  	pr->throttling_platform_limit = (int)tpc;
  	return 0;
  }
  
  int acpi_processor_tstate_has_changed(struct acpi_processor *pr)
  {
ef54d5ad2   Zhao Yakui   ACPI: Enforce T-s...
306
307
308
309
310
  	int result = 0;
  	int throttling_limit;
  	int current_state;
  	struct acpi_processor_limit *limit;
  	int target_state;
56c213fa0   Zhang Rui   ACPI processor: i...
311
312
  	if (ignore_tpc)
  		return 0;
ef54d5ad2   Zhao Yakui   ACPI: Enforce T-s...
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
  	result = acpi_processor_get_platform_limit(pr);
  	if (result) {
  		/* Throttling Limit is unsupported */
  		return result;
  	}
  
  	throttling_limit = pr->throttling_platform_limit;
  	if (throttling_limit >= pr->throttling.state_count) {
  		/* Uncorrect Throttling Limit */
  		return -EINVAL;
  	}
  
  	current_state = pr->throttling.state;
  	if (current_state > throttling_limit) {
  		/*
  		 * The current state can meet the requirement of
  		 * _TPC limit. But it is reasonable that OSPM changes
  		 * t-states from high to low for better performance.
  		 * Of course the limit condition of thermal
  		 * and user should be considered.
  		 */
  		limit = &pr->limit;
  		target_state = throttling_limit;
  		if (limit->thermal.tx > target_state)
  			target_state = limit->thermal.tx;
  		if (limit->user.tx > target_state)
  			target_state = limit->user.tx;
  	} else if (current_state == throttling_limit) {
  		/*
  		 * Unnecessary to change the throttling state
  		 */
  		return 0;
  	} else {
  		/*
  		 * If the current state is lower than the limit of _TPC, it
  		 * will be forced to switch to the throttling state defined
  		 * by throttling_platfor_limit.
  		 * Because the previous state meets with the limit condition
  		 * of thermal and user, it is unnecessary to check it again.
  		 */
  		target_state = throttling_limit;
  	}
2a908002c   Frans Pop   ACPI processor: f...
355
  	return acpi_processor_set_throttling(pr, target_state, false);
01854e697   Luming Yu   ACPI: add ACPI 3....
356
  }
c30c620ee   Len Brown   ACPI: quiet ACPI ...
357
  /*
5a344a505   Zhao Yakui   ACPI: Reevaluate ...
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
   * This function is used to reevaluate whether the T-state is valid
   * after one CPU is onlined/offlined.
   * It is noted that it won't reevaluate the following properties for
   * the T-state.
   *	1. Control method.
   *	2. the number of supported T-state
   *	3. TSD domain
   */
  void acpi_processor_reevaluate_tstate(struct acpi_processor *pr,
  					unsigned long action)
  {
  	int result = 0;
  
  	if (action == CPU_DEAD) {
  		/* When one CPU is offline, the T-state throttling
  		 * will be invalidated.
  		 */
  		pr->flags.throttling = 0;
  		return;
  	}
  	/* the following is to recheck whether the T-state is valid for
  	 * the online CPU
  	 */
  	if (!pr->throttling.state_count) {
  		/* If the number of T-state is invalid, it is
  		 * invalidated.
  		 */
  		pr->flags.throttling = 0;
  		return;
  	}
  	pr->flags.throttling = 1;
  
  	/* Disable throttling (if enabled).  We'll let subsequent
  	 * policy (e.g.thermal) decide to lower performance if it
  	 * so chooses, but for now we'll crank up the speed.
  	 */
  
  	result = acpi_processor_get_throttling(pr);
  	if (result)
  		goto end;
  
  	if (pr->throttling.state) {
  		result = acpi_processor_set_throttling(pr, 0, false);
  		if (result)
  			goto end;
  	}
  
  end:
  	if (result)
  		pr->flags.throttling = 0;
  }
  /*
c30c620ee   Len Brown   ACPI: quiet ACPI ...
410
411
   * _PTC - Processor Throttling Control (and status) register location
   */
01854e697   Luming Yu   ACPI: add ACPI 3....
412
413
414
415
416
417
418
  static int acpi_processor_get_throttling_control(struct acpi_processor *pr)
  {
  	int result = 0;
  	acpi_status status = 0;
  	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  	union acpi_object *ptc = NULL;
  	union acpi_object obj = { 0 };
9bcb27217   Zhao Yakui   ACPI: Use _TSS fo...
419
  	struct acpi_processor_throttling *throttling;
01854e697   Luming Yu   ACPI: add ACPI 3....
420
421
422
  
  	status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer);
  	if (ACPI_FAILURE(status)) {
c30c620ee   Len Brown   ACPI: quiet ACPI ...
423
424
425
  		if (status != AE_NOT_FOUND) {
  			ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PTC"));
  		}
01854e697   Luming Yu   ACPI: add ACPI 3....
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
  		return -ENODEV;
  	}
  
  	ptc = (union acpi_object *)buffer.pointer;
  	if (!ptc || (ptc->type != ACPI_TYPE_PACKAGE)
  	    || (ptc->package.count != 2)) {
  		printk(KERN_ERR PREFIX "Invalid _PTC data
  ");
  		result = -EFAULT;
  		goto end;
  	}
  
  	/*
  	 * control_register
  	 */
  
  	obj = ptc->package.elements[0];
  
  	if ((obj.type != ACPI_TYPE_BUFFER)
  	    || (obj.buffer.length < sizeof(struct acpi_ptc_register))
  	    || (obj.buffer.pointer == NULL)) {
ff55a9ceb   Len Brown   ACPI: Lindent pro...
447
448
449
  		printk(KERN_ERR PREFIX
  		       "Invalid _PTC data (control_register)
  ");
01854e697   Luming Yu   ACPI: add ACPI 3....
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
  		result = -EFAULT;
  		goto end;
  	}
  	memcpy(&pr->throttling.control_register, obj.buffer.pointer,
  	       sizeof(struct acpi_ptc_register));
  
  	/*
  	 * status_register
  	 */
  
  	obj = ptc->package.elements[1];
  
  	if ((obj.type != ACPI_TYPE_BUFFER)
  	    || (obj.buffer.length < sizeof(struct acpi_ptc_register))
  	    || (obj.buffer.pointer == NULL)) {
  		printk(KERN_ERR PREFIX "Invalid _PTC data (status_register)
  ");
  		result = -EFAULT;
  		goto end;
  	}
  
  	memcpy(&pr->throttling.status_register, obj.buffer.pointer,
ff55a9ceb   Len Brown   ACPI: Lindent pro...
472
  	       sizeof(struct acpi_ptc_register));
01854e697   Luming Yu   ACPI: add ACPI 3....
473

9bcb27217   Zhao Yakui   ACPI: Use _TSS fo...
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
  	throttling = &pr->throttling;
  
  	if ((throttling->control_register.bit_width +
  		throttling->control_register.bit_offset) > 32) {
  		printk(KERN_ERR PREFIX "Invalid _PTC control register
  ");
  		result = -EFAULT;
  		goto end;
  	}
  
  	if ((throttling->status_register.bit_width +
  		throttling->status_register.bit_offset) > 32) {
  		printk(KERN_ERR PREFIX "Invalid _PTC status register
  ");
  		result = -EFAULT;
  		goto end;
  	}
ff55a9ceb   Len Brown   ACPI: Lindent pro...
491
        end:
01854e697   Luming Yu   ACPI: add ACPI 3....
492
493
494
495
  	kfree(buffer.pointer);
  
  	return result;
  }
c30c620ee   Len Brown   ACPI: quiet ACPI ...
496
497
498
499
  
  /*
   * _TSS - Throttling Supported States
   */
01854e697   Luming Yu   ACPI: add ACPI 3....
500
501
502
503
504
505
506
507
508
509
510
511
  static int acpi_processor_get_throttling_states(struct acpi_processor *pr)
  {
  	int result = 0;
  	acpi_status status = AE_OK;
  	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  	struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" };
  	struct acpi_buffer state = { 0, NULL };
  	union acpi_object *tss = NULL;
  	int i;
  
  	status = acpi_evaluate_object(pr->handle, "_TSS", NULL, &buffer);
  	if (ACPI_FAILURE(status)) {
c30c620ee   Len Brown   ACPI: quiet ACPI ...
512
513
514
  		if (status != AE_NOT_FOUND) {
  			ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TSS"));
  		}
01854e697   Luming Yu   ACPI: add ACPI 3....
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
  		return -ENODEV;
  	}
  
  	tss = buffer.pointer;
  	if (!tss || (tss->type != ACPI_TYPE_PACKAGE)) {
  		printk(KERN_ERR PREFIX "Invalid _TSS data
  ");
  		result = -EFAULT;
  		goto end;
  	}
  
  	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states
  ",
  			  tss->package.count));
  
  	pr->throttling.state_count = tss->package.count;
  	pr->throttling.states_tss =
  	    kmalloc(sizeof(struct acpi_processor_tx_tss) * tss->package.count,
  		    GFP_KERNEL);
  	if (!pr->throttling.states_tss) {
  		result = -ENOMEM;
  		goto end;
  	}
  
  	for (i = 0; i < pr->throttling.state_count; i++) {
ff55a9ceb   Len Brown   ACPI: Lindent pro...
540
541
542
  		struct acpi_processor_tx_tss *tx =
  		    (struct acpi_processor_tx_tss *)&(pr->throttling.
  						      states_tss[i]);
01854e697   Luming Yu   ACPI: add ACPI 3....
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
  
  		state.length = sizeof(struct acpi_processor_tx_tss);
  		state.pointer = tx;
  
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d
  ", i));
  
  		status = acpi_extract_package(&(tss->package.elements[i]),
  					      &format, &state);
  		if (ACPI_FAILURE(status)) {
  			ACPI_EXCEPTION((AE_INFO, status, "Invalid _TSS data"));
  			result = -EFAULT;
  			kfree(pr->throttling.states_tss);
  			goto end;
  		}
  
  		if (!tx->freqpercentage) {
  			printk(KERN_ERR PREFIX
ff55a9ceb   Len Brown   ACPI: Lindent pro...
561
562
  			       "Invalid _TSS data: freq is zero
  ");
01854e697   Luming Yu   ACPI: add ACPI 3....
563
564
565
566
567
568
569
570
571
572
573
  			result = -EFAULT;
  			kfree(pr->throttling.states_tss);
  			goto end;
  		}
  	}
  
        end:
  	kfree(buffer.pointer);
  
  	return result;
  }
c30c620ee   Len Brown   ACPI: quiet ACPI ...
574
575
576
577
  
  /*
   * _TSD - T-State Dependencies
   */
ff55a9ceb   Len Brown   ACPI: Lindent pro...
578
  static int acpi_processor_get_tsd(struct acpi_processor *pr)
01854e697   Luming Yu   ACPI: add ACPI 3....
579
580
581
  {
  	int result = 0;
  	acpi_status status = AE_OK;
ff55a9ceb   Len Brown   ACPI: Lindent pro...
582
583
584
585
  	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
  	struct acpi_buffer format = { sizeof("NNNNN"), "NNNNN" };
  	struct acpi_buffer state = { 0, NULL };
  	union acpi_object *tsd = NULL;
01854e697   Luming Yu   ACPI: add ACPI 3....
586
  	struct acpi_tsd_package *pdomain;
1180509f6   Zhao Yakui   ACPI : Update T-s...
587
588
589
590
  	struct acpi_processor_throttling *pthrottling;
  
  	pthrottling = &pr->throttling;
  	pthrottling->tsd_valid_flag = 0;
01854e697   Luming Yu   ACPI: add ACPI 3....
591
592
593
  
  	status = acpi_evaluate_object(pr->handle, "_TSD", NULL, &buffer);
  	if (ACPI_FAILURE(status)) {
c30c620ee   Len Brown   ACPI: quiet ACPI ...
594
595
596
  		if (status != AE_NOT_FOUND) {
  			ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TSD"));
  		}
01854e697   Luming Yu   ACPI: add ACPI 3....
597
598
599
600
601
  		return -ENODEV;
  	}
  
  	tsd = buffer.pointer;
  	if (!tsd || (tsd->type != ACPI_TYPE_PACKAGE)) {
55ac9a018   Lin Ming   ACPI: replace ACP...
602
603
  		printk(KERN_ERR PREFIX "Invalid _TSD data
  ");
01854e697   Luming Yu   ACPI: add ACPI 3....
604
605
606
607
608
  		result = -EFAULT;
  		goto end;
  	}
  
  	if (tsd->package.count != 1) {
55ac9a018   Lin Ming   ACPI: replace ACP...
609
610
  		printk(KERN_ERR PREFIX "Invalid _TSD data
  ");
01854e697   Luming Yu   ACPI: add ACPI 3....
611
612
613
614
615
616
617
618
619
620
  		result = -EFAULT;
  		goto end;
  	}
  
  	pdomain = &(pr->throttling.domain_info);
  
  	state.length = sizeof(struct acpi_tsd_package);
  	state.pointer = pdomain;
  
  	status = acpi_extract_package(&(tsd->package.elements[0]),
ff55a9ceb   Len Brown   ACPI: Lindent pro...
621
  				      &format, &state);
01854e697   Luming Yu   ACPI: add ACPI 3....
622
  	if (ACPI_FAILURE(status)) {
55ac9a018   Lin Ming   ACPI: replace ACP...
623
624
  		printk(KERN_ERR PREFIX "Invalid _TSD data
  ");
01854e697   Luming Yu   ACPI: add ACPI 3....
625
626
627
628
629
  		result = -EFAULT;
  		goto end;
  	}
  
  	if (pdomain->num_entries != ACPI_TSD_REV0_ENTRIES) {
55ac9a018   Lin Ming   ACPI: replace ACP...
630
631
  		printk(KERN_ERR PREFIX "Unknown _TSD:num_entries
  ");
01854e697   Luming Yu   ACPI: add ACPI 3....
632
633
634
635
636
  		result = -EFAULT;
  		goto end;
  	}
  
  	if (pdomain->revision != ACPI_TSD_REV0_REVISION) {
55ac9a018   Lin Ming   ACPI: replace ACP...
637
638
  		printk(KERN_ERR PREFIX "Unknown _TSD:revision
  ");
01854e697   Luming Yu   ACPI: add ACPI 3....
639
640
641
  		result = -EFAULT;
  		goto end;
  	}
1180509f6   Zhao Yakui   ACPI : Update T-s...
642
643
644
  	pthrottling = &pr->throttling;
  	pthrottling->tsd_valid_flag = 1;
  	pthrottling->shared_type = pdomain->coord_type;
2fdf66b49   Rusty Russell   cpumask: convert ...
645
  	cpumask_set_cpu(pr->id, pthrottling->shared_cpu_map);
1180509f6   Zhao Yakui   ACPI : Update T-s...
646
647
648
649
650
651
652
653
654
655
656
  	/*
  	 * If the coordination type is not defined in ACPI spec,
  	 * the tsd_valid_flag will be clear and coordination type
  	 * will be forecd as DOMAIN_COORD_TYPE_SW_ALL.
  	 */
  	if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL &&
  		pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY &&
  		pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) {
  		pthrottling->tsd_valid_flag = 0;
  		pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
  	}
ff55a9ceb   Len Brown   ACPI: Lindent pro...
657
        end:
01854e697   Luming Yu   ACPI: add ACPI 3....
658
659
660
  	kfree(buffer.pointer);
  	return result;
  }
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
661
662
663
  /* --------------------------------------------------------------------------
                                Throttling Control
     -------------------------------------------------------------------------- */
01854e697   Luming Yu   ACPI: add ACPI 3....
664
  static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
665
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
666
667
668
669
  	int state = 0;
  	u32 value = 0;
  	u32 duty_mask = 0;
  	u32 duty_value = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
670

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
671
  	if (!pr)
d550d98d3   Patrick Mochel   ACPI: delete trac...
672
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
673
674
  
  	if (!pr->flags.throttling)
d550d98d3   Patrick Mochel   ACPI: delete trac...
675
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
  
  	pr->throttling.state = 0;
  
  	duty_mask = pr->throttling.state_count - 1;
  
  	duty_mask <<= pr->throttling.duty_offset;
  
  	local_irq_disable();
  
  	value = inl(pr->throttling.address);
  
  	/*
  	 * Compute the current throttling state when throttling is enabled
  	 * (bit 4 is on).
  	 */
  	if (value & 0x10) {
  		duty_value = value & duty_mask;
  		duty_value >>= pr->throttling.duty_offset;
  
  		if (duty_value)
4be44fcd3   Len Brown   [ACPI] Lindent al...
696
  			state = pr->throttling.state_count - duty_value;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
697
698
699
700
701
702
703
  	}
  
  	pr->throttling.state = state;
  
  	local_irq_enable();
  
  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd3   Len Brown   [ACPI] Lindent al...
704
705
706
  			  "Throttling state is T%d (%d%% throttling applied)
  ",
  			  state, pr->throttling.states[state].performance));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
707

d550d98d3   Patrick Mochel   ACPI: delete trac...
708
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
709
  }
f79f06ab9   Zhao Yakui   ACPI: Enable MSR ...
710
  #ifdef CONFIG_X86
9d42a53e0   Christoph Lameter   acpi throttling: ...
711
  static int acpi_throttling_rdmsr(u64 *value)
f79f06ab9   Zhao Yakui   ACPI: Enable MSR ...
712
  {
f79f06ab9   Zhao Yakui   ACPI: Enable MSR ...
713
  	u64 msr_high, msr_low;
f79f06ab9   Zhao Yakui   ACPI: Enable MSR ...
714
715
  	u64 msr = 0;
  	int ret = -1;
9d42a53e0   Christoph Lameter   acpi throttling: ...
716
717
  	if ((this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_INTEL) ||
  		!this_cpu_has(X86_FEATURE_ACPI)) {
f79f06ab9   Zhao Yakui   ACPI: Enable MSR ...
718
719
720
721
722
723
  		printk(KERN_ERR PREFIX
  			"HARDWARE addr space,NOT supported yet
  ");
  	} else {
  		msr_low = 0;
  		msr_high = 0;
357dc4c3f   Zhao Yakui   ACPI: Delete the ...
724
  		rdmsr_safe(MSR_IA32_THERM_CONTROL,
f79f06ab9   Zhao Yakui   ACPI: Enable MSR ...
725
726
  			(u32 *)&msr_low , (u32 *) &msr_high);
  		msr = (msr_high << 32) | msr_low;
439913fff   Lin Ming   ACPI: replace acp...
727
  		*value = (u64) msr;
f79f06ab9   Zhao Yakui   ACPI: Enable MSR ...
728
729
730
731
  		ret = 0;
  	}
  	return ret;
  }
9d42a53e0   Christoph Lameter   acpi throttling: ...
732
  static int acpi_throttling_wrmsr(u64 value)
f79f06ab9   Zhao Yakui   ACPI: Enable MSR ...
733
  {
f79f06ab9   Zhao Yakui   ACPI: Enable MSR ...
734
735
  	int ret = -1;
  	u64 msr;
9d42a53e0   Christoph Lameter   acpi throttling: ...
736
737
  	if ((this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_INTEL) ||
  		!this_cpu_has(X86_FEATURE_ACPI)) {
f79f06ab9   Zhao Yakui   ACPI: Enable MSR ...
738
739
740
741
742
  		printk(KERN_ERR PREFIX
  			"HARDWARE addr space,NOT supported yet
  ");
  	} else {
  		msr = value;
357dc4c3f   Zhao Yakui   ACPI: Delete the ...
743
  		wrmsr_safe(MSR_IA32_THERM_CONTROL,
f79f06ab9   Zhao Yakui   ACPI: Enable MSR ...
744
745
746
747
748
749
  			msr & 0xffffffff, msr >> 32);
  		ret = 0;
  	}
  	return ret;
  }
  #else
9d42a53e0   Christoph Lameter   acpi throttling: ...
750
  static int acpi_throttling_rdmsr(u64 *value)
f79f06ab9   Zhao Yakui   ACPI: Enable MSR ...
751
752
753
754
755
756
  {
  	printk(KERN_ERR PREFIX
  		"HARDWARE addr space,NOT supported yet
  ");
  	return -1;
  }
9d42a53e0   Christoph Lameter   acpi throttling: ...
757
  static int acpi_throttling_wrmsr(u64 value)
f79f06ab9   Zhao Yakui   ACPI: Enable MSR ...
758
759
760
761
762
763
764
  {
  	printk(KERN_ERR PREFIX
  		"HARDWARE addr space,NOT supported yet
  ");
  	return -1;
  }
  #endif
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
765
  static int acpi_read_throttling_status(struct acpi_processor *pr,
439913fff   Lin Ming   ACPI: replace acp...
766
  					u64 *value)
01854e697   Luming Yu   ACPI: add ACPI 3....
767
  {
9bcb27217   Zhao Yakui   ACPI: Use _TSS fo...
768
  	u32 bit_width, bit_offset;
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
769
  	u64 ptc_value;
9bcb27217   Zhao Yakui   ACPI: Use _TSS fo...
770
  	u64 ptc_mask;
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
771
772
773
774
  	struct acpi_processor_throttling *throttling;
  	int ret = -1;
  
  	throttling = &pr->throttling;
01854e697   Luming Yu   ACPI: add ACPI 3....
775
776
  	switch (throttling->status_register.space_id) {
  	case ACPI_ADR_SPACE_SYSTEM_IO:
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
777
  		ptc_value = 0;
9bcb27217   Zhao Yakui   ACPI: Use _TSS fo...
778
779
  		bit_width = throttling->status_register.bit_width;
  		bit_offset = throttling->status_register.bit_offset;
ff55a9ceb   Len Brown   ACPI: Lindent pro...
780
  		acpi_os_read_port((acpi_io_address) throttling->status_register.
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
781
  				  address, (u32 *) &ptc_value,
9bcb27217   Zhao Yakui   ACPI: Use _TSS fo...
782
783
  				  (u32) (bit_width + bit_offset));
  		ptc_mask = (1 << bit_width) - 1;
439913fff   Lin Ming   ACPI: replace acp...
784
  		*value = (u64) ((ptc_value >> bit_offset) & ptc_mask);
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
785
  		ret = 0;
01854e697   Luming Yu   ACPI: add ACPI 3....
786
787
  		break;
  	case ACPI_ADR_SPACE_FIXED_HARDWARE:
9d42a53e0   Christoph Lameter   acpi throttling: ...
788
  		ret = acpi_throttling_rdmsr(value);
01854e697   Luming Yu   ACPI: add ACPI 3....
789
790
791
792
  		break;
  	default:
  		printk(KERN_ERR PREFIX "Unknown addr space %d
  ",
ff55a9ceb   Len Brown   ACPI: Lindent pro...
793
  		       (u32) (throttling->status_register.space_id));
01854e697   Luming Yu   ACPI: add ACPI 3....
794
  	}
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
795
  	return ret;
01854e697   Luming Yu   ACPI: add ACPI 3....
796
  }
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
797
  static int acpi_write_throttling_state(struct acpi_processor *pr,
439913fff   Lin Ming   ACPI: replace acp...
798
  				u64 value)
01854e697   Luming Yu   ACPI: add ACPI 3....
799
  {
9bcb27217   Zhao Yakui   ACPI: Use _TSS fo...
800
  	u32 bit_width, bit_offset;
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
801
  	u64 ptc_value;
9bcb27217   Zhao Yakui   ACPI: Use _TSS fo...
802
  	u64 ptc_mask;
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
803
  	struct acpi_processor_throttling *throttling;
01854e697   Luming Yu   ACPI: add ACPI 3....
804
  	int ret = -1;
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
805
  	throttling = &pr->throttling;
01854e697   Luming Yu   ACPI: add ACPI 3....
806
807
  	switch (throttling->control_register.space_id) {
  	case ACPI_ADR_SPACE_SYSTEM_IO:
9bcb27217   Zhao Yakui   ACPI: Use _TSS fo...
808
809
810
811
  		bit_width = throttling->control_register.bit_width;
  		bit_offset = throttling->control_register.bit_offset;
  		ptc_mask = (1 << bit_width) - 1;
  		ptc_value = value & ptc_mask;
ff55a9ceb   Len Brown   ACPI: Lindent pro...
812
  		acpi_os_write_port((acpi_io_address) throttling->
9bcb27217   Zhao Yakui   ACPI: Use _TSS fo...
813
814
815
  					control_register.address,
  					(u32) (ptc_value << bit_offset),
  					(u32) (bit_width + bit_offset));
01854e697   Luming Yu   ACPI: add ACPI 3....
816
817
818
  		ret = 0;
  		break;
  	case ACPI_ADR_SPACE_FIXED_HARDWARE:
9d42a53e0   Christoph Lameter   acpi throttling: ...
819
  		ret = acpi_throttling_wrmsr(value);
01854e697   Luming Yu   ACPI: add ACPI 3....
820
821
822
823
  		break;
  	default:
  		printk(KERN_ERR PREFIX "Unknown addr space %d
  ",
ff55a9ceb   Len Brown   ACPI: Lindent pro...
824
  		       (u32) (throttling->control_register.space_id));
01854e697   Luming Yu   ACPI: add ACPI 3....
825
826
827
  	}
  	return ret;
  }
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
828
  static int acpi_get_throttling_state(struct acpi_processor *pr,
439913fff   Lin Ming   ACPI: replace acp...
829
  				u64 value)
01854e697   Luming Yu   ACPI: add ACPI 3....
830
831
832
833
  {
  	int i;
  
  	for (i = 0; i < pr->throttling.state_count; i++) {
ff55a9ceb   Len Brown   ACPI: Lindent pro...
834
835
836
837
  		struct acpi_processor_tx_tss *tx =
  		    (struct acpi_processor_tx_tss *)&(pr->throttling.
  						      states_tss[i]);
  		if (tx->control == value)
53af9cfb3   Len Brown   ACPI: get_throttl...
838
  			return i;
01854e697   Luming Yu   ACPI: add ACPI 3....
839
  	}
53af9cfb3   Len Brown   ACPI: get_throttl...
840
  	return -1;
01854e697   Luming Yu   ACPI: add ACPI 3....
841
  }
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
842
  static int acpi_get_throttling_value(struct acpi_processor *pr,
439913fff   Lin Ming   ACPI: replace acp...
843
  			int state, u64 *value)
01854e697   Luming Yu   ACPI: add ACPI 3....
844
  {
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
845
  	int ret = -1;
ff55a9ceb   Len Brown   ACPI: Lindent pro...
846
847
848
849
  	if (state >= 0 && state <= pr->throttling.state_count) {
  		struct acpi_processor_tx_tss *tx =
  		    (struct acpi_processor_tx_tss *)&(pr->throttling.
  						      states_tss[state]);
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
850
851
  		*value = tx->control;
  		ret = 0;
01854e697   Luming Yu   ACPI: add ACPI 3....
852
  	}
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
853
  	return ret;
01854e697   Luming Yu   ACPI: add ACPI 3....
854
855
856
857
858
  }
  
  static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr)
  {
  	int state = 0;
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
859
  	int ret;
439913fff   Lin Ming   ACPI: replace acp...
860
  	u64 value;
01854e697   Luming Yu   ACPI: add ACPI 3....
861

01854e697   Luming Yu   ACPI: add ACPI 3....
862
863
864
865
866
867
868
  	if (!pr)
  		return -EINVAL;
  
  	if (!pr->flags.throttling)
  		return -ENODEV;
  
  	pr->throttling.state = 0;
357dc4c3f   Zhao Yakui   ACPI: Delete the ...
869

0753f6e0a   Zhao Yakui   ACPI: throttle: C...
870
871
872
  	value = 0;
  	ret = acpi_read_throttling_status(pr, &value);
  	if (ret >= 0) {
ff55a9ceb   Len Brown   ACPI: Lindent pro...
873
  		state = acpi_get_throttling_state(pr, value);
4973b22aa   Zhang Rui   ACPI processor: r...
874
  		if (state == -1) {
bdf57de4e   Frans Pop   acpi processor: r...
875
876
877
  			ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  				"Invalid throttling state, reset
  "));
4973b22aa   Zhang Rui   ACPI processor: r...
878
  			state = 0;
2a908002c   Frans Pop   ACPI processor: f...
879
  			ret = acpi_processor_set_throttling(pr, state, true);
4973b22aa   Zhang Rui   ACPI processor: r...
880
881
882
  			if (ret)
  				return ret;
  		}
01854e697   Luming Yu   ACPI: add ACPI 3....
883
884
  		pr->throttling.state = state;
  	}
01854e697   Luming Yu   ACPI: add ACPI 3....
885
886
887
  
  	return 0;
  }
01854e697   Luming Yu   ACPI: add ACPI 3....
888
889
  static int acpi_processor_get_throttling(struct acpi_processor *pr)
  {
2fdf66b49   Rusty Russell   cpumask: convert ...
890
  	cpumask_var_t saved_mask;
357dc4c3f   Zhao Yakui   ACPI: Delete the ...
891
  	int ret;
87654273e   Zhao Yakui   ACPI : Check para...
892
893
894
895
896
  	if (!pr)
  		return -EINVAL;
  
  	if (!pr->flags.throttling)
  		return -ENODEV;
2fdf66b49   Rusty Russell   cpumask: convert ...
897
898
899
  
  	if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL))
  		return -ENOMEM;
357dc4c3f   Zhao Yakui   ACPI: Delete the ...
900
901
902
  	/*
  	 * Migrate task to the cpu pointed by pr.
  	 */
2fdf66b49   Rusty Russell   cpumask: convert ...
903
904
  	cpumask_copy(saved_mask, &current->cpus_allowed);
  	/* FIXME: use work_on_cpu() */
daef1f35e   Zhao Yakui   ACPI: Check the r...
905
906
907
908
909
  	if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) {
  		/* Can't migrate to the target pr->id CPU. Exit */
  		free_cpumask_var(saved_mask);
  		return -ENODEV;
  	}
357dc4c3f   Zhao Yakui   ACPI: Delete the ...
910
911
  	ret = pr->throttling.acpi_processor_get_throttling(pr);
  	/* restore the previous state */
2fdf66b49   Rusty Russell   cpumask: convert ...
912
913
  	set_cpus_allowed_ptr(current, saved_mask);
  	free_cpumask_var(saved_mask);
357dc4c3f   Zhao Yakui   ACPI: Delete the ...
914
915
  
  	return ret;
01854e697   Luming Yu   ACPI: add ACPI 3....
916
  }
22cc50199   Zhao Yakui   ACPI: If _TSS exi...
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
  static int acpi_processor_get_fadt_info(struct acpi_processor *pr)
  {
  	int i, step;
  
  	if (!pr->throttling.address) {
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling register
  "));
  		return -EINVAL;
  	} else if (!pr->throttling.duty_width) {
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No throttling states
  "));
  		return -EINVAL;
  	}
  	/* TBD: Support duty_cycle values that span bit 4. */
  	else if ((pr->throttling.duty_offset + pr->throttling.duty_width) > 4) {
  		printk(KERN_WARNING PREFIX "duty_cycle spans bit 4
  ");
  		return -EINVAL;
  	}
  
  	pr->throttling.state_count = 1 << acpi_gbl_FADT.duty_width;
  
  	/*
  	 * Compute state values. Note that throttling displays a linear power
  	 * performance relationship (at 50% performance the CPU will consume
  	 * 50% power).  Values are in 1/10th of a percent to preserve accuracy.
  	 */
  
  	step = (1000 / pr->throttling.state_count);
  
  	for (i = 0; i < pr->throttling.state_count; i++) {
  		pr->throttling.states[i].performance = 1000 - step * i;
  		pr->throttling.states[i].power = 1000 - step * i;
  	}
  	return 0;
  }
6c5cf8aa5   Adrian Bunk   ACPI: static
953
  static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr,
2a908002c   Frans Pop   ACPI processor: f...
954
  					      int state, bool force)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
955
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
956
957
958
  	u32 value = 0;
  	u32 duty_mask = 0;
  	u32 duty_value = 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
959

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
960
  	if (!pr)
d550d98d3   Patrick Mochel   ACPI: delete trac...
961
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
962
963
  
  	if ((state < 0) || (state > (pr->throttling.state_count - 1)))
d550d98d3   Patrick Mochel   ACPI: delete trac...
964
  		return -EINVAL;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
965
966
  
  	if (!pr->flags.throttling)
d550d98d3   Patrick Mochel   ACPI: delete trac...
967
  		return -ENODEV;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
968

2a908002c   Frans Pop   ACPI processor: f...
969
  	if (!force && (state == pr->throttling.state))
d550d98d3   Patrick Mochel   ACPI: delete trac...
970
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
971

01854e697   Luming Yu   ACPI: add ACPI 3....
972
973
  	if (state < pr->throttling_platform_limit)
  		return -EPERM;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
974
975
976
977
978
979
980
981
982
983
  	/*
  	 * Calculate the duty_value and duty_mask.
  	 */
  	if (state) {
  		duty_value = pr->throttling.state_count - state;
  
  		duty_value <<= pr->throttling.duty_offset;
  
  		/* Used to clear all duty_value bits */
  		duty_mask = pr->throttling.state_count - 1;
cee324b14   Alexey Starikovskiy   ACPICA: use new A...
984
  		duty_mask <<= acpi_gbl_FADT.duty_offset;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
  		duty_mask = ~duty_mask;
  	}
  
  	local_irq_disable();
  
  	/*
  	 * Disable throttling by writing a 0 to bit 4.  Note that we must
  	 * turn it off before you can change the duty_value.
  	 */
  	value = inl(pr->throttling.address);
  	if (value & 0x10) {
  		value &= 0xFFFFFFEF;
  		outl(value, pr->throttling.address);
  	}
  
  	/*
  	 * Write the new duty_value and then enable throttling.  Note
  	 * that a state value of 0 leaves throttling disabled.
  	 */
  	if (state) {
  		value &= duty_mask;
  		value |= duty_value;
  		outl(value, pr->throttling.address);
  
  		value |= 0x00000010;
  		outl(value, pr->throttling.address);
  	}
  
  	pr->throttling.state = state;
  
  	local_irq_enable();
  
  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd3   Len Brown   [ACPI] Lindent al...
1018
1019
1020
1021
  			  "Throttling state set to T%d (%d%%)
  ", state,
  			  (pr->throttling.states[state].performance ? pr->
  			   throttling.states[state].performance / 10 : 0)));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1022

d550d98d3   Patrick Mochel   ACPI: delete trac...
1023
  	return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1024
  }
6c5cf8aa5   Adrian Bunk   ACPI: static
1025
  static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr,
2a908002c   Frans Pop   ACPI processor: f...
1026
  					     int state, bool force)
01854e697   Luming Yu   ACPI: add ACPI 3....
1027
  {
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
1028
  	int ret;
439913fff   Lin Ming   ACPI: replace acp...
1029
  	u64 value;
01854e697   Luming Yu   ACPI: add ACPI 3....
1030
1031
1032
1033
1034
1035
1036
1037
1038
  
  	if (!pr)
  		return -EINVAL;
  
  	if ((state < 0) || (state > (pr->throttling.state_count - 1)))
  		return -EINVAL;
  
  	if (!pr->flags.throttling)
  		return -ENODEV;
2a908002c   Frans Pop   ACPI processor: f...
1039
  	if (!force && (state == pr->throttling.state))
01854e697   Luming Yu   ACPI: add ACPI 3....
1040
1041
1042
1043
  		return 0;
  
  	if (state < pr->throttling_platform_limit)
  		return -EPERM;
0753f6e0a   Zhao Yakui   ACPI: throttle: C...
1044
1045
1046
1047
  	value = 0;
  	ret = acpi_get_throttling_value(pr, state, &value);
  	if (ret >= 0) {
  		acpi_write_throttling_state(pr, value);
01854e697   Luming Yu   ACPI: add ACPI 3....
1048
1049
  		pr->throttling.state = state;
  	}
01854e697   Luming Yu   ACPI: add ACPI 3....
1050
1051
1052
  
  	return 0;
  }
2a908002c   Frans Pop   ACPI processor: f...
1053
1054
  int acpi_processor_set_throttling(struct acpi_processor *pr,
  						int state, bool force)
01854e697   Luming Yu   ACPI: add ACPI 3....
1055
  {
2fdf66b49   Rusty Russell   cpumask: convert ...
1056
  	cpumask_var_t saved_mask;
3391a76f2   Len Brown   ACPI: throttling:...
1057
  	int ret = 0;
33a2a529f   Zhao Yakui   ACPI: Update the ...
1058
1059
1060
1061
  	unsigned int i;
  	struct acpi_processor *match_pr;
  	struct acpi_processor_throttling *p_throttling;
  	struct throttling_tstate t_state;
2fdf66b49   Rusty Russell   cpumask: convert ...
1062
  	cpumask_var_t online_throttling_cpus;
87654273e   Zhao Yakui   ACPI : Check para...
1063
1064
1065
1066
1067
1068
1069
1070
1071
  
  	if (!pr)
  		return -EINVAL;
  
  	if (!pr->flags.throttling)
  		return -ENODEV;
  
  	if ((state < 0) || (state > (pr->throttling.state_count - 1)))
  		return -EINVAL;
2fdf66b49   Rusty Russell   cpumask: convert ...
1072
1073
1074
1075
1076
1077
1078
  	if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL))
  		return -ENOMEM;
  
  	if (!alloc_cpumask_var(&online_throttling_cpus, GFP_KERNEL)) {
  		free_cpumask_var(saved_mask);
  		return -ENOMEM;
  	}
daef1f35e   Zhao Yakui   ACPI: Check the r...
1079
1080
1081
1082
1083
1084
1085
  	if (cpu_is_offline(pr->id)) {
  		/*
  		 * the cpu pointed by pr->id is offline. Unnecessary to change
  		 * the throttling state any more.
  		 */
  		return -ENODEV;
  	}
2fdf66b49   Rusty Russell   cpumask: convert ...
1086
  	cpumask_copy(saved_mask, &current->cpus_allowed);
33a2a529f   Zhao Yakui   ACPI: Update the ...
1087
1088
  	t_state.target_state = state;
  	p_throttling = &(pr->throttling);
2fdf66b49   Rusty Russell   cpumask: convert ...
1089
1090
  	cpumask_and(online_throttling_cpus, cpu_online_mask,
  		    p_throttling->shared_cpu_map);
357dc4c3f   Zhao Yakui   ACPI: Delete the ...
1091
  	/*
33a2a529f   Zhao Yakui   ACPI: Update the ...
1092
1093
1094
  	 * The throttling notifier will be called for every
  	 * affected cpu in order to get one proper T-state.
  	 * The notifier event is THROTTLING_PRECHANGE.
357dc4c3f   Zhao Yakui   ACPI: Delete the ...
1095
  	 */
2fdf66b49   Rusty Russell   cpumask: convert ...
1096
  	for_each_cpu(i, online_throttling_cpus) {
33a2a529f   Zhao Yakui   ACPI: Update the ...
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
  		t_state.cpu = i;
  		acpi_processor_throttling_notifier(THROTTLING_PRECHANGE,
  							&t_state);
  	}
  	/*
  	 * The function of acpi_processor_set_throttling will be called
  	 * to switch T-state. If the coordination type is SW_ALL or HW_ALL,
  	 * it is necessary to call it for every affected cpu. Otherwise
  	 * it can be called only for the cpu pointed by pr.
  	 */
  	if (p_throttling->shared_type == DOMAIN_COORD_TYPE_SW_ANY) {
2fdf66b49   Rusty Russell   cpumask: convert ...
1108
  		/* FIXME: use work_on_cpu() */
daef1f35e   Zhao Yakui   ACPI: Check the r...
1109
1110
1111
1112
1113
  		if (set_cpus_allowed_ptr(current, cpumask_of(pr->id))) {
  			/* Can't migrate to the pr->id CPU. Exit */
  			ret = -ENODEV;
  			goto exit;
  		}
33a2a529f   Zhao Yakui   ACPI: Update the ...
1114
  		ret = p_throttling->acpi_processor_set_throttling(pr,
2a908002c   Frans Pop   ACPI processor: f...
1115
  						t_state.target_state, force);
33a2a529f   Zhao Yakui   ACPI: Update the ...
1116
1117
1118
1119
1120
1121
  	} else {
  		/*
  		 * When the T-state coordination is SW_ALL or HW_ALL,
  		 * it is necessary to set T-state for every affected
  		 * cpus.
  		 */
2fdf66b49   Rusty Russell   cpumask: convert ...
1122
  		for_each_cpu(i, online_throttling_cpus) {
706546d02   Mike Travis   ACPI: change proc...
1123
  			match_pr = per_cpu(processors, i);
33a2a529f   Zhao Yakui   ACPI: Update the ...
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
  			/*
  			 * If the pointer is invalid, we will report the
  			 * error message and continue.
  			 */
  			if (!match_pr) {
  				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  					"Invalid Pointer for CPU %d
  ", i));
  				continue;
  			}
  			/*
  			 * If the throttling control is unsupported on CPU i,
  			 * we will report the error message and continue.
  			 */
  			if (!match_pr->flags.throttling) {
  				ACPI_DEBUG_PRINT((ACPI_DB_INFO,
25985edce   Lucas De Marchi   Fix common misspe...
1140
  					"Throttling Control is unsupported "
33a2a529f   Zhao Yakui   ACPI: Update the ...
1141
1142
1143
1144
1145
  					"on CPU %d
  ", i));
  				continue;
  			}
  			t_state.cpu = i;
2fdf66b49   Rusty Russell   cpumask: convert ...
1146
  			/* FIXME: use work_on_cpu() */
daef1f35e   Zhao Yakui   ACPI: Check the r...
1147
1148
  			if (set_cpus_allowed_ptr(current, cpumask_of(i)))
  				continue;
33a2a529f   Zhao Yakui   ACPI: Update the ...
1149
1150
  			ret = match_pr->throttling.
  				acpi_processor_set_throttling(
2a908002c   Frans Pop   ACPI processor: f...
1151
  				match_pr, t_state.target_state, force);
33a2a529f   Zhao Yakui   ACPI: Update the ...
1152
1153
1154
1155
1156
1157
1158
1159
  		}
  	}
  	/*
  	 * After the set_throttling is called, the
  	 * throttling notifier is called for every
  	 * affected cpu to update the T-states.
  	 * The notifier event is THROTTLING_POSTCHANGE
  	 */
2fdf66b49   Rusty Russell   cpumask: convert ...
1160
  	for_each_cpu(i, online_throttling_cpus) {
33a2a529f   Zhao Yakui   ACPI: Update the ...
1161
1162
1163
1164
  		t_state.cpu = i;
  		acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE,
  							&t_state);
  	}
357dc4c3f   Zhao Yakui   ACPI: Delete the ...
1165
  	/* restore the previous state */
2fdf66b49   Rusty Russell   cpumask: convert ...
1166
1167
  	/* FIXME: use work_on_cpu() */
  	set_cpus_allowed_ptr(current, saved_mask);
daef1f35e   Zhao Yakui   ACPI: Check the r...
1168
  exit:
2fdf66b49   Rusty Russell   cpumask: convert ...
1169
1170
  	free_cpumask_var(online_throttling_cpus);
  	free_cpumask_var(saved_mask);
357dc4c3f   Zhao Yakui   ACPI: Delete the ...
1171
  	return ret;
01854e697   Luming Yu   ACPI: add ACPI 3....
1172
  }
4be44fcd3   Len Brown   [ACPI] Lindent al...
1173
  int acpi_processor_get_throttling_info(struct acpi_processor *pr)
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1174
  {
4be44fcd3   Len Brown   [ACPI] Lindent al...
1175
  	int result = 0;
1180509f6   Zhao Yakui   ACPI : Update T-s...
1176
  	struct acpi_processor_throttling *pthrottling;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1177

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1178
  	ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd3   Len Brown   [ACPI] Lindent al...
1179
1180
1181
1182
1183
  			  "pblk_address[0x%08x] duty_offset[%d] duty_width[%d]
  ",
  			  pr->throttling.address,
  			  pr->throttling.duty_offset,
  			  pr->throttling.duty_width));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1184

c30c620ee   Len Brown   ACPI: quiet ACPI ...
1185
1186
1187
1188
1189
1190
1191
1192
  	/*
  	 * Evaluate _PTC, _TSS and _TPC
  	 * They must all be present or none of them can be used.
  	 */
  	if (acpi_processor_get_throttling_control(pr) ||
  		acpi_processor_get_throttling_states(pr) ||
  		acpi_processor_get_platform_limit(pr))
  	{
ff55a9ceb   Len Brown   ACPI: Lindent pro...
1193
1194
1195
1196
  		pr->throttling.acpi_processor_get_throttling =
  		    &acpi_processor_get_throttling_fadt;
  		pr->throttling.acpi_processor_set_throttling =
  		    &acpi_processor_set_throttling_fadt;
d1154be30   Alexey Starikovskiy   ACPI: processor: ...
1197
1198
  		if (acpi_processor_get_fadt_info(pr))
  			return 0;
01854e697   Luming Yu   ACPI: add ACPI 3....
1199
  	} else {
ff55a9ceb   Len Brown   ACPI: Lindent pro...
1200
1201
1202
1203
  		pr->throttling.acpi_processor_get_throttling =
  		    &acpi_processor_get_throttling_ptc;
  		pr->throttling.acpi_processor_set_throttling =
  		    &acpi_processor_set_throttling_ptc;
01854e697   Luming Yu   ACPI: add ACPI 3....
1204
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1205

1180509f6   Zhao Yakui   ACPI : Update T-s...
1206
1207
1208
1209
1210
1211
1212
  	/*
  	 * If TSD package for one CPU can't be parsed successfully, it means
  	 * that this CPU will have no coordination with other CPUs.
  	 */
  	if (acpi_processor_get_tsd(pr)) {
  		pthrottling = &pr->throttling;
  		pthrottling->tsd_valid_flag = 0;
2fdf66b49   Rusty Russell   cpumask: convert ...
1213
  		cpumask_set_cpu(pr->id, pthrottling->shared_cpu_map);
1180509f6   Zhao Yakui   ACPI : Update T-s...
1214
1215
  		pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL;
  	}
c30c620ee   Len Brown   ACPI: quiet ACPI ...
1216

1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1217
1218
1219
1220
1221
1222
1223
  	/*
  	 * PIIX4 Errata: We don't support throttling on the original PIIX4.
  	 * This shouldn't be an issue as few (if any) mobile systems ever
  	 * used this part.
  	 */
  	if (errata.piix4.throttle) {
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
4be44fcd3   Len Brown   [ACPI] Lindent al...
1224
1225
  				  "Throttling not supported on PIIX4 A- or B-step
  "));
d550d98d3   Patrick Mochel   ACPI: delete trac...
1226
  		return 0;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1227
  	}
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1228
1229
  	ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states
  ",
4be44fcd3   Len Brown   [ACPI] Lindent al...
1230
  			  pr->throttling.state_count));
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
  
  	pr->flags.throttling = 1;
  
  	/*
  	 * Disable throttling (if enabled).  We'll let subsequent policy (e.g.
  	 * thermal) decide to lower performance if it so chooses, but for now
  	 * we'll crank up the speed.
  	 */
  
  	result = acpi_processor_get_throttling(pr);
  	if (result)
  		goto end;
  
  	if (pr->throttling.state) {
4be44fcd3   Len Brown   [ACPI] Lindent al...
1245
1246
1247
1248
  		ACPI_DEBUG_PRINT((ACPI_DB_INFO,
  				  "Disabling throttling (was T%d)
  ",
  				  pr->throttling.state));
2a908002c   Frans Pop   ACPI processor: f...
1249
  		result = acpi_processor_set_throttling(pr, 0, false);
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1250
1251
1252
  		if (result)
  			goto end;
  	}
4be44fcd3   Len Brown   [ACPI] Lindent al...
1253
        end:
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1254
1255
  	if (result)
  		pr->flags.throttling = 0;
d550d98d3   Patrick Mochel   ACPI: delete trac...
1256
  	return result;
1da177e4c   Linus Torvalds   Linux-2.6.12-rc2
1257
  }