Blame view
drivers/acpi/processor_throttling.c
31.6 KB
1da177e4c 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 include cleanup: ... |
31 |
#include <linux/slab.h> |
1da177e4c Linux-2.6.12-rc2 |
32 |
#include <linux/init.h> |
357dc4c3f ACPI: Delete the ... |
33 |
#include <linux/sched.h> |
1da177e4c Linux-2.6.12-rc2 |
34 |
#include <linux/cpufreq.h> |
1da177e4c Linux-2.6.12-rc2 |
35 36 37 38 39 |
#include <asm/io.h> #include <asm/uaccess.h> #include <acpi/acpi_bus.h> |
89595b8f2 ACPI: consolidate... |
40 |
#include <acpi/acpi_drivers.h> |
1da177e4c Linux-2.6.12-rc2 |
41 |
#include <acpi/processor.h> |
a192a9580 ACPI: Move defini... |
42 |
#define PREFIX "ACPI: " |
1da177e4c Linux-2.6.12-rc2 |
43 |
#define ACPI_PROCESSOR_CLASS "processor" |
1da177e4c Linux-2.6.12-rc2 |
44 |
#define _COMPONENT ACPI_PROCESSOR_COMPONENT |
f52fd66d2 ACPI: clean up AC... |
45 |
ACPI_MODULE_NAME("processor_throttling"); |
1da177e4c Linux-2.6.12-rc2 |
46 |
|
56c213fa0 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 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 ACPI: Lindent pro... |
61 |
static int acpi_processor_get_throttling(struct acpi_processor *pr); |
2a908002c ACPI processor: f... |
62 63 |
int acpi_processor_set_throttling(struct acpi_processor *pr, int state, bool force); |
01854e697 ACPI: add ACPI 3.... |
64 |
|
1180509f6 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 cpumask: convert ... |
70 |
cpumask_var_t covered_cpus; |
1180509f6 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 cpumask: use zall... |
74 |
if (!zalloc_cpumask_var(&covered_cpus, GFP_KERNEL)) |
2fdf66b49 cpumask: convert ... |
75 |
return -ENOMEM; |
1180509f6 ACPI : Update T-s... |
76 77 |
/* * Now that we have _TSD data from all CPUs, lets setup T-state |
33a2a529f ACPI: Update the ... |
78 |
* coordination between all CPUs. |
1180509f6 ACPI : Update T-s... |
79 80 |
*/ for_each_possible_cpu(i) { |
706546d02 ACPI: change proc... |
81 |
pr = per_cpu(processors, i); |
1180509f6 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 ACPI : Update T-s... |
100 |
for_each_possible_cpu(i) { |
706546d02 ACPI: change proc... |
101 |
pr = per_cpu(processors, i); |
1180509f6 ACPI : Update T-s... |
102 103 |
if (!pr) continue; |
2fdf66b49 cpumask: convert ... |
104 |
if (cpumask_test_cpu(i, covered_cpus)) |
1180509f6 ACPI : Update T-s... |
105 106 107 108 |
continue; pthrottling = &pr->throttling; pdomain = &(pthrottling->domain_info); |
2fdf66b49 cpumask: convert ... |
109 110 |
cpumask_set_cpu(i, pthrottling->shared_cpu_map); cpumask_set_cpu(i, covered_cpus); |
1180509f6 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 ACPI: change proc... |
125 |
match_pr = per_cpu(processors, j); |
1180509f6 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 cpumask: convert ... |
149 150 |
cpumask_set_cpu(j, covered_cpus); cpumask_set_cpu(j, pthrottling->shared_cpu_map); |
1180509f6 ACPI : Update T-s... |
151 152 153 154 155 |
count++; } for_each_possible_cpu(j) { if (i == j) continue; |
706546d02 ACPI: change proc... |
156 |
match_pr = per_cpu(processors, j); |
1180509f6 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 cpumask: convert ... |
169 170 |
cpumask_copy(match_pthrottling->shared_cpu_map, pthrottling->shared_cpu_map); |
1180509f6 ACPI : Update T-s... |
171 172 173 174 |
} } err_ret: |
2fdf66b49 cpumask: convert ... |
175 |
free_cpumask_var(covered_cpus); |
1180509f6 ACPI : Update T-s... |
176 |
for_each_possible_cpu(i) { |
706546d02 ACPI: change proc... |
177 |
pr = per_cpu(processors, i); |
1180509f6 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 cpumask: convert ... |
187 188 |
cpumask_clear(pthrottling->shared_cpu_map); cpumask_set_cpu(i, pthrottling->shared_cpu_map); |
1180509f6 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 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 ACPI: change proc... |
219 |
pr = per_cpu(processors, cpu); |
e4aa5cb21 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 ACPI: quiet ACPI ... |
278 279 280 |
/* * _TPC - Throttling Present Capabilities */ |
01854e697 ACPI: add ACPI 3.... |
281 282 283 |
static int acpi_processor_get_platform_limit(struct acpi_processor *pr) { acpi_status status = 0; |
27663c585 ACPI: Change acpi... |
284 |
unsigned long long tpc = 0; |
01854e697 ACPI: add ACPI 3.... |
285 |
|
ff55a9ceb ACPI: Lindent pro... |
286 |
if (!pr) |
01854e697 ACPI: add ACPI 3.... |
287 |
return -EINVAL; |
56c213fa0 ACPI processor: i... |
288 289 290 |
if (ignore_tpc) goto end; |
01854e697 ACPI: add ACPI 3.... |
291 |
status = acpi_evaluate_integer(pr->handle, "_TPC", NULL, &tpc); |
c30c620ee ACPI: quiet ACPI ... |
292 293 294 295 |
if (ACPI_FAILURE(status)) { if (status != AE_NOT_FOUND) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TPC")); } |
01854e697 ACPI: add ACPI 3.... |
296 297 |
return -ENODEV; } |
56c213fa0 ACPI processor: i... |
298 299 |
end: |
01854e697 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 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 ACPI processor: i... |
311 312 |
if (ignore_tpc) return 0; |
ef54d5ad2 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 ACPI processor: f... |
355 |
return acpi_processor_set_throttling(pr, target_state, false); |
01854e697 ACPI: add ACPI 3.... |
356 |
} |
c30c620ee ACPI: quiet ACPI ... |
357 |
/* |
5a344a505 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 ACPI: quiet ACPI ... |
410 411 |
* _PTC - Processor Throttling Control (and status) register location */ |
01854e697 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 ACPI: Use _TSS fo... |
419 |
struct acpi_processor_throttling *throttling; |
01854e697 ACPI: add ACPI 3.... |
420 421 422 |
status = acpi_evaluate_object(pr->handle, "_PTC", NULL, &buffer); if (ACPI_FAILURE(status)) { |
c30c620ee ACPI: quiet ACPI ... |
423 424 425 |
if (status != AE_NOT_FOUND) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PTC")); } |
01854e697 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 ACPI: Lindent pro... |
447 448 449 |
printk(KERN_ERR PREFIX "Invalid _PTC data (control_register) "); |
01854e697 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 ACPI: Lindent pro... |
472 |
sizeof(struct acpi_ptc_register)); |
01854e697 ACPI: add ACPI 3.... |
473 |
|
9bcb27217 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 ACPI: Lindent pro... |
491 |
end: |
01854e697 ACPI: add ACPI 3.... |
492 493 494 495 |
kfree(buffer.pointer); return result; } |
c30c620ee ACPI: quiet ACPI ... |
496 497 498 499 |
/* * _TSS - Throttling Supported States */ |
01854e697 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 ACPI: quiet ACPI ... |
512 513 514 |
if (status != AE_NOT_FOUND) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TSS")); } |
01854e697 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 ACPI: Lindent pro... |
540 541 542 |
struct acpi_processor_tx_tss *tx = (struct acpi_processor_tx_tss *)&(pr->throttling. states_tss[i]); |
01854e697 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 ACPI: Lindent pro... |
561 562 |
"Invalid _TSS data: freq is zero "); |
01854e697 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 ACPI: quiet ACPI ... |
574 575 576 577 |
/* * _TSD - T-State Dependencies */ |
ff55a9ceb ACPI: Lindent pro... |
578 |
static int acpi_processor_get_tsd(struct acpi_processor *pr) |
01854e697 ACPI: add ACPI 3.... |
579 580 581 |
{ int result = 0; acpi_status status = AE_OK; |
ff55a9ceb 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 ACPI: add ACPI 3.... |
586 |
struct acpi_tsd_package *pdomain; |
1180509f6 ACPI : Update T-s... |
587 588 589 590 |
struct acpi_processor_throttling *pthrottling; pthrottling = &pr->throttling; pthrottling->tsd_valid_flag = 0; |
01854e697 ACPI: add ACPI 3.... |
591 592 593 |
status = acpi_evaluate_object(pr->handle, "_TSD", NULL, &buffer); if (ACPI_FAILURE(status)) { |
c30c620ee ACPI: quiet ACPI ... |
594 595 596 |
if (status != AE_NOT_FOUND) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _TSD")); } |
01854e697 ACPI: add ACPI 3.... |
597 598 599 600 601 |
return -ENODEV; } tsd = buffer.pointer; if (!tsd || (tsd->type != ACPI_TYPE_PACKAGE)) { |
55ac9a018 ACPI: replace ACP... |
602 603 |
printk(KERN_ERR PREFIX "Invalid _TSD data "); |
01854e697 ACPI: add ACPI 3.... |
604 605 606 607 608 |
result = -EFAULT; goto end; } if (tsd->package.count != 1) { |
55ac9a018 ACPI: replace ACP... |
609 610 |
printk(KERN_ERR PREFIX "Invalid _TSD data "); |
01854e697 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 ACPI: Lindent pro... |
621 |
&format, &state); |
01854e697 ACPI: add ACPI 3.... |
622 |
if (ACPI_FAILURE(status)) { |
55ac9a018 ACPI: replace ACP... |
623 624 |
printk(KERN_ERR PREFIX "Invalid _TSD data "); |
01854e697 ACPI: add ACPI 3.... |
625 626 627 628 629 |
result = -EFAULT; goto end; } if (pdomain->num_entries != ACPI_TSD_REV0_ENTRIES) { |
55ac9a018 ACPI: replace ACP... |
630 631 |
printk(KERN_ERR PREFIX "Unknown _TSD:num_entries "); |
01854e697 ACPI: add ACPI 3.... |
632 633 634 635 636 |
result = -EFAULT; goto end; } if (pdomain->revision != ACPI_TSD_REV0_REVISION) { |
55ac9a018 ACPI: replace ACP... |
637 638 |
printk(KERN_ERR PREFIX "Unknown _TSD:revision "); |
01854e697 ACPI: add ACPI 3.... |
639 640 641 |
result = -EFAULT; goto end; } |
1180509f6 ACPI : Update T-s... |
642 643 644 |
pthrottling = &pr->throttling; pthrottling->tsd_valid_flag = 1; pthrottling->shared_type = pdomain->coord_type; |
2fdf66b49 cpumask: convert ... |
645 |
cpumask_set_cpu(pr->id, pthrottling->shared_cpu_map); |
1180509f6 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 ACPI: Lindent pro... |
657 |
end: |
01854e697 ACPI: add ACPI 3.... |
658 659 660 |
kfree(buffer.pointer); return result; } |
1da177e4c Linux-2.6.12-rc2 |
661 662 663 |
/* -------------------------------------------------------------------------- Throttling Control -------------------------------------------------------------------------- */ |
01854e697 ACPI: add ACPI 3.... |
664 |
static int acpi_processor_get_throttling_fadt(struct acpi_processor *pr) |
1da177e4c Linux-2.6.12-rc2 |
665 |
{ |
4be44fcd3 [ACPI] Lindent al... |
666 667 668 669 |
int state = 0; u32 value = 0; u32 duty_mask = 0; u32 duty_value = 0; |
1da177e4c Linux-2.6.12-rc2 |
670 |
|
1da177e4c Linux-2.6.12-rc2 |
671 |
if (!pr) |
d550d98d3 ACPI: delete trac... |
672 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
673 674 |
if (!pr->flags.throttling) |
d550d98d3 ACPI: delete trac... |
675 |
return -ENODEV; |
1da177e4c 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 [ACPI] Lindent al... |
696 |
state = pr->throttling.state_count - duty_value; |
1da177e4c 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 [ACPI] Lindent al... |
704 705 706 |
"Throttling state is T%d (%d%% throttling applied) ", state, pr->throttling.states[state].performance)); |
1da177e4c Linux-2.6.12-rc2 |
707 |
|
d550d98d3 ACPI: delete trac... |
708 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
709 |
} |
f79f06ab9 ACPI: Enable MSR ... |
710 |
#ifdef CONFIG_X86 |
9d42a53e0 acpi throttling: ... |
711 |
static int acpi_throttling_rdmsr(u64 *value) |
f79f06ab9 ACPI: Enable MSR ... |
712 |
{ |
f79f06ab9 ACPI: Enable MSR ... |
713 |
u64 msr_high, msr_low; |
f79f06ab9 ACPI: Enable MSR ... |
714 715 |
u64 msr = 0; int ret = -1; |
9d42a53e0 acpi throttling: ... |
716 717 |
if ((this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_INTEL) || !this_cpu_has(X86_FEATURE_ACPI)) { |
f79f06ab9 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 ACPI: Delete the ... |
724 |
rdmsr_safe(MSR_IA32_THERM_CONTROL, |
f79f06ab9 ACPI: Enable MSR ... |
725 726 |
(u32 *)&msr_low , (u32 *) &msr_high); msr = (msr_high << 32) | msr_low; |
439913fff ACPI: replace acp... |
727 |
*value = (u64) msr; |
f79f06ab9 ACPI: Enable MSR ... |
728 729 730 731 |
ret = 0; } return ret; } |
9d42a53e0 acpi throttling: ... |
732 |
static int acpi_throttling_wrmsr(u64 value) |
f79f06ab9 ACPI: Enable MSR ... |
733 |
{ |
f79f06ab9 ACPI: Enable MSR ... |
734 735 |
int ret = -1; u64 msr; |
9d42a53e0 acpi throttling: ... |
736 737 |
if ((this_cpu_read(cpu_info.x86_vendor) != X86_VENDOR_INTEL) || !this_cpu_has(X86_FEATURE_ACPI)) { |
f79f06ab9 ACPI: Enable MSR ... |
738 739 740 741 742 |
printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet "); } else { msr = value; |
357dc4c3f ACPI: Delete the ... |
743 |
wrmsr_safe(MSR_IA32_THERM_CONTROL, |
f79f06ab9 ACPI: Enable MSR ... |
744 745 746 747 748 749 |
msr & 0xffffffff, msr >> 32); ret = 0; } return ret; } #else |
9d42a53e0 acpi throttling: ... |
750 |
static int acpi_throttling_rdmsr(u64 *value) |
f79f06ab9 ACPI: Enable MSR ... |
751 752 753 754 755 756 |
{ printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet "); return -1; } |
9d42a53e0 acpi throttling: ... |
757 |
static int acpi_throttling_wrmsr(u64 value) |
f79f06ab9 ACPI: Enable MSR ... |
758 759 760 761 762 763 764 |
{ printk(KERN_ERR PREFIX "HARDWARE addr space,NOT supported yet "); return -1; } #endif |
0753f6e0a ACPI: throttle: C... |
765 |
static int acpi_read_throttling_status(struct acpi_processor *pr, |
439913fff ACPI: replace acp... |
766 |
u64 *value) |
01854e697 ACPI: add ACPI 3.... |
767 |
{ |
9bcb27217 ACPI: Use _TSS fo... |
768 |
u32 bit_width, bit_offset; |
0753f6e0a ACPI: throttle: C... |
769 |
u64 ptc_value; |
9bcb27217 ACPI: Use _TSS fo... |
770 |
u64 ptc_mask; |
0753f6e0a ACPI: throttle: C... |
771 772 773 774 |
struct acpi_processor_throttling *throttling; int ret = -1; throttling = &pr->throttling; |
01854e697 ACPI: add ACPI 3.... |
775 776 |
switch (throttling->status_register.space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: |
0753f6e0a ACPI: throttle: C... |
777 |
ptc_value = 0; |
9bcb27217 ACPI: Use _TSS fo... |
778 779 |
bit_width = throttling->status_register.bit_width; bit_offset = throttling->status_register.bit_offset; |
ff55a9ceb ACPI: Lindent pro... |
780 |
acpi_os_read_port((acpi_io_address) throttling->status_register. |
0753f6e0a ACPI: throttle: C... |
781 |
address, (u32 *) &ptc_value, |
9bcb27217 ACPI: Use _TSS fo... |
782 783 |
(u32) (bit_width + bit_offset)); ptc_mask = (1 << bit_width) - 1; |
439913fff ACPI: replace acp... |
784 |
*value = (u64) ((ptc_value >> bit_offset) & ptc_mask); |
0753f6e0a ACPI: throttle: C... |
785 |
ret = 0; |
01854e697 ACPI: add ACPI 3.... |
786 787 |
break; case ACPI_ADR_SPACE_FIXED_HARDWARE: |
9d42a53e0 acpi throttling: ... |
788 |
ret = acpi_throttling_rdmsr(value); |
01854e697 ACPI: add ACPI 3.... |
789 790 791 792 |
break; default: printk(KERN_ERR PREFIX "Unknown addr space %d ", |
ff55a9ceb ACPI: Lindent pro... |
793 |
(u32) (throttling->status_register.space_id)); |
01854e697 ACPI: add ACPI 3.... |
794 |
} |
0753f6e0a ACPI: throttle: C... |
795 |
return ret; |
01854e697 ACPI: add ACPI 3.... |
796 |
} |
0753f6e0a ACPI: throttle: C... |
797 |
static int acpi_write_throttling_state(struct acpi_processor *pr, |
439913fff ACPI: replace acp... |
798 |
u64 value) |
01854e697 ACPI: add ACPI 3.... |
799 |
{ |
9bcb27217 ACPI: Use _TSS fo... |
800 |
u32 bit_width, bit_offset; |
0753f6e0a ACPI: throttle: C... |
801 |
u64 ptc_value; |
9bcb27217 ACPI: Use _TSS fo... |
802 |
u64 ptc_mask; |
0753f6e0a ACPI: throttle: C... |
803 |
struct acpi_processor_throttling *throttling; |
01854e697 ACPI: add ACPI 3.... |
804 |
int ret = -1; |
0753f6e0a ACPI: throttle: C... |
805 |
throttling = &pr->throttling; |
01854e697 ACPI: add ACPI 3.... |
806 807 |
switch (throttling->control_register.space_id) { case ACPI_ADR_SPACE_SYSTEM_IO: |
9bcb27217 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 ACPI: Lindent pro... |
812 |
acpi_os_write_port((acpi_io_address) throttling-> |
9bcb27217 ACPI: Use _TSS fo... |
813 814 815 |
control_register.address, (u32) (ptc_value << bit_offset), (u32) (bit_width + bit_offset)); |
01854e697 ACPI: add ACPI 3.... |
816 817 818 |
ret = 0; break; case ACPI_ADR_SPACE_FIXED_HARDWARE: |
9d42a53e0 acpi throttling: ... |
819 |
ret = acpi_throttling_wrmsr(value); |
01854e697 ACPI: add ACPI 3.... |
820 821 822 823 |
break; default: printk(KERN_ERR PREFIX "Unknown addr space %d ", |
ff55a9ceb ACPI: Lindent pro... |
824 |
(u32) (throttling->control_register.space_id)); |
01854e697 ACPI: add ACPI 3.... |
825 826 827 |
} return ret; } |
0753f6e0a ACPI: throttle: C... |
828 |
static int acpi_get_throttling_state(struct acpi_processor *pr, |
439913fff ACPI: replace acp... |
829 |
u64 value) |
01854e697 ACPI: add ACPI 3.... |
830 831 832 833 |
{ int i; for (i = 0; i < pr->throttling.state_count; i++) { |
ff55a9ceb 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 ACPI: get_throttl... |
838 |
return i; |
01854e697 ACPI: add ACPI 3.... |
839 |
} |
53af9cfb3 ACPI: get_throttl... |
840 |
return -1; |
01854e697 ACPI: add ACPI 3.... |
841 |
} |
0753f6e0a ACPI: throttle: C... |
842 |
static int acpi_get_throttling_value(struct acpi_processor *pr, |
439913fff ACPI: replace acp... |
843 |
int state, u64 *value) |
01854e697 ACPI: add ACPI 3.... |
844 |
{ |
0753f6e0a ACPI: throttle: C... |
845 |
int ret = -1; |
ff55a9ceb 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 ACPI: throttle: C... |
850 851 |
*value = tx->control; ret = 0; |
01854e697 ACPI: add ACPI 3.... |
852 |
} |
0753f6e0a ACPI: throttle: C... |
853 |
return ret; |
01854e697 ACPI: add ACPI 3.... |
854 855 856 857 858 |
} static int acpi_processor_get_throttling_ptc(struct acpi_processor *pr) { int state = 0; |
0753f6e0a ACPI: throttle: C... |
859 |
int ret; |
439913fff ACPI: replace acp... |
860 |
u64 value; |
01854e697 ACPI: add ACPI 3.... |
861 |
|
01854e697 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 ACPI: Delete the ... |
869 |
|
0753f6e0a ACPI: throttle: C... |
870 871 872 |
value = 0; ret = acpi_read_throttling_status(pr, &value); if (ret >= 0) { |
ff55a9ceb ACPI: Lindent pro... |
873 |
state = acpi_get_throttling_state(pr, value); |
4973b22aa ACPI processor: r... |
874 |
if (state == -1) { |
bdf57de4e acpi processor: r... |
875 876 877 |
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Invalid throttling state, reset ")); |
4973b22aa ACPI processor: r... |
878 |
state = 0; |
2a908002c ACPI processor: f... |
879 |
ret = acpi_processor_set_throttling(pr, state, true); |
4973b22aa ACPI processor: r... |
880 881 882 |
if (ret) return ret; } |
01854e697 ACPI: add ACPI 3.... |
883 884 |
pr->throttling.state = state; } |
01854e697 ACPI: add ACPI 3.... |
885 886 887 |
return 0; } |
01854e697 ACPI: add ACPI 3.... |
888 889 |
static int acpi_processor_get_throttling(struct acpi_processor *pr) { |
2fdf66b49 cpumask: convert ... |
890 |
cpumask_var_t saved_mask; |
357dc4c3f ACPI: Delete the ... |
891 |
int ret; |
87654273e ACPI : Check para... |
892 893 894 895 896 |
if (!pr) return -EINVAL; if (!pr->flags.throttling) return -ENODEV; |
2fdf66b49 cpumask: convert ... |
897 898 899 |
if (!alloc_cpumask_var(&saved_mask, GFP_KERNEL)) return -ENOMEM; |
357dc4c3f ACPI: Delete the ... |
900 901 902 |
/* * Migrate task to the cpu pointed by pr. */ |
2fdf66b49 cpumask: convert ... |
903 904 |
cpumask_copy(saved_mask, ¤t->cpus_allowed); /* FIXME: use work_on_cpu() */ |
daef1f35e 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 ACPI: Delete the ... |
910 911 |
ret = pr->throttling.acpi_processor_get_throttling(pr); /* restore the previous state */ |
2fdf66b49 cpumask: convert ... |
912 913 |
set_cpus_allowed_ptr(current, saved_mask); free_cpumask_var(saved_mask); |
357dc4c3f ACPI: Delete the ... |
914 915 |
return ret; |
01854e697 ACPI: add ACPI 3.... |
916 |
} |
22cc50199 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 ACPI: static |
953 |
static int acpi_processor_set_throttling_fadt(struct acpi_processor *pr, |
2a908002c ACPI processor: f... |
954 |
int state, bool force) |
1da177e4c Linux-2.6.12-rc2 |
955 |
{ |
4be44fcd3 [ACPI] Lindent al... |
956 957 958 |
u32 value = 0; u32 duty_mask = 0; u32 duty_value = 0; |
1da177e4c Linux-2.6.12-rc2 |
959 |
|
1da177e4c Linux-2.6.12-rc2 |
960 |
if (!pr) |
d550d98d3 ACPI: delete trac... |
961 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
962 963 |
if ((state < 0) || (state > (pr->throttling.state_count - 1))) |
d550d98d3 ACPI: delete trac... |
964 |
return -EINVAL; |
1da177e4c Linux-2.6.12-rc2 |
965 966 |
if (!pr->flags.throttling) |
d550d98d3 ACPI: delete trac... |
967 |
return -ENODEV; |
1da177e4c Linux-2.6.12-rc2 |
968 |
|
2a908002c ACPI processor: f... |
969 |
if (!force && (state == pr->throttling.state)) |
d550d98d3 ACPI: delete trac... |
970 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
971 |
|
01854e697 ACPI: add ACPI 3.... |
972 973 |
if (state < pr->throttling_platform_limit) return -EPERM; |
1da177e4c 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 ACPICA: use new A... |
984 |
duty_mask <<= acpi_gbl_FADT.duty_offset; |
1da177e4c 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 [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 Linux-2.6.12-rc2 |
1022 |
|
d550d98d3 ACPI: delete trac... |
1023 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1024 |
} |
6c5cf8aa5 ACPI: static |
1025 |
static int acpi_processor_set_throttling_ptc(struct acpi_processor *pr, |
2a908002c ACPI processor: f... |
1026 |
int state, bool force) |
01854e697 ACPI: add ACPI 3.... |
1027 |
{ |
0753f6e0a ACPI: throttle: C... |
1028 |
int ret; |
439913fff ACPI: replace acp... |
1029 |
u64 value; |
01854e697 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 ACPI processor: f... |
1039 |
if (!force && (state == pr->throttling.state)) |
01854e697 ACPI: add ACPI 3.... |
1040 1041 1042 1043 |
return 0; if (state < pr->throttling_platform_limit) return -EPERM; |
0753f6e0a 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 ACPI: add ACPI 3.... |
1048 1049 |
pr->throttling.state = state; } |
01854e697 ACPI: add ACPI 3.... |
1050 1051 1052 |
return 0; } |
2a908002c ACPI processor: f... |
1053 1054 |
int acpi_processor_set_throttling(struct acpi_processor *pr, int state, bool force) |
01854e697 ACPI: add ACPI 3.... |
1055 |
{ |
2fdf66b49 cpumask: convert ... |
1056 |
cpumask_var_t saved_mask; |
3391a76f2 ACPI: throttling:... |
1057 |
int ret = 0; |
33a2a529f 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 cpumask: convert ... |
1062 |
cpumask_var_t online_throttling_cpus; |
87654273e 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 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 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 cpumask: convert ... |
1086 |
cpumask_copy(saved_mask, ¤t->cpus_allowed); |
33a2a529f ACPI: Update the ... |
1087 1088 |
t_state.target_state = state; p_throttling = &(pr->throttling); |
2fdf66b49 cpumask: convert ... |
1089 1090 |
cpumask_and(online_throttling_cpus, cpu_online_mask, p_throttling->shared_cpu_map); |
357dc4c3f ACPI: Delete the ... |
1091 |
/* |
33a2a529f 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 ACPI: Delete the ... |
1095 |
*/ |
2fdf66b49 cpumask: convert ... |
1096 |
for_each_cpu(i, online_throttling_cpus) { |
33a2a529f 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 cpumask: convert ... |
1108 |
/* FIXME: use work_on_cpu() */ |
daef1f35e 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 ACPI: Update the ... |
1114 |
ret = p_throttling->acpi_processor_set_throttling(pr, |
2a908002c ACPI processor: f... |
1115 |
t_state.target_state, force); |
33a2a529f 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 cpumask: convert ... |
1122 |
for_each_cpu(i, online_throttling_cpus) { |
706546d02 ACPI: change proc... |
1123 |
match_pr = per_cpu(processors, i); |
33a2a529f 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 Fix common misspe... |
1140 |
"Throttling Control is unsupported " |
33a2a529f ACPI: Update the ... |
1141 1142 1143 1144 1145 |
"on CPU %d ", i)); continue; } t_state.cpu = i; |
2fdf66b49 cpumask: convert ... |
1146 |
/* FIXME: use work_on_cpu() */ |
daef1f35e ACPI: Check the r... |
1147 1148 |
if (set_cpus_allowed_ptr(current, cpumask_of(i))) continue; |
33a2a529f ACPI: Update the ... |
1149 1150 |
ret = match_pr->throttling. acpi_processor_set_throttling( |
2a908002c ACPI processor: f... |
1151 |
match_pr, t_state.target_state, force); |
33a2a529f 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 cpumask: convert ... |
1160 |
for_each_cpu(i, online_throttling_cpus) { |
33a2a529f ACPI: Update the ... |
1161 1162 1163 1164 |
t_state.cpu = i; acpi_processor_throttling_notifier(THROTTLING_POSTCHANGE, &t_state); } |
357dc4c3f ACPI: Delete the ... |
1165 |
/* restore the previous state */ |
2fdf66b49 cpumask: convert ... |
1166 1167 |
/* FIXME: use work_on_cpu() */ set_cpus_allowed_ptr(current, saved_mask); |
daef1f35e ACPI: Check the r... |
1168 |
exit: |
2fdf66b49 cpumask: convert ... |
1169 1170 |
free_cpumask_var(online_throttling_cpus); free_cpumask_var(saved_mask); |
357dc4c3f ACPI: Delete the ... |
1171 |
return ret; |
01854e697 ACPI: add ACPI 3.... |
1172 |
} |
4be44fcd3 [ACPI] Lindent al... |
1173 |
int acpi_processor_get_throttling_info(struct acpi_processor *pr) |
1da177e4c Linux-2.6.12-rc2 |
1174 |
{ |
4be44fcd3 [ACPI] Lindent al... |
1175 |
int result = 0; |
1180509f6 ACPI : Update T-s... |
1176 |
struct acpi_processor_throttling *pthrottling; |
1da177e4c Linux-2.6.12-rc2 |
1177 |
|
1da177e4c Linux-2.6.12-rc2 |
1178 |
ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
4be44fcd3 [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 Linux-2.6.12-rc2 |
1184 |
|
c30c620ee 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 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 ACPI: processor: ... |
1197 1198 |
if (acpi_processor_get_fadt_info(pr)) return 0; |
01854e697 ACPI: add ACPI 3.... |
1199 |
} else { |
ff55a9ceb 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 ACPI: add ACPI 3.... |
1204 |
} |
1da177e4c Linux-2.6.12-rc2 |
1205 |
|
1180509f6 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 cpumask: convert ... |
1213 |
cpumask_set_cpu(pr->id, pthrottling->shared_cpu_map); |
1180509f6 ACPI : Update T-s... |
1214 1215 |
pthrottling->shared_type = DOMAIN_COORD_TYPE_SW_ALL; } |
c30c620ee ACPI: quiet ACPI ... |
1216 |
|
1da177e4c 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 [ACPI] Lindent al... |
1224 1225 |
"Throttling not supported on PIIX4 A- or B-step ")); |
d550d98d3 ACPI: delete trac... |
1226 |
return 0; |
1da177e4c Linux-2.6.12-rc2 |
1227 |
} |
1da177e4c Linux-2.6.12-rc2 |
1228 1229 |
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d throttling states ", |
4be44fcd3 [ACPI] Lindent al... |
1230 |
pr->throttling.state_count)); |
1da177e4c 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 [ACPI] Lindent al... |
1245 1246 1247 1248 |
ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Disabling throttling (was T%d) ", pr->throttling.state)); |
2a908002c ACPI processor: f... |
1249 |
result = acpi_processor_set_throttling(pr, 0, false); |
1da177e4c Linux-2.6.12-rc2 |
1250 1251 1252 |
if (result) goto end; } |
4be44fcd3 [ACPI] Lindent al... |
1253 |
end: |
1da177e4c Linux-2.6.12-rc2 |
1254 1255 |
if (result) pr->flags.throttling = 0; |
d550d98d3 ACPI: delete trac... |
1256 |
return result; |
1da177e4c Linux-2.6.12-rc2 |
1257 |
} |