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