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