root/drivers/acpi/processor_perflib.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. acpi_processor_get_platform_limit
  2. acpi_processor_ppc_ost
  3. acpi_processor_ppc_has_changed
  4. acpi_processor_get_bios_limit
  5. acpi_processor_ignore_ppc_init
  6. acpi_processor_ppc_init
  7. acpi_processor_ppc_exit
  8. acpi_processor_get_performance_control
  9. amd_fixup_frequency
  10. amd_fixup_frequency
  11. acpi_processor_get_performance_states
  12. acpi_processor_get_performance_info
  13. acpi_processor_pstate_control
  14. acpi_processor_notify_smm
  15. acpi_processor_get_psd
  16. acpi_processor_preregister_performance
  17. acpi_processor_register_performance
  18. acpi_processor_unregister_performance

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * processor_perflib.c - ACPI Processor P-States Library ($Revision: 71 $)
   4  *
   5  *  Copyright (C) 2001, 2002 Andy Grover <andrew.grover@intel.com>
   6  *  Copyright (C) 2001, 2002 Paul Diefenbaugh <paul.s.diefenbaugh@intel.com>
   7  *  Copyright (C) 2004       Dominik Brodowski <linux@brodo.de>
   8  *  Copyright (C) 2004  Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
   9  *                      - Added processor hotplug support
  10  */
  11 
  12 #include <linux/kernel.h>
  13 #include <linux/module.h>
  14 #include <linux/init.h>
  15 #include <linux/cpufreq.h>
  16 #include <linux/slab.h>
  17 #include <linux/acpi.h>
  18 #include <acpi/processor.h>
  19 #ifdef CONFIG_X86
  20 #include <asm/cpufeature.h>
  21 #endif
  22 
  23 #define PREFIX "ACPI: "
  24 
  25 #define ACPI_PROCESSOR_CLASS            "processor"
  26 #define ACPI_PROCESSOR_FILE_PERFORMANCE "performance"
  27 #define _COMPONENT              ACPI_PROCESSOR_COMPONENT
  28 ACPI_MODULE_NAME("processor_perflib");
  29 
  30 static DEFINE_MUTEX(performance_mutex);
  31 
  32 /*
  33  * _PPC support is implemented as a CPUfreq policy notifier:
  34  * This means each time a CPUfreq driver registered also with
  35  * the ACPI core is asked to change the speed policy, the maximum
  36  * value is adjusted so that it is within the platform limit.
  37  *
  38  * Also, when a new platform limit value is detected, the CPUfreq
  39  * policy is adjusted accordingly.
  40  */
  41 
  42 /* ignore_ppc:
  43  * -1 -> cpufreq low level drivers not initialized -> _PSS, etc. not called yet
  44  *       ignore _PPC
  45  *  0 -> cpufreq low level drivers initialized -> consider _PPC values
  46  *  1 -> ignore _PPC totally -> forced by user through boot param
  47  */
  48 static int ignore_ppc = -1;
  49 module_param(ignore_ppc, int, 0644);
  50 MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \
  51                  "limited by BIOS, this should help");
  52 
  53 static bool acpi_processor_ppc_in_use;
  54 
  55 static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
  56 {
  57         acpi_status status = 0;
  58         unsigned long long ppc = 0;
  59         int ret;
  60 
  61         if (!pr)
  62                 return -EINVAL;
  63 
  64         /*
  65          * _PPC indicates the maximum state currently supported by the platform
  66          * (e.g. 0 = states 0..n; 1 = states 1..n; etc.
  67          */
  68         status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc);
  69 
  70         if (status != AE_NOT_FOUND)
  71                 acpi_processor_ppc_in_use = true;
  72 
  73         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
  74                 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PPC"));
  75                 return -ENODEV;
  76         }
  77 
  78         pr_debug("CPU %d: _PPC is %d - frequency %s limited\n", pr->id,
  79                        (int)ppc, ppc ? "" : "not");
  80 
  81         pr->performance_platform_limit = (int)ppc;
  82 
  83         if (ppc >= pr->performance->state_count ||
  84             unlikely(!freq_qos_request_active(&pr->perflib_req)))
  85                 return 0;
  86 
  87         ret = freq_qos_update_request(&pr->perflib_req,
  88                         pr->performance->states[ppc].core_frequency * 1000);
  89         if (ret < 0) {
  90                 pr_warn("Failed to update perflib freq constraint: CPU%d (%d)\n",
  91                         pr->id, ret);
  92         }
  93 
  94         return 0;
  95 }
  96 
  97 #define ACPI_PROCESSOR_NOTIFY_PERFORMANCE       0x80
  98 /*
  99  * acpi_processor_ppc_ost: Notify firmware the _PPC evaluation status
 100  * @handle: ACPI processor handle
 101  * @status: the status code of _PPC evaluation
 102  *      0: success. OSPM is now using the performance state specificed.
 103  *      1: failure. OSPM has not changed the number of P-states in use
 104  */
 105 static void acpi_processor_ppc_ost(acpi_handle handle, int status)
 106 {
 107         if (acpi_has_method(handle, "_OST"))
 108                 acpi_evaluate_ost(handle, ACPI_PROCESSOR_NOTIFY_PERFORMANCE,
 109                                   status, NULL);
 110 }
 111 
 112 void acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
 113 {
 114         int ret;
 115 
 116         if (ignore_ppc || !pr->performance) {
 117                 /*
 118                  * Only when it is notification event, the _OST object
 119                  * will be evaluated. Otherwise it is skipped.
 120                  */
 121                 if (event_flag)
 122                         acpi_processor_ppc_ost(pr->handle, 1);
 123                 return;
 124         }
 125 
 126         ret = acpi_processor_get_platform_limit(pr);
 127         /*
 128          * Only when it is notification event, the _OST object
 129          * will be evaluated. Otherwise it is skipped.
 130          */
 131         if (event_flag) {
 132                 if (ret < 0)
 133                         acpi_processor_ppc_ost(pr->handle, 1);
 134                 else
 135                         acpi_processor_ppc_ost(pr->handle, 0);
 136         }
 137         if (ret >= 0)
 138                 cpufreq_update_limits(pr->id);
 139 }
 140 
 141 int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
 142 {
 143         struct acpi_processor *pr;
 144 
 145         pr = per_cpu(processors, cpu);
 146         if (!pr || !pr->performance || !pr->performance->state_count)
 147                 return -ENODEV;
 148         *limit = pr->performance->states[pr->performance_platform_limit].
 149                 core_frequency * 1000;
 150         return 0;
 151 }
 152 EXPORT_SYMBOL(acpi_processor_get_bios_limit);
 153 
 154 void acpi_processor_ignore_ppc_init(void)
 155 {
 156         if (ignore_ppc < 0)
 157                 ignore_ppc = 0;
 158 }
 159 
 160 void acpi_processor_ppc_init(struct cpufreq_policy *policy)
 161 {
 162         unsigned int cpu;
 163 
 164         for_each_cpu(cpu, policy->related_cpus) {
 165                 struct acpi_processor *pr = per_cpu(processors, cpu);
 166                 int ret;
 167 
 168                 if (!pr)
 169                         continue;
 170 
 171                 ret = freq_qos_add_request(&policy->constraints,
 172                                            &pr->perflib_req,
 173                                            FREQ_QOS_MAX, INT_MAX);
 174                 if (ret < 0)
 175                         pr_err("Failed to add freq constraint for CPU%d (%d)\n",
 176                                cpu, ret);
 177         }
 178 }
 179 
 180 void acpi_processor_ppc_exit(struct cpufreq_policy *policy)
 181 {
 182         unsigned int cpu;
 183 
 184         for_each_cpu(cpu, policy->related_cpus) {
 185                 struct acpi_processor *pr = per_cpu(processors, cpu);
 186 
 187                 if (pr)
 188                         freq_qos_remove_request(&pr->perflib_req);
 189         }
 190 }
 191 
 192 static 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 
 254 #ifdef CONFIG_X86
 255 /*
 256  * Some AMDs have 50MHz frequency multiples, but only provide 100MHz rounding
 257  * in their ACPI data. Calculate the real values and fix up the _PSS data.
 258  */
 259 static void amd_fixup_frequency(struct acpi_processor_px *px, int i)
 260 {
 261         u32 hi, lo, fid, did;
 262         int index = px->control & 0x00000007;
 263 
 264         if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
 265                 return;
 266 
 267         if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10)
 268             || boot_cpu_data.x86 == 0x11) {
 269                 rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi);
 270                 /*
 271                  * MSR C001_0064+:
 272                  * Bit 63: PstateEn. Read-write. If set, the P-state is valid.
 273                  */
 274                 if (!(hi & BIT(31)))
 275                         return;
 276 
 277                 fid = lo & 0x3f;
 278                 did = (lo >> 6) & 7;
 279                 if (boot_cpu_data.x86 == 0x10)
 280                         px->core_frequency = (100 * (fid + 0x10)) >> did;
 281                 else
 282                         px->core_frequency = (100 * (fid + 8)) >> did;
 283         }
 284 }
 285 #else
 286 static void amd_fixup_frequency(struct acpi_processor_px *px, int i) {};
 287 #endif
 288 
 289 static int acpi_processor_get_performance_states(struct acpi_processor *pr)
 290 {
 291         int result = 0;
 292         acpi_status status = AE_OK;
 293         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 294         struct acpi_buffer format = { sizeof("NNNNNN"), "NNNNNN" };
 295         struct acpi_buffer state = { 0, NULL };
 296         union acpi_object *pss = NULL;
 297         int i;
 298         int last_invalid = -1;
 299 
 300 
 301         status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
 302         if (ACPI_FAILURE(status)) {
 303                 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PSS"));
 304                 return -ENODEV;
 305         }
 306 
 307         pss = buffer.pointer;
 308         if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
 309                 printk(KERN_ERR PREFIX "Invalid _PSS data\n");
 310                 result = -EFAULT;
 311                 goto end;
 312         }
 313 
 314         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n",
 315                           pss->package.count));
 316 
 317         pr->performance->state_count = pss->package.count;
 318         pr->performance->states =
 319             kmalloc_array(pss->package.count,
 320                           sizeof(struct acpi_processor_px),
 321                           GFP_KERNEL);
 322         if (!pr->performance->states) {
 323                 result = -ENOMEM;
 324                 goto end;
 325         }
 326 
 327         for (i = 0; i < pr->performance->state_count; i++) {
 328 
 329                 struct acpi_processor_px *px = &(pr->performance->states[i]);
 330 
 331                 state.length = sizeof(struct acpi_processor_px);
 332                 state.pointer = px;
 333 
 334                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
 335 
 336                 status = acpi_extract_package(&(pss->package.elements[i]),
 337                                               &format, &state);
 338                 if (ACPI_FAILURE(status)) {
 339                         ACPI_EXCEPTION((AE_INFO, status, "Invalid _PSS data"));
 340                         result = -EFAULT;
 341                         kfree(pr->performance->states);
 342                         goto end;
 343                 }
 344 
 345                 amd_fixup_frequency(px, i);
 346 
 347                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 348                                   "State [%d]: core_frequency[%d] power[%d] transition_latency[%d] bus_master_latency[%d] control[0x%x] status[0x%x]\n",
 349                                   i,
 350                                   (u32) px->core_frequency,
 351                                   (u32) px->power,
 352                                   (u32) px->transition_latency,
 353                                   (u32) px->bus_master_latency,
 354                                   (u32) px->control, (u32) px->status));
 355 
 356                 /*
 357                  * Check that ACPI's u64 MHz will be valid as u32 KHz in cpufreq
 358                  */
 359                 if (!px->core_frequency ||
 360                     ((u32)(px->core_frequency * 1000) !=
 361                      (px->core_frequency * 1000))) {
 362                         printk(KERN_ERR FW_BUG PREFIX
 363                                "Invalid BIOS _PSS frequency found for processor %d: 0x%llx MHz\n",
 364                                pr->id, px->core_frequency);
 365                         if (last_invalid == -1)
 366                                 last_invalid = i;
 367                 } else {
 368                         if (last_invalid != -1) {
 369                                 /*
 370                                  * Copy this valid entry over last_invalid entry
 371                                  */
 372                                 memcpy(&(pr->performance->states[last_invalid]),
 373                                        px, sizeof(struct acpi_processor_px));
 374                                 ++last_invalid;
 375                         }
 376                 }
 377         }
 378 
 379         if (last_invalid == 0) {
 380                 printk(KERN_ERR FW_BUG PREFIX
 381                        "No valid BIOS _PSS frequency found for processor %d\n", pr->id);
 382                 result = -EFAULT;
 383                 kfree(pr->performance->states);
 384                 pr->performance->states = NULL;
 385         }
 386 
 387         if (last_invalid > 0)
 388                 pr->performance->state_count = last_invalid;
 389 
 390       end:
 391         kfree(buffer.pointer);
 392 
 393         return result;
 394 }
 395 
 396 int acpi_processor_get_performance_info(struct acpi_processor *pr)
 397 {
 398         int result = 0;
 399 
 400         if (!pr || !pr->performance || !pr->handle)
 401                 return -EINVAL;
 402 
 403         if (!acpi_has_method(pr->handle, "_PCT")) {
 404                 ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 405                                   "ACPI-based processor performance control unavailable\n"));
 406                 return -ENODEV;
 407         }
 408 
 409         result = acpi_processor_get_performance_control(pr);
 410         if (result)
 411                 goto update_bios;
 412 
 413         result = acpi_processor_get_performance_states(pr);
 414         if (result)
 415                 goto update_bios;
 416 
 417         /* We need to call _PPC once when cpufreq starts */
 418         if (ignore_ppc != 1)
 419                 result = acpi_processor_get_platform_limit(pr);
 420 
 421         return result;
 422 
 423         /*
 424          * Having _PPC but missing frequencies (_PSS, _PCT) is a very good hint that
 425          * the BIOS is older than the CPU and does not know its frequencies
 426          */
 427  update_bios:
 428 #ifdef CONFIG_X86
 429         if (acpi_has_method(pr->handle, "_PPC")) {
 430                 if(boot_cpu_has(X86_FEATURE_EST))
 431                         printk(KERN_WARNING FW_BUG "BIOS needs update for CPU "
 432                                "frequency support\n");
 433         }
 434 #endif
 435         return result;
 436 }
 437 EXPORT_SYMBOL_GPL(acpi_processor_get_performance_info);
 438 
 439 int acpi_processor_pstate_control(void)
 440 {
 441         acpi_status status;
 442 
 443         if (!acpi_gbl_FADT.smi_command || !acpi_gbl_FADT.pstate_control)
 444                 return 0;
 445 
 446         ACPI_DEBUG_PRINT((ACPI_DB_INFO,
 447                           "Writing pstate_control [0x%x] to smi_command [0x%x]\n",
 448                           acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
 449 
 450         status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
 451                                     (u32)acpi_gbl_FADT.pstate_control, 8);
 452         if (ACPI_SUCCESS(status))
 453                 return 1;
 454 
 455         ACPI_EXCEPTION((AE_INFO, status,
 456                         "Failed to write pstate_control [0x%x] to smi_command [0x%x]",
 457                         acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
 458         return -EIO;
 459 }
 460 
 461 int acpi_processor_notify_smm(struct module *calling_module)
 462 {
 463         static int is_done = 0;
 464         int result;
 465 
 466         if (!acpi_processor_cpufreq_init)
 467                 return -EBUSY;
 468 
 469         if (!try_module_get(calling_module))
 470                 return -EINVAL;
 471 
 472         /* is_done is set to negative if an error occurred,
 473          * and to postitive if _no_ error occurred, but SMM
 474          * was already notified. This avoids double notification
 475          * which might lead to unexpected results...
 476          */
 477         if (is_done > 0) {
 478                 module_put(calling_module);
 479                 return 0;
 480         } else if (is_done < 0) {
 481                 module_put(calling_module);
 482                 return is_done;
 483         }
 484 
 485         is_done = -EIO;
 486 
 487         result = acpi_processor_pstate_control();
 488         if (!result) {
 489                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_control\n"));
 490                 module_put(calling_module);
 491                 return 0;
 492         }
 493         if (result < 0) {
 494                 module_put(calling_module);
 495                 return result;
 496         }
 497 
 498         /* Success. If there's no _PPC, we need to fear nothing, so
 499          * we can allow the cpufreq driver to be rmmod'ed. */
 500         is_done = 1;
 501 
 502         if (!acpi_processor_ppc_in_use)
 503                 module_put(calling_module);
 504 
 505         return 0;
 506 }
 507 
 508 EXPORT_SYMBOL(acpi_processor_notify_smm);
 509 
 510 int acpi_processor_get_psd(acpi_handle handle, struct acpi_psd_package *pdomain)
 511 {
 512         int result = 0;
 513         acpi_status status = AE_OK;
 514         struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
 515         struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"};
 516         struct acpi_buffer state = {0, NULL};
 517         union acpi_object  *psd = NULL;
 518 
 519         status = acpi_evaluate_object(handle, "_PSD", NULL, &buffer);
 520         if (ACPI_FAILURE(status)) {
 521                 return -ENODEV;
 522         }
 523 
 524         psd = buffer.pointer;
 525         if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) {
 526                 printk(KERN_ERR PREFIX "Invalid _PSD data\n");
 527                 result = -EFAULT;
 528                 goto end;
 529         }
 530 
 531         if (psd->package.count != 1) {
 532                 printk(KERN_ERR PREFIX "Invalid _PSD data\n");
 533                 result = -EFAULT;
 534                 goto end;
 535         }
 536 
 537         state.length = sizeof(struct acpi_psd_package);
 538         state.pointer = pdomain;
 539 
 540         status = acpi_extract_package(&(psd->package.elements[0]),
 541                 &format, &state);
 542         if (ACPI_FAILURE(status)) {
 543                 printk(KERN_ERR PREFIX "Invalid _PSD data\n");
 544                 result = -EFAULT;
 545                 goto end;
 546         }
 547 
 548         if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) {
 549                 printk(KERN_ERR PREFIX "Unknown _PSD:num_entries\n");
 550                 result = -EFAULT;
 551                 goto end;
 552         }
 553 
 554         if (pdomain->revision != ACPI_PSD_REV0_REVISION) {
 555                 printk(KERN_ERR PREFIX "Unknown _PSD:revision\n");
 556                 result = -EFAULT;
 557                 goto end;
 558         }
 559 
 560         if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL &&
 561             pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY &&
 562             pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) {
 563                 printk(KERN_ERR PREFIX "Invalid _PSD:coord_type\n");
 564                 result = -EFAULT;
 565                 goto end;
 566         }
 567 end:
 568         kfree(buffer.pointer);
 569         return result;
 570 }
 571 EXPORT_SYMBOL(acpi_processor_get_psd);
 572 
 573 int acpi_processor_preregister_performance(
 574                 struct acpi_processor_performance __percpu *performance)
 575 {
 576         int count_target;
 577         int retval = 0;
 578         unsigned int i, j;
 579         cpumask_var_t covered_cpus;
 580         struct acpi_processor *pr;
 581         struct acpi_psd_package *pdomain;
 582         struct acpi_processor *match_pr;
 583         struct acpi_psd_package *match_pdomain;
 584 
 585         if (!zalloc_cpumask_var(&covered_cpus, GFP_KERNEL))
 586                 return -ENOMEM;
 587 
 588         mutex_lock(&performance_mutex);
 589 
 590         /*
 591          * Check if another driver has already registered, and abort before
 592          * changing pr->performance if it has. Check input data as well.
 593          */
 594         for_each_possible_cpu(i) {
 595                 pr = per_cpu(processors, i);
 596                 if (!pr) {
 597                         /* Look only at processors in ACPI namespace */
 598                         continue;
 599                 }
 600 
 601                 if (pr->performance) {
 602                         retval = -EBUSY;
 603                         goto err_out;
 604                 }
 605 
 606                 if (!performance || !per_cpu_ptr(performance, i)) {
 607                         retval = -EINVAL;
 608                         goto err_out;
 609                 }
 610         }
 611 
 612         /* Call _PSD for all CPUs */
 613         for_each_possible_cpu(i) {
 614                 pr = per_cpu(processors, i);
 615                 if (!pr)
 616                         continue;
 617 
 618                 pr->performance = per_cpu_ptr(performance, i);
 619                 cpumask_set_cpu(i, pr->performance->shared_cpu_map);
 620                 pdomain = &(pr->performance->domain_info);
 621                 if (acpi_processor_get_psd(pr->handle, pdomain)) {
 622                         retval = -EINVAL;
 623                         continue;
 624                 }
 625         }
 626         if (retval)
 627                 goto err_ret;
 628 
 629         /*
 630          * Now that we have _PSD data from all CPUs, lets setup P-state 
 631          * domain info.
 632          */
 633         for_each_possible_cpu(i) {
 634                 pr = per_cpu(processors, i);
 635                 if (!pr)
 636                         continue;
 637 
 638                 if (cpumask_test_cpu(i, covered_cpus))
 639                         continue;
 640 
 641                 pdomain = &(pr->performance->domain_info);
 642                 cpumask_set_cpu(i, pr->performance->shared_cpu_map);
 643                 cpumask_set_cpu(i, covered_cpus);
 644                 if (pdomain->num_processors <= 1)
 645                         continue;
 646 
 647                 /* Validate the Domain info */
 648                 count_target = pdomain->num_processors;
 649                 if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL)
 650                         pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
 651                 else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL)
 652                         pr->performance->shared_type = CPUFREQ_SHARED_TYPE_HW;
 653                 else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY)
 654                         pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ANY;
 655 
 656                 for_each_possible_cpu(j) {
 657                         if (i == j)
 658                                 continue;
 659 
 660                         match_pr = per_cpu(processors, j);
 661                         if (!match_pr)
 662                                 continue;
 663 
 664                         match_pdomain = &(match_pr->performance->domain_info);
 665                         if (match_pdomain->domain != pdomain->domain)
 666                                 continue;
 667 
 668                         /* Here i and j are in the same domain */
 669 
 670                         if (match_pdomain->num_processors != count_target) {
 671                                 retval = -EINVAL;
 672                                 goto err_ret;
 673                         }
 674 
 675                         if (pdomain->coord_type != match_pdomain->coord_type) {
 676                                 retval = -EINVAL;
 677                                 goto err_ret;
 678                         }
 679 
 680                         cpumask_set_cpu(j, covered_cpus);
 681                         cpumask_set_cpu(j, pr->performance->shared_cpu_map);
 682                 }
 683 
 684                 for_each_possible_cpu(j) {
 685                         if (i == j)
 686                                 continue;
 687 
 688                         match_pr = per_cpu(processors, j);
 689                         if (!match_pr)
 690                                 continue;
 691 
 692                         match_pdomain = &(match_pr->performance->domain_info);
 693                         if (match_pdomain->domain != pdomain->domain)
 694                                 continue;
 695 
 696                         match_pr->performance->shared_type = 
 697                                         pr->performance->shared_type;
 698                         cpumask_copy(match_pr->performance->shared_cpu_map,
 699                                      pr->performance->shared_cpu_map);
 700                 }
 701         }
 702 
 703 err_ret:
 704         for_each_possible_cpu(i) {
 705                 pr = per_cpu(processors, i);
 706                 if (!pr || !pr->performance)
 707                         continue;
 708 
 709                 /* Assume no coordination on any error parsing domain info */
 710                 if (retval) {
 711                         cpumask_clear(pr->performance->shared_cpu_map);
 712                         cpumask_set_cpu(i, pr->performance->shared_cpu_map);
 713                         pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
 714                 }
 715                 pr->performance = NULL; /* Will be set for real in register */
 716         }
 717 
 718 err_out:
 719         mutex_unlock(&performance_mutex);
 720         free_cpumask_var(covered_cpus);
 721         return retval;
 722 }
 723 EXPORT_SYMBOL(acpi_processor_preregister_performance);
 724 
 725 int
 726 acpi_processor_register_performance(struct acpi_processor_performance
 727                                     *performance, unsigned int cpu)
 728 {
 729         struct acpi_processor *pr;
 730 
 731         if (!acpi_processor_cpufreq_init)
 732                 return -EINVAL;
 733 
 734         mutex_lock(&performance_mutex);
 735 
 736         pr = per_cpu(processors, cpu);
 737         if (!pr) {
 738                 mutex_unlock(&performance_mutex);
 739                 return -ENODEV;
 740         }
 741 
 742         if (pr->performance) {
 743                 mutex_unlock(&performance_mutex);
 744                 return -EBUSY;
 745         }
 746 
 747         WARN_ON(!performance);
 748 
 749         pr->performance = performance;
 750 
 751         if (acpi_processor_get_performance_info(pr)) {
 752                 pr->performance = NULL;
 753                 mutex_unlock(&performance_mutex);
 754                 return -EIO;
 755         }
 756 
 757         mutex_unlock(&performance_mutex);
 758         return 0;
 759 }
 760 
 761 EXPORT_SYMBOL(acpi_processor_register_performance);
 762 
 763 void acpi_processor_unregister_performance(unsigned int cpu)
 764 {
 765         struct acpi_processor *pr;
 766 
 767         mutex_lock(&performance_mutex);
 768 
 769         pr = per_cpu(processors, cpu);
 770         if (!pr) {
 771                 mutex_unlock(&performance_mutex);
 772                 return;
 773         }
 774 
 775         if (pr->performance)
 776                 kfree(pr->performance->states);
 777         pr->performance = NULL;
 778 
 779         mutex_unlock(&performance_mutex);
 780 
 781         return;
 782 }
 783 
 784 EXPORT_SYMBOL(acpi_processor_unregister_performance);

/* [<][>][^][v][top][bottom][index][help] */