linux/drivers/acpi/processor_perflib.c
<<
>>
Prefs
   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
  28ACPI_MODULE_NAME("processor_perflib");
  29
  30static 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 */
  48static int ignore_ppc = -1;
  49module_param(ignore_ppc, int, 0644);
  50MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \
  51                 "limited by BIOS, this should help");
  52
  53static bool acpi_processor_ppc_in_use;
  54
  55static 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 */
 105static 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
 112void 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
 141int 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}
 152EXPORT_SYMBOL(acpi_processor_get_bios_limit);
 153
 154void acpi_processor_ignore_ppc_init(void)
 155{
 156        if (ignore_ppc < 0)
 157                ignore_ppc = 0;
 158}
 159
 160void 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
 180void 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
 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
 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 */
 259static 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
 286static void amd_fixup_frequency(struct acpi_processor_px *px, int i) {};
 287#endif
 288
 289static 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
 396int 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}
 437EXPORT_SYMBOL_GPL(acpi_processor_get_performance_info);
 438
 439int 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
 461int 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
 508EXPORT_SYMBOL(acpi_processor_notify_smm);
 509
 510int 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        }
 567end:
 568        kfree(buffer.pointer);
 569        return result;
 570}
 571EXPORT_SYMBOL(acpi_processor_get_psd);
 572
 573int 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
 703err_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
 718err_out:
 719        mutex_unlock(&performance_mutex);
 720        free_cpumask_var(covered_cpus);
 721        return retval;
 722}
 723EXPORT_SYMBOL(acpi_processor_preregister_performance);
 724
 725int
 726acpi_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
 761EXPORT_SYMBOL(acpi_processor_register_performance);
 762
 763void 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
 784EXPORT_SYMBOL(acpi_processor_unregister_performance);
 785