Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
at v2.6.28-rc2 809 lines 20 kB view raw
1/* 2 * processor_perflib.c - ACPI Processor P-States Library ($Revision: 71 $) 3 * 4 * Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com> 5 * Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com> 6 * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de> 7 * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> 8 * - Added processor hotplug support 9 * 10 * 11 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 12 * 13 * This program is free software; you can redistribute it and/or modify 14 * it under the terms of the GNU General Public License as published by 15 * the Free Software Foundation; either version 2 of the License, or (at 16 * your option) any later version. 17 * 18 * This program is distributed in the hope that it will be useful, but 19 * WITHOUT ANY WARRANTY; without even the implied warranty of 20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 * General Public License for more details. 22 * 23 * You should have received a copy of the GNU General Public License along 24 * with this program; if not, write to the Free Software Foundation, Inc., 25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. 26 * 27 */ 28 29#include <linux/kernel.h> 30#include <linux/module.h> 31#include <linux/init.h> 32#include <linux/cpufreq.h> 33 34#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF 35#include <linux/proc_fs.h> 36#include <linux/seq_file.h> 37#include <linux/mutex.h> 38 39#include <asm/uaccess.h> 40#endif 41#include <asm/cpufeature.h> 42 43#include <acpi/acpi_bus.h> 44#include <acpi/processor.h> 45 46#define ACPI_PROCESSOR_COMPONENT 0x01000000 47#define ACPI_PROCESSOR_CLASS "processor" 48#define ACPI_PROCESSOR_FILE_PERFORMANCE "performance" 49#define _COMPONENT ACPI_PROCESSOR_COMPONENT 50ACPI_MODULE_NAME("processor_perflib"); 51 52static DEFINE_MUTEX(performance_mutex); 53 54/* Use cpufreq debug layer for _PPC changes. */ 55#define cpufreq_printk(msg...) cpufreq_debug_printk(CPUFREQ_DEBUG_CORE, \ 56 "cpufreq-core", msg) 57 58/* 59 * _PPC support is implemented as a CPUfreq policy notifier: 60 * This means each time a CPUfreq driver registered also with 61 * the ACPI core is asked to change the speed policy, the maximum 62 * value is adjusted so that it is within the platform limit. 63 * 64 * Also, when a new platform limit value is detected, the CPUfreq 65 * policy is adjusted accordingly. 66 */ 67 68/* ignore_ppc: 69 * -1 -> cpufreq low level drivers not initialized -> _PSS, etc. not called yet 70 * ignore _PPC 71 * 0 -> cpufreq low level drivers initialized -> consider _PPC values 72 * 1 -> ignore _PPC totally -> forced by user through boot param 73 */ 74static int ignore_ppc = -1; 75module_param(ignore_ppc, int, 0644); 76MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \ 77 "limited by BIOS, this should help"); 78 79#define PPC_REGISTERED 1 80#define PPC_IN_USE 2 81 82static int acpi_processor_ppc_status; 83 84static int acpi_processor_ppc_notifier(struct notifier_block *nb, 85 unsigned long event, void *data) 86{ 87 struct cpufreq_policy *policy = data; 88 struct acpi_processor *pr; 89 unsigned int ppc = 0; 90 91 if (event == CPUFREQ_START && ignore_ppc <= 0) { 92 ignore_ppc = 0; 93 return 0; 94 } 95 96 if (ignore_ppc) 97 return 0; 98 99 if (event != CPUFREQ_INCOMPATIBLE) 100 return 0; 101 102 mutex_lock(&performance_mutex); 103 104 pr = per_cpu(processors, policy->cpu); 105 if (!pr || !pr->performance) 106 goto out; 107 108 ppc = (unsigned int)pr->performance_platform_limit; 109 110 if (ppc >= pr->performance->state_count) 111 goto out; 112 113 cpufreq_verify_within_limits(policy, 0, 114 pr->performance->states[ppc]. 115 core_frequency * 1000); 116 117 out: 118 mutex_unlock(&performance_mutex); 119 120 return 0; 121} 122 123static struct notifier_block acpi_ppc_notifier_block = { 124 .notifier_call = acpi_processor_ppc_notifier, 125}; 126 127static int acpi_processor_get_platform_limit(struct acpi_processor *pr) 128{ 129 acpi_status status = 0; 130 unsigned long long ppc = 0; 131 132 133 if (!pr) 134 return -EINVAL; 135 136 /* 137 * _PPC indicates the maximum state currently supported by the platform 138 * (e.g. 0 = states 0..n; 1 = states 1..n; etc. 139 */ 140 status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc); 141 142 if (status != AE_NOT_FOUND) 143 acpi_processor_ppc_status |= PPC_IN_USE; 144 145 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { 146 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PPC")); 147 return -ENODEV; 148 } 149 150 cpufreq_printk("CPU %d: _PPC is %d - frequency %s limited\n", pr->id, 151 (int)ppc, ppc ? "" : "not"); 152 153 pr->performance_platform_limit = (int)ppc; 154 155 return 0; 156} 157 158int acpi_processor_ppc_has_changed(struct acpi_processor *pr) 159{ 160 int ret; 161 162 if (ignore_ppc) 163 return 0; 164 165 ret = acpi_processor_get_platform_limit(pr); 166 167 if (ret < 0) 168 return (ret); 169 else 170 return cpufreq_update_policy(pr->id); 171} 172 173void acpi_processor_ppc_init(void) 174{ 175 if (!cpufreq_register_notifier 176 (&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER)) 177 acpi_processor_ppc_status |= PPC_REGISTERED; 178 else 179 printk(KERN_DEBUG 180 "Warning: Processor Platform Limit not supported.\n"); 181} 182 183void acpi_processor_ppc_exit(void) 184{ 185 if (acpi_processor_ppc_status & PPC_REGISTERED) 186 cpufreq_unregister_notifier(&acpi_ppc_notifier_block, 187 CPUFREQ_POLICY_NOTIFIER); 188 189 acpi_processor_ppc_status &= ~PPC_REGISTERED; 190} 191 192static int acpi_processor_get_performance_control(struct acpi_processor *pr) 193{ 194 int result = 0; 195 acpi_status status = 0; 196 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 197 union acpi_object *pct = NULL; 198 union acpi_object obj = { 0 }; 199 200 201 status = acpi_evaluate_object(pr->handle, "_PCT", NULL, &buffer); 202 if (ACPI_FAILURE(status)) { 203 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PCT")); 204 return -ENODEV; 205 } 206 207 pct = (union acpi_object *)buffer.pointer; 208 if (!pct || (pct->type != ACPI_TYPE_PACKAGE) 209 || (pct->package.count != 2)) { 210 printk(KERN_ERR PREFIX "Invalid _PCT data\n"); 211 result = -EFAULT; 212 goto end; 213 } 214 215 /* 216 * control_register 217 */ 218 219 obj = pct->package.elements[0]; 220 221 if ((obj.type != ACPI_TYPE_BUFFER) 222 || (obj.buffer.length < sizeof(struct acpi_pct_register)) 223 || (obj.buffer.pointer == NULL)) { 224 printk(KERN_ERR PREFIX "Invalid _PCT data (control_register)\n"); 225 result = -EFAULT; 226 goto end; 227 } 228 memcpy(&pr->performance->control_register, obj.buffer.pointer, 229 sizeof(struct acpi_pct_register)); 230 231 /* 232 * status_register 233 */ 234 235 obj = pct->package.elements[1]; 236 237 if ((obj.type != ACPI_TYPE_BUFFER) 238 || (obj.buffer.length < sizeof(struct acpi_pct_register)) 239 || (obj.buffer.pointer == NULL)) { 240 printk(KERN_ERR PREFIX "Invalid _PCT data (status_register)\n"); 241 result = -EFAULT; 242 goto end; 243 } 244 245 memcpy(&pr->performance->status_register, obj.buffer.pointer, 246 sizeof(struct acpi_pct_register)); 247 248 end: 249 kfree(buffer.pointer); 250 251 return result; 252} 253 254static int acpi_processor_get_performance_states(struct acpi_processor *pr) 255{ 256 int result = 0; 257 acpi_status status = AE_OK; 258 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 259 struct acpi_buffer format = { sizeof("NNNNNN"), "NNNNNN" }; 260 struct acpi_buffer state = { 0, NULL }; 261 union acpi_object *pss = NULL; 262 int i; 263 264 265 status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer); 266 if (ACPI_FAILURE(status)) { 267 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PSS")); 268 return -ENODEV; 269 } 270 271 pss = buffer.pointer; 272 if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) { 273 printk(KERN_ERR PREFIX "Invalid _PSS data\n"); 274 result = -EFAULT; 275 goto end; 276 } 277 278 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n", 279 pss->package.count)); 280 281 pr->performance->state_count = pss->package.count; 282 pr->performance->states = 283 kmalloc(sizeof(struct acpi_processor_px) * pss->package.count, 284 GFP_KERNEL); 285 if (!pr->performance->states) { 286 result = -ENOMEM; 287 goto end; 288 } 289 290 for (i = 0; i < pr->performance->state_count; i++) { 291 292 struct acpi_processor_px *px = &(pr->performance->states[i]); 293 294 state.length = sizeof(struct acpi_processor_px); 295 state.pointer = px; 296 297 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i)); 298 299 status = acpi_extract_package(&(pss->package.elements[i]), 300 &format, &state); 301 if (ACPI_FAILURE(status)) { 302 ACPI_EXCEPTION((AE_INFO, status, "Invalid _PSS data")); 303 result = -EFAULT; 304 kfree(pr->performance->states); 305 goto end; 306 } 307 308 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 309 "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n", 310 i, 311 (u32) px->core_frequency, 312 (u32) px->power, 313 (u32) px->transition_latency, 314 (u32) px->bus_master_latency, 315 (u32) px->control, (u32) px->status)); 316 317 if (!px->core_frequency) { 318 printk(KERN_ERR PREFIX 319 "Invalid _PSS data: freq is zero\n"); 320 result = -EFAULT; 321 kfree(pr->performance->states); 322 goto end; 323 } 324 } 325 326 end: 327 kfree(buffer.pointer); 328 329 return result; 330} 331 332static int acpi_processor_get_performance_info(struct acpi_processor *pr) 333{ 334 int result = 0; 335 acpi_status status = AE_OK; 336 acpi_handle handle = NULL; 337 338 if (!pr || !pr->performance || !pr->handle) 339 return -EINVAL; 340 341 status = acpi_get_handle(pr->handle, "_PCT", &handle); 342 if (ACPI_FAILURE(status)) { 343 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 344 "ACPI-based processor performance control unavailable\n")); 345 return -ENODEV; 346 } 347 348 result = acpi_processor_get_performance_control(pr); 349 if (result) 350 goto update_bios; 351 352 result = acpi_processor_get_performance_states(pr); 353 if (result) 354 goto update_bios; 355 356 return 0; 357 358 /* 359 * Having _PPC but missing frequencies (_PSS, _PCT) is a very good hint that 360 * the BIOS is older than the CPU and does not know its frequencies 361 */ 362 update_bios: 363 if (ACPI_SUCCESS(acpi_get_handle(pr->handle, "_PPC", &handle))){ 364 if(boot_cpu_has(X86_FEATURE_EST)) 365 printk(KERN_WARNING FW_BUG "BIOS needs update for CPU " 366 "frequency support\n"); 367 } 368 return result; 369} 370 371int acpi_processor_notify_smm(struct module *calling_module) 372{ 373 acpi_status status; 374 static int is_done = 0; 375 376 377 if (!(acpi_processor_ppc_status & PPC_REGISTERED)) 378 return -EBUSY; 379 380 if (!try_module_get(calling_module)) 381 return -EINVAL; 382 383 /* is_done is set to negative if an error occured, 384 * and to postitive if _no_ error occured, but SMM 385 * was already notified. This avoids double notification 386 * which might lead to unexpected results... 387 */ 388 if (is_done > 0) { 389 module_put(calling_module); 390 return 0; 391 } else if (is_done < 0) { 392 module_put(calling_module); 393 return is_done; 394 } 395 396 is_done = -EIO; 397 398 /* Can't write pstate_control to smi_command if either value is zero */ 399 if ((!acpi_gbl_FADT.smi_command) || (!acpi_gbl_FADT.pstate_control)) { 400 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_control\n")); 401 module_put(calling_module); 402 return 0; 403 } 404 405 ACPI_DEBUG_PRINT((ACPI_DB_INFO, 406 "Writing pstate_control [0x%x] to smi_command [0x%x]\n", 407 acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command)); 408 409 status = acpi_os_write_port(acpi_gbl_FADT.smi_command, 410 (u32) acpi_gbl_FADT.pstate_control, 8); 411 if (ACPI_FAILURE(status)) { 412 ACPI_EXCEPTION((AE_INFO, status, 413 "Failed to write pstate_control [0x%x] to " 414 "smi_command [0x%x]", acpi_gbl_FADT.pstate_control, 415 acpi_gbl_FADT.smi_command)); 416 module_put(calling_module); 417 return status; 418 } 419 420 /* Success. If there's no _PPC, we need to fear nothing, so 421 * we can allow the cpufreq driver to be rmmod'ed. */ 422 is_done = 1; 423 424 if (!(acpi_processor_ppc_status & PPC_IN_USE)) 425 module_put(calling_module); 426 427 return 0; 428} 429 430EXPORT_SYMBOL(acpi_processor_notify_smm); 431 432#ifdef CONFIG_X86_ACPI_CPUFREQ_PROC_INTF 433/* /proc/acpi/processor/../performance interface (DEPRECATED) */ 434 435static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file); 436static struct file_operations acpi_processor_perf_fops = { 437 .owner = THIS_MODULE, 438 .open = acpi_processor_perf_open_fs, 439 .read = seq_read, 440 .llseek = seq_lseek, 441 .release = single_release, 442}; 443 444static int acpi_processor_perf_seq_show(struct seq_file *seq, void *offset) 445{ 446 struct acpi_processor *pr = seq->private; 447 int i; 448 449 450 if (!pr) 451 goto end; 452 453 if (!pr->performance) { 454 seq_puts(seq, "<not supported>\n"); 455 goto end; 456 } 457 458 seq_printf(seq, "state count: %d\n" 459 "active state: P%d\n", 460 pr->performance->state_count, pr->performance->state); 461 462 seq_puts(seq, "states:\n"); 463 for (i = 0; i < pr->performance->state_count; i++) 464 seq_printf(seq, 465 " %cP%d: %d MHz, %d mW, %d uS\n", 466 (i == pr->performance->state ? '*' : ' '), i, 467 (u32) pr->performance->states[i].core_frequency, 468 (u32) pr->performance->states[i].power, 469 (u32) pr->performance->states[i].transition_latency); 470 471 end: 472 return 0; 473} 474 475static int acpi_processor_perf_open_fs(struct inode *inode, struct file *file) 476{ 477 return single_open(file, acpi_processor_perf_seq_show, 478 PDE(inode)->data); 479} 480 481static void acpi_cpufreq_add_file(struct acpi_processor *pr) 482{ 483 struct acpi_device *device = NULL; 484 485 486 if (acpi_bus_get_device(pr->handle, &device)) 487 return; 488 489 /* add file 'performance' [R/W] */ 490 proc_create_data(ACPI_PROCESSOR_FILE_PERFORMANCE, S_IFREG | S_IRUGO, 491 acpi_device_dir(device), 492 &acpi_processor_perf_fops, acpi_driver_data(device)); 493 return; 494} 495 496static void acpi_cpufreq_remove_file(struct acpi_processor *pr) 497{ 498 struct acpi_device *device = NULL; 499 500 501 if (acpi_bus_get_device(pr->handle, &device)) 502 return; 503 504 /* remove file 'performance' */ 505 remove_proc_entry(ACPI_PROCESSOR_FILE_PERFORMANCE, 506 acpi_device_dir(device)); 507 508 return; 509} 510 511#else 512static void acpi_cpufreq_add_file(struct acpi_processor *pr) 513{ 514 return; 515} 516static void acpi_cpufreq_remove_file(struct acpi_processor *pr) 517{ 518 return; 519} 520#endif /* CONFIG_X86_ACPI_CPUFREQ_PROC_INTF */ 521 522static int acpi_processor_get_psd(struct acpi_processor *pr) 523{ 524 int result = 0; 525 acpi_status status = AE_OK; 526 struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL}; 527 struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"}; 528 struct acpi_buffer state = {0, NULL}; 529 union acpi_object *psd = NULL; 530 struct acpi_psd_package *pdomain; 531 532 status = acpi_evaluate_object(pr->handle, "_PSD", NULL, &buffer); 533 if (ACPI_FAILURE(status)) { 534 return -ENODEV; 535 } 536 537 psd = buffer.pointer; 538 if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) { 539 printk(KERN_ERR PREFIX "Invalid _PSD data\n"); 540 result = -EFAULT; 541 goto end; 542 } 543 544 if (psd->package.count != 1) { 545 printk(KERN_ERR PREFIX "Invalid _PSD data\n"); 546 result = -EFAULT; 547 goto end; 548 } 549 550 pdomain = &(pr->performance->domain_info); 551 552 state.length = sizeof(struct acpi_psd_package); 553 state.pointer = pdomain; 554 555 status = acpi_extract_package(&(psd->package.elements[0]), 556 &format, &state); 557 if (ACPI_FAILURE(status)) { 558 printk(KERN_ERR PREFIX "Invalid _PSD data\n"); 559 result = -EFAULT; 560 goto end; 561 } 562 563 if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) { 564 printk(KERN_ERR PREFIX "Unknown _PSD:num_entries\n"); 565 result = -EFAULT; 566 goto end; 567 } 568 569 if (pdomain->revision != ACPI_PSD_REV0_REVISION) { 570 printk(KERN_ERR PREFIX "Unknown _PSD:revision\n"); 571 result = -EFAULT; 572 goto end; 573 } 574 575end: 576 kfree(buffer.pointer); 577 return result; 578} 579 580int acpi_processor_preregister_performance( 581 struct acpi_processor_performance *performance) 582{ 583 int count, count_target; 584 int retval = 0; 585 unsigned int i, j; 586 cpumask_t covered_cpus; 587 struct acpi_processor *pr; 588 struct acpi_psd_package *pdomain; 589 struct acpi_processor *match_pr; 590 struct acpi_psd_package *match_pdomain; 591 592 mutex_lock(&performance_mutex); 593 594 retval = 0; 595 596 /* Call _PSD for all CPUs */ 597 for_each_possible_cpu(i) { 598 pr = per_cpu(processors, i); 599 if (!pr) { 600 /* Look only at processors in ACPI namespace */ 601 continue; 602 } 603 604 if (pr->performance) { 605 retval = -EBUSY; 606 continue; 607 } 608 609 if (!performance || !percpu_ptr(performance, i)) { 610 retval = -EINVAL; 611 continue; 612 } 613 614 pr->performance = percpu_ptr(performance, i); 615 cpu_set(i, pr->performance->shared_cpu_map); 616 if (acpi_processor_get_psd(pr)) { 617 retval = -EINVAL; 618 continue; 619 } 620 } 621 if (retval) 622 goto err_ret; 623 624 /* 625 * Now that we have _PSD data from all CPUs, lets setup P-state 626 * domain info. 627 */ 628 for_each_possible_cpu(i) { 629 pr = per_cpu(processors, i); 630 if (!pr) 631 continue; 632 633 /* Basic validity check for domain info */ 634 pdomain = &(pr->performance->domain_info); 635 if ((pdomain->revision != ACPI_PSD_REV0_REVISION) || 636 (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES)) { 637 retval = -EINVAL; 638 goto err_ret; 639 } 640 if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL && 641 pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY && 642 pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) { 643 retval = -EINVAL; 644 goto err_ret; 645 } 646 } 647 648 cpus_clear(covered_cpus); 649 for_each_possible_cpu(i) { 650 pr = per_cpu(processors, i); 651 if (!pr) 652 continue; 653 654 if (cpu_isset(i, covered_cpus)) 655 continue; 656 657 pdomain = &(pr->performance->domain_info); 658 cpu_set(i, pr->performance->shared_cpu_map); 659 cpu_set(i, covered_cpus); 660 if (pdomain->num_processors <= 1) 661 continue; 662 663 /* Validate the Domain info */ 664 count_target = pdomain->num_processors; 665 count = 1; 666 if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL) 667 pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL; 668 else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL) 669 pr->performance->shared_type = CPUFREQ_SHARED_TYPE_HW; 670 else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY) 671 pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ANY; 672 673 for_each_possible_cpu(j) { 674 if (i == j) 675 continue; 676 677 match_pr = per_cpu(processors, j); 678 if (!match_pr) 679 continue; 680 681 match_pdomain = &(match_pr->performance->domain_info); 682 if (match_pdomain->domain != pdomain->domain) 683 continue; 684 685 /* Here i and j are in the same domain */ 686 687 if (match_pdomain->num_processors != count_target) { 688 retval = -EINVAL; 689 goto err_ret; 690 } 691 692 if (pdomain->coord_type != match_pdomain->coord_type) { 693 retval = -EINVAL; 694 goto err_ret; 695 } 696 697 cpu_set(j, covered_cpus); 698 cpu_set(j, pr->performance->shared_cpu_map); 699 count++; 700 } 701 702 for_each_possible_cpu(j) { 703 if (i == j) 704 continue; 705 706 match_pr = per_cpu(processors, j); 707 if (!match_pr) 708 continue; 709 710 match_pdomain = &(match_pr->performance->domain_info); 711 if (match_pdomain->domain != pdomain->domain) 712 continue; 713 714 match_pr->performance->shared_type = 715 pr->performance->shared_type; 716 match_pr->performance->shared_cpu_map = 717 pr->performance->shared_cpu_map; 718 } 719 } 720 721err_ret: 722 for_each_possible_cpu(i) { 723 pr = per_cpu(processors, i); 724 if (!pr || !pr->performance) 725 continue; 726 727 /* Assume no coordination on any error parsing domain info */ 728 if (retval) { 729 cpus_clear(pr->performance->shared_cpu_map); 730 cpu_set(i, pr->performance->shared_cpu_map); 731 pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL; 732 } 733 pr->performance = NULL; /* Will be set for real in register */ 734 } 735 736 mutex_unlock(&performance_mutex); 737 return retval; 738} 739EXPORT_SYMBOL(acpi_processor_preregister_performance); 740 741 742int 743acpi_processor_register_performance(struct acpi_processor_performance 744 *performance, unsigned int cpu) 745{ 746 struct acpi_processor *pr; 747 748 749 if (!(acpi_processor_ppc_status & PPC_REGISTERED)) 750 return -EINVAL; 751 752 mutex_lock(&performance_mutex); 753 754 pr = per_cpu(processors, cpu); 755 if (!pr) { 756 mutex_unlock(&performance_mutex); 757 return -ENODEV; 758 } 759 760 if (pr->performance) { 761 mutex_unlock(&performance_mutex); 762 return -EBUSY; 763 } 764 765 WARN_ON(!performance); 766 767 pr->performance = performance; 768 769 if (acpi_processor_get_performance_info(pr)) { 770 pr->performance = NULL; 771 mutex_unlock(&performance_mutex); 772 return -EIO; 773 } 774 775 acpi_cpufreq_add_file(pr); 776 777 mutex_unlock(&performance_mutex); 778 return 0; 779} 780 781EXPORT_SYMBOL(acpi_processor_register_performance); 782 783void 784acpi_processor_unregister_performance(struct acpi_processor_performance 785 *performance, unsigned int cpu) 786{ 787 struct acpi_processor *pr; 788 789 790 mutex_lock(&performance_mutex); 791 792 pr = per_cpu(processors, cpu); 793 if (!pr) { 794 mutex_unlock(&performance_mutex); 795 return; 796 } 797 798 if (pr->performance) 799 kfree(pr->performance->states); 800 pr->performance = NULL; 801 802 acpi_cpufreq_remove_file(pr); 803 804 mutex_unlock(&performance_mutex); 805 806 return; 807} 808 809EXPORT_SYMBOL(acpi_processor_unregister_performance);