LCOV - code coverage report
Current view: top level - drivers/acpi - processor_perflib.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 74 335 22.1 %
Date: 2022-03-28 13:20:08 Functions: 6 15 40.0 %
Branches: 29 198 14.6 %

           Branch data     Line data    Source code
       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                 :          0 : static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
      56                 :            : {
      57                 :          0 :         acpi_status status = 0;
      58                 :          0 :         unsigned long long ppc = 0;
      59                 :          0 :         int ret;
      60                 :            : 
      61         [ #  # ]:          0 :         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                 :          0 :         status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc);
      69                 :            : 
      70         [ #  # ]:          0 :         if (status != AE_NOT_FOUND)
      71                 :          0 :                 acpi_processor_ppc_in_use = true;
      72                 :            : 
      73         [ #  # ]:          0 :         if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
      74                 :          0 :                 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PPC"));
      75                 :          0 :                 return -ENODEV;
      76                 :            :         }
      77                 :            : 
      78                 :          0 :         pr_debug("CPU %d: _PPC is %d - frequency %s limited\n", pr->id,
      79                 :            :                        (int)ppc, ppc ? "" : "not");
      80                 :            : 
      81                 :          0 :         pr->performance_platform_limit = (int)ppc;
      82                 :            : 
      83         [ #  # ]:          0 :         if (ppc >= pr->performance->state_count ||
      84   [ #  #  #  # ]:          0 :             unlikely(!freq_qos_request_active(&pr->perflib_req)))
      85                 :            :                 return 0;
      86                 :            : 
      87                 :          0 :         ret = freq_qos_update_request(&pr->perflib_req,
      88                 :          0 :                         pr->performance->states[ppc].core_frequency * 1000);
      89         [ #  # ]:          0 :         if (ret < 0) {
      90                 :          0 :                 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                 :          0 : static void acpi_processor_ppc_ost(acpi_handle handle, int status)
     106                 :            : {
     107         [ #  # ]:          0 :         if (acpi_has_method(handle, "_OST"))
     108                 :          0 :                 acpi_evaluate_ost(handle, ACPI_PROCESSOR_NOTIFY_PERFORMANCE,
     109                 :            :                                   status, NULL);
     110                 :          0 : }
     111                 :            : 
     112                 :         30 : void acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag)
     113                 :            : {
     114                 :         30 :         int ret;
     115                 :            : 
     116   [ -  +  -  - ]:         30 :         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         [ -  + ]:         30 :                 if (event_flag)
     122                 :          0 :                         acpi_processor_ppc_ost(pr->handle, 1);
     123                 :         30 :                 return;
     124                 :            :         }
     125                 :            : 
     126                 :          0 :         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         [ #  # ]:          0 :         if (event_flag) {
     132         [ #  # ]:          0 :                 if (ret < 0)
     133                 :          0 :                         acpi_processor_ppc_ost(pr->handle, 1);
     134                 :            :                 else
     135                 :          0 :                         acpi_processor_ppc_ost(pr->handle, 0);
     136                 :            :         }
     137         [ #  # ]:          0 :         if (ret >= 0)
     138                 :          0 :                 cpufreq_update_limits(pr->id);
     139                 :            : }
     140                 :            : 
     141                 :          0 : int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
     142                 :            : {
     143                 :          0 :         struct acpi_processor *pr;
     144                 :            : 
     145                 :          0 :         pr = per_cpu(processors, cpu);
     146   [ #  #  #  #  :          0 :         if (!pr || !pr->performance || !pr->performance->state_count)
                   #  # ]
     147                 :            :                 return -ENODEV;
     148                 :          0 :         *limit = pr->performance->states[pr->performance_platform_limit].
     149                 :            :                 core_frequency * 1000;
     150                 :          0 :         return 0;
     151                 :            : }
     152                 :            : EXPORT_SYMBOL(acpi_processor_get_bios_limit);
     153                 :            : 
     154                 :         30 : void acpi_processor_ignore_ppc_init(void)
     155                 :            : {
     156         [ +  - ]:         30 :         if (ignore_ppc < 0)
     157                 :         30 :                 ignore_ppc = 0;
     158                 :         30 : }
     159                 :            : 
     160                 :          0 : void acpi_processor_ppc_init(struct cpufreq_policy *policy)
     161                 :            : {
     162                 :          0 :         unsigned int cpu;
     163                 :            : 
     164         [ #  # ]:          0 :         for_each_cpu(cpu, policy->related_cpus) {
     165                 :          0 :                 struct acpi_processor *pr = per_cpu(processors, cpu);
     166                 :          0 :                 int ret;
     167                 :            : 
     168         [ #  # ]:          0 :                 if (!pr)
     169                 :          0 :                         continue;
     170                 :            : 
     171                 :          0 :                 ret = freq_qos_add_request(&policy->constraints,
     172                 :            :                                            &pr->perflib_req,
     173                 :            :                                            FREQ_QOS_MAX, INT_MAX);
     174         [ #  # ]:          0 :                 if (ret < 0)
     175                 :          0 :                         pr_err("Failed to add freq constraint for CPU%d (%d)\n",
     176                 :            :                                cpu, ret);
     177                 :            :         }
     178                 :          0 : }
     179                 :            : 
     180                 :          0 : void acpi_processor_ppc_exit(struct cpufreq_policy *policy)
     181                 :            : {
     182                 :          0 :         unsigned int cpu;
     183                 :            : 
     184         [ #  # ]:          0 :         for_each_cpu(cpu, policy->related_cpus) {
     185                 :          0 :                 struct acpi_processor *pr = per_cpu(processors, cpu);
     186                 :            : 
     187         [ #  # ]:          0 :                 if (pr)
     188                 :          0 :                         freq_qos_remove_request(&pr->perflib_req);
     189                 :            :         }
     190                 :          0 : }
     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                 :          0 : static int acpi_processor_get_performance_states(struct acpi_processor *pr)
     290                 :            : {
     291                 :          0 :         int result = 0;
     292                 :          0 :         acpi_status status = AE_OK;
     293                 :          0 :         struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
     294                 :          0 :         struct acpi_buffer format = { sizeof("NNNNNN"), "NNNNNN" };
     295                 :          0 :         struct acpi_buffer state = { 0, NULL };
     296                 :          0 :         union acpi_object *pss = NULL;
     297                 :          0 :         int i;
     298                 :          0 :         int last_invalid = -1;
     299                 :            : 
     300                 :            : 
     301                 :          0 :         status = acpi_evaluate_object(pr->handle, "_PSS", NULL, &buffer);
     302         [ #  # ]:          0 :         if (ACPI_FAILURE(status)) {
     303                 :          0 :                 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PSS"));
     304                 :          0 :                 return -ENODEV;
     305                 :            :         }
     306                 :            : 
     307                 :          0 :         pss = buffer.pointer;
     308   [ #  #  #  # ]:          0 :         if (!pss || (pss->type != ACPI_TYPE_PACKAGE)) {
     309                 :          0 :                 printk(KERN_ERR PREFIX "Invalid _PSS data\n");
     310                 :          0 :                 result = -EFAULT;
     311                 :          0 :                 goto end;
     312                 :            :         }
     313                 :            : 
     314                 :            :         ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Found %d performance states\n",
     315                 :          0 :                           pss->package.count));
     316                 :            : 
     317                 :          0 :         pr->performance->state_count = pss->package.count;
     318                 :          0 :         pr->performance->states =
     319                 :          0 :             kmalloc_array(pss->package.count,
     320                 :            :                           sizeof(struct acpi_processor_px),
     321                 :            :                           GFP_KERNEL);
     322         [ #  # ]:          0 :         if (!pr->performance->states) {
     323                 :          0 :                 result = -ENOMEM;
     324                 :          0 :                 goto end;
     325                 :            :         }
     326                 :            : 
     327         [ #  # ]:          0 :         for (i = 0; i < pr->performance->state_count; i++) {
     328                 :            : 
     329                 :          0 :                 struct acpi_processor_px *px = &(pr->performance->states[i]);
     330                 :            : 
     331                 :          0 :                 state.length = sizeof(struct acpi_processor_px);
     332                 :          0 :                 state.pointer = px;
     333                 :            : 
     334                 :          0 :                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Extracting state %d\n", i));
     335                 :            : 
     336                 :          0 :                 status = acpi_extract_package(&(pss->package.elements[i]),
     337                 :            :                                               &format, &state);
     338         [ #  # ]:          0 :                 if (ACPI_FAILURE(status)) {
     339                 :          0 :                         ACPI_EXCEPTION((AE_INFO, status, "Invalid _PSS data"));
     340                 :          0 :                         result = -EFAULT;
     341                 :          0 :                         kfree(pr->performance->states);
     342                 :          0 :                         goto end;
     343                 :            :                 }
     344                 :            : 
     345                 :          0 :                 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                 :          0 :                                   (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         [ #  # ]:          0 :                 if (!px->core_frequency ||
     360                 :          0 :                     ((u32)(px->core_frequency * 1000) !=
     361         [ #  # ]:          0 :                      (px->core_frequency * 1000))) {
     362                 :          0 :                         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         [ #  # ]:          0 :                         if (last_invalid == -1)
     366                 :          0 :                                 last_invalid = i;
     367                 :            :                 } else {
     368         [ #  # ]:          0 :                         if (last_invalid != -1) {
     369                 :            :                                 /*
     370                 :            :                                  * Copy this valid entry over last_invalid entry
     371                 :            :                                  */
     372                 :          0 :                                 memcpy(&(pr->performance->states[last_invalid]),
     373                 :            :                                        px, sizeof(struct acpi_processor_px));
     374                 :          0 :                                 ++last_invalid;
     375                 :            :                         }
     376                 :            :                 }
     377                 :            :         }
     378                 :            : 
     379         [ #  # ]:          0 :         if (last_invalid == 0) {
     380                 :          0 :                 printk(KERN_ERR FW_BUG PREFIX
     381                 :            :                        "No valid BIOS _PSS frequency found for processor %d\n", pr->id);
     382                 :          0 :                 result = -EFAULT;
     383                 :          0 :                 kfree(pr->performance->states);
     384                 :          0 :                 pr->performance->states = NULL;
     385                 :            :         }
     386                 :            : 
     387         [ #  # ]:          0 :         if (last_invalid > 0)
     388                 :          0 :                 pr->performance->state_count = last_invalid;
     389                 :            : 
     390                 :          0 :       end:
     391                 :          0 :         kfree(buffer.pointer);
     392                 :            : 
     393                 :          0 :         return result;
     394                 :            : }
     395                 :            : 
     396                 :         30 : int acpi_processor_get_performance_info(struct acpi_processor *pr)
     397                 :            : {
     398                 :         30 :         int result = 0;
     399                 :            : 
     400   [ +  -  +  -  :         30 :         if (!pr || !pr->performance || !pr->handle)
                   +  - ]
     401                 :            :                 return -EINVAL;
     402                 :            : 
     403         [ -  + ]:         30 :         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                 :          0 :         result = acpi_processor_get_performance_control(pr);
     410         [ #  # ]:          0 :         if (result)
     411                 :          0 :                 goto update_bios;
     412                 :            : 
     413                 :          0 :         result = acpi_processor_get_performance_states(pr);
     414         [ #  # ]:          0 :         if (result)
     415                 :          0 :                 goto update_bios;
     416                 :            : 
     417                 :            :         /* We need to call _PPC once when cpufreq starts */
     418         [ #  # ]:          0 :         if (ignore_ppc != 1)
     419                 :          0 :                 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                 :          0 :  update_bios:
     428                 :            : #ifdef CONFIG_X86
     429         [ #  # ]:          0 :         if (acpi_has_method(pr->handle, "_PPC")) {
     430         [ #  # ]:          0 :                 if(boot_cpu_has(X86_FEATURE_EST))
     431                 :          0 :                         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                 :          0 : int acpi_processor_pstate_control(void)
     440                 :            : {
     441                 :          0 :         acpi_status status;
     442                 :            : 
     443   [ #  #  #  # ]:          0 :         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                 :          0 :                           acpi_gbl_FADT.pstate_control, acpi_gbl_FADT.smi_command));
     449                 :            : 
     450                 :          0 :         status = acpi_os_write_port(acpi_gbl_FADT.smi_command,
     451                 :            :                                     (u32)acpi_gbl_FADT.pstate_control, 8);
     452         [ #  # ]:          0 :         if (ACPI_SUCCESS(status))
     453                 :            :                 return 1;
     454                 :            : 
     455                 :          0 :         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                 :          0 :         return -EIO;
     459                 :            : }
     460                 :            : 
     461                 :          0 : int acpi_processor_notify_smm(struct module *calling_module)
     462                 :            : {
     463                 :          0 :         static int is_done = 0;
     464                 :          0 :         int result;
     465                 :            : 
     466         [ #  # ]:          0 :         if (!acpi_processor_cpufreq_init)
     467                 :            :                 return -EBUSY;
     468                 :            : 
     469         [ #  # ]:          0 :         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         [ #  # ]:          0 :         if (is_done > 0) {
     478                 :          0 :                 module_put(calling_module);
     479                 :          0 :                 return 0;
     480         [ #  # ]:          0 :         } else if (is_done < 0) {
     481                 :          0 :                 module_put(calling_module);
     482                 :          0 :                 return is_done;
     483                 :            :         }
     484                 :            : 
     485                 :          0 :         is_done = -EIO;
     486                 :            : 
     487                 :          0 :         result = acpi_processor_pstate_control();
     488         [ #  # ]:          0 :         if (!result) {
     489                 :          0 :                 ACPI_DEBUG_PRINT((ACPI_DB_INFO, "No SMI port or pstate_control\n"));
     490                 :          0 :                 module_put(calling_module);
     491                 :          0 :                 return 0;
     492                 :            :         }
     493         [ #  # ]:          0 :         if (result < 0) {
     494                 :          0 :                 module_put(calling_module);
     495                 :          0 :                 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                 :          0 :         is_done = 1;
     501                 :            : 
     502         [ #  # ]:          0 :         if (!acpi_processor_ppc_in_use)
     503                 :          0 :                 module_put(calling_module);
     504                 :            : 
     505                 :            :         return 0;
     506                 :            : }
     507                 :            : 
     508                 :            : EXPORT_SYMBOL(acpi_processor_notify_smm);
     509                 :            : 
     510                 :         30 : int acpi_processor_get_psd(acpi_handle handle, struct acpi_psd_package *pdomain)
     511                 :            : {
     512                 :         30 :         int result = 0;
     513                 :         30 :         acpi_status status = AE_OK;
     514                 :         30 :         struct acpi_buffer buffer = {ACPI_ALLOCATE_BUFFER, NULL};
     515                 :         30 :         struct acpi_buffer format = {sizeof("NNNNN"), "NNNNN"};
     516                 :         30 :         struct acpi_buffer state = {0, NULL};
     517                 :         30 :         union acpi_object  *psd = NULL;
     518                 :            : 
     519                 :         30 :         status = acpi_evaluate_object(handle, "_PSD", NULL, &buffer);
     520         [ -  + ]:         30 :         if (ACPI_FAILURE(status)) {
     521                 :            :                 return -ENODEV;
     522                 :            :         }
     523                 :            : 
     524                 :          0 :         psd = buffer.pointer;
     525   [ #  #  #  # ]:          0 :         if (!psd || (psd->type != ACPI_TYPE_PACKAGE)) {
     526                 :          0 :                 printk(KERN_ERR PREFIX "Invalid _PSD data\n");
     527                 :          0 :                 result = -EFAULT;
     528                 :          0 :                 goto end;
     529                 :            :         }
     530                 :            : 
     531         [ #  # ]:          0 :         if (psd->package.count != 1) {
     532                 :          0 :                 printk(KERN_ERR PREFIX "Invalid _PSD data\n");
     533                 :          0 :                 result = -EFAULT;
     534                 :          0 :                 goto end;
     535                 :            :         }
     536                 :            : 
     537                 :          0 :         state.length = sizeof(struct acpi_psd_package);
     538                 :          0 :         state.pointer = pdomain;
     539                 :            : 
     540                 :          0 :         status = acpi_extract_package(&(psd->package.elements[0]),
     541                 :            :                 &format, &state);
     542         [ #  # ]:          0 :         if (ACPI_FAILURE(status)) {
     543                 :          0 :                 printk(KERN_ERR PREFIX "Invalid _PSD data\n");
     544                 :          0 :                 result = -EFAULT;
     545                 :          0 :                 goto end;
     546                 :            :         }
     547                 :            : 
     548         [ #  # ]:          0 :         if (pdomain->num_entries != ACPI_PSD_REV0_ENTRIES) {
     549                 :          0 :                 printk(KERN_ERR PREFIX "Unknown _PSD:num_entries\n");
     550                 :          0 :                 result = -EFAULT;
     551                 :          0 :                 goto end;
     552                 :            :         }
     553                 :            : 
     554         [ #  # ]:          0 :         if (pdomain->revision != ACPI_PSD_REV0_REVISION) {
     555                 :          0 :                 printk(KERN_ERR PREFIX "Unknown _PSD:revision\n");
     556                 :          0 :                 result = -EFAULT;
     557                 :          0 :                 goto end;
     558                 :            :         }
     559                 :            : 
     560                 :          0 :         if (pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ALL &&
     561         [ #  # ]:          0 :             pdomain->coord_type != DOMAIN_COORD_TYPE_SW_ANY &&
     562                 :            :             pdomain->coord_type != DOMAIN_COORD_TYPE_HW_ALL) {
     563                 :          0 :                 printk(KERN_ERR PREFIX "Invalid _PSD:coord_type\n");
     564                 :          0 :                 result = -EFAULT;
     565                 :          0 :                 goto end;
     566                 :            :         }
     567                 :          0 : end:
     568                 :          0 :         kfree(buffer.pointer);
     569                 :          0 :         return result;
     570                 :            : }
     571                 :            : EXPORT_SYMBOL(acpi_processor_get_psd);
     572                 :            : 
     573                 :         30 : int acpi_processor_preregister_performance(
     574                 :            :                 struct acpi_processor_performance __percpu *performance)
     575                 :            : {
     576                 :         30 :         int count_target;
     577                 :         30 :         int retval = 0;
     578                 :         30 :         unsigned int i, j;
     579                 :         30 :         cpumask_var_t covered_cpus;
     580                 :         30 :         struct acpi_processor *pr;
     581                 :         30 :         struct acpi_psd_package *pdomain;
     582                 :         30 :         struct acpi_processor *match_pr;
     583                 :         30 :         struct acpi_psd_package *match_pdomain;
     584                 :            : 
     585                 :         30 :         if (!zalloc_cpumask_var(&covered_cpus, GFP_KERNEL))
     586                 :            :                 return -ENOMEM;
     587                 :            : 
     588                 :         30 :         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         [ +  + ]:         90 :         for_each_possible_cpu(i) {
     595                 :         30 :                 pr = per_cpu(processors, i);
     596         [ -  + ]:         30 :                 if (!pr) {
     597                 :            :                         /* Look only at processors in ACPI namespace */
     598                 :          0 :                         continue;
     599                 :            :                 }
     600                 :            : 
     601         [ -  + ]:         30 :                 if (pr->performance) {
     602                 :          0 :                         retval = -EBUSY;
     603                 :          0 :                         goto err_out;
     604                 :            :                 }
     605                 :            : 
     606   [ +  -  -  + ]:         30 :                 if (!performance || !per_cpu_ptr(performance, i)) {
     607                 :          0 :                         retval = -EINVAL;
     608                 :          0 :                         goto err_out;
     609                 :            :                 }
     610                 :            :         }
     611                 :            : 
     612                 :            :         /* Call _PSD for all CPUs */
     613         [ +  + ]:         60 :         for_each_possible_cpu(i) {
     614                 :         30 :                 pr = per_cpu(processors, i);
     615         [ -  + ]:         30 :                 if (!pr)
     616                 :          0 :                         continue;
     617                 :            : 
     618                 :         30 :                 pr->performance = per_cpu_ptr(performance, i);
     619                 :         30 :                 cpumask_set_cpu(i, pr->performance->shared_cpu_map);
     620                 :         30 :                 pdomain = &(pr->performance->domain_info);
     621         [ +  - ]:         30 :                 if (acpi_processor_get_psd(pr->handle, pdomain)) {
     622                 :         30 :                         retval = -EINVAL;
     623                 :         30 :                         continue;
     624                 :            :                 }
     625                 :            :         }
     626         [ -  + ]:         30 :         if (retval)
     627                 :         30 :                 goto err_ret;
     628                 :            : 
     629                 :            :         /*
     630                 :            :          * Now that we have _PSD data from all CPUs, lets setup P-state 
     631                 :            :          * domain info.
     632                 :            :          */
     633         [ #  # ]:          0 :         for_each_possible_cpu(i) {
     634                 :          0 :                 pr = per_cpu(processors, i);
     635         [ #  # ]:          0 :                 if (!pr)
     636                 :          0 :                         continue;
     637                 :            : 
     638         [ #  # ]:          0 :                 if (cpumask_test_cpu(i, covered_cpus))
     639                 :          0 :                         continue;
     640                 :            : 
     641                 :          0 :                 pdomain = &(pr->performance->domain_info);
     642                 :          0 :                 cpumask_set_cpu(i, pr->performance->shared_cpu_map);
     643                 :          0 :                 cpumask_set_cpu(i, covered_cpus);
     644         [ #  # ]:          0 :                 if (pdomain->num_processors <= 1)
     645                 :          0 :                         continue;
     646                 :            : 
     647                 :            :                 /* Validate the Domain info */
     648                 :          0 :                 count_target = pdomain->num_processors;
     649         [ #  # ]:          0 :                 if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ALL)
     650                 :          0 :                         pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
     651         [ #  # ]:          0 :                 else if (pdomain->coord_type == DOMAIN_COORD_TYPE_HW_ALL)
     652                 :          0 :                         pr->performance->shared_type = CPUFREQ_SHARED_TYPE_HW;
     653         [ #  # ]:          0 :                 else if (pdomain->coord_type == DOMAIN_COORD_TYPE_SW_ANY)
     654                 :          0 :                         pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ANY;
     655                 :            : 
     656         [ #  # ]:          0 :                 for_each_possible_cpu(j) {
     657         [ #  # ]:          0 :                         if (i == j)
     658                 :          0 :                                 continue;
     659                 :            : 
     660                 :          0 :                         match_pr = per_cpu(processors, j);
     661         [ #  # ]:          0 :                         if (!match_pr)
     662                 :          0 :                                 continue;
     663                 :            : 
     664                 :          0 :                         match_pdomain = &(match_pr->performance->domain_info);
     665         [ #  # ]:          0 :                         if (match_pdomain->domain != pdomain->domain)
     666                 :          0 :                                 continue;
     667                 :            : 
     668                 :            :                         /* Here i and j are in the same domain */
     669                 :            : 
     670         [ #  # ]:          0 :                         if (match_pdomain->num_processors != count_target) {
     671                 :          0 :                                 retval = -EINVAL;
     672                 :          0 :                                 goto err_ret;
     673                 :            :                         }
     674                 :            : 
     675         [ #  # ]:          0 :                         if (pdomain->coord_type != match_pdomain->coord_type) {
     676                 :          0 :                                 retval = -EINVAL;
     677                 :          0 :                                 goto err_ret;
     678                 :            :                         }
     679                 :            : 
     680                 :          0 :                         cpumask_set_cpu(j, covered_cpus);
     681                 :          0 :                         cpumask_set_cpu(j, pr->performance->shared_cpu_map);
     682                 :            :                 }
     683                 :            : 
     684         [ #  # ]:          0 :                 for_each_possible_cpu(j) {
     685         [ #  # ]:          0 :                         if (i == j)
     686                 :          0 :                                 continue;
     687                 :            : 
     688                 :          0 :                         match_pr = per_cpu(processors, j);
     689         [ #  # ]:          0 :                         if (!match_pr)
     690                 :          0 :                                 continue;
     691                 :            : 
     692                 :          0 :                         match_pdomain = &(match_pr->performance->domain_info);
     693         [ #  # ]:          0 :                         if (match_pdomain->domain != pdomain->domain)
     694                 :          0 :                                 continue;
     695                 :            : 
     696                 :          0 :                         match_pr->performance->shared_type = 
     697                 :          0 :                                         pr->performance->shared_type;
     698                 :          0 :                         cpumask_copy(match_pr->performance->shared_cpu_map,
     699                 :          0 :                                      pr->performance->shared_cpu_map);
     700                 :            :                 }
     701                 :            :         }
     702                 :            : 
     703                 :          0 : err_ret:
     704         [ +  + ]:         60 :         for_each_possible_cpu(i) {
     705                 :         30 :                 pr = per_cpu(processors, i);
     706   [ +  -  -  + ]:         30 :                 if (!pr || !pr->performance)
     707                 :          0 :                         continue;
     708                 :            : 
     709                 :            :                 /* Assume no coordination on any error parsing domain info */
     710         [ +  - ]:         30 :                 if (retval) {
     711                 :         30 :                         cpumask_clear(pr->performance->shared_cpu_map);
     712                 :         30 :                         cpumask_set_cpu(i, pr->performance->shared_cpu_map);
     713                 :         30 :                         pr->performance->shared_type = CPUFREQ_SHARED_TYPE_ALL;
     714                 :            :                 }
     715                 :         30 :                 pr->performance = NULL; /* Will be set for real in register */
     716                 :            :         }
     717                 :            : 
     718                 :         30 : err_out:
     719                 :         30 :         mutex_unlock(&performance_mutex);
     720                 :         30 :         free_cpumask_var(covered_cpus);
     721                 :         30 :         return retval;
     722                 :            : }
     723                 :            : EXPORT_SYMBOL(acpi_processor_preregister_performance);
     724                 :            : 
     725                 :            : int
     726                 :         30 : acpi_processor_register_performance(struct acpi_processor_performance
     727                 :            :                                     *performance, unsigned int cpu)
     728                 :            : {
     729                 :         30 :         struct acpi_processor *pr;
     730                 :            : 
     731         [ +  - ]:         30 :         if (!acpi_processor_cpufreq_init)
     732                 :            :                 return -EINVAL;
     733                 :            : 
     734                 :         30 :         mutex_lock(&performance_mutex);
     735                 :            : 
     736                 :         30 :         pr = per_cpu(processors, cpu);
     737         [ -  + ]:         30 :         if (!pr) {
     738                 :          0 :                 mutex_unlock(&performance_mutex);
     739                 :          0 :                 return -ENODEV;
     740                 :            :         }
     741                 :            : 
     742         [ -  + ]:         30 :         if (pr->performance) {
     743                 :          0 :                 mutex_unlock(&performance_mutex);
     744                 :          0 :                 return -EBUSY;
     745                 :            :         }
     746                 :            : 
     747         [ -  + ]:         30 :         WARN_ON(!performance);
     748                 :            : 
     749                 :         30 :         pr->performance = performance;
     750                 :            : 
     751         [ +  - ]:         30 :         if (acpi_processor_get_performance_info(pr)) {
     752                 :         30 :                 pr->performance = NULL;
     753                 :         30 :                 mutex_unlock(&performance_mutex);
     754                 :         30 :                 return -EIO;
     755                 :            :         }
     756                 :            : 
     757                 :          0 :         mutex_unlock(&performance_mutex);
     758                 :          0 :         return 0;
     759                 :            : }
     760                 :            : 
     761                 :            : EXPORT_SYMBOL(acpi_processor_register_performance);
     762                 :            : 
     763                 :          0 : void acpi_processor_unregister_performance(unsigned int cpu)
     764                 :            : {
     765                 :          0 :         struct acpi_processor *pr;
     766                 :            : 
     767                 :          0 :         mutex_lock(&performance_mutex);
     768                 :            : 
     769                 :          0 :         pr = per_cpu(processors, cpu);
     770         [ #  # ]:          0 :         if (!pr) {
     771                 :          0 :                 mutex_unlock(&performance_mutex);
     772                 :          0 :                 return;
     773                 :            :         }
     774                 :            : 
     775         [ #  # ]:          0 :         if (pr->performance)
     776                 :          0 :                 kfree(pr->performance->states);
     777                 :          0 :         pr->performance = NULL;
     778                 :            : 
     779                 :          0 :         mutex_unlock(&performance_mutex);
     780                 :            : 
     781                 :          0 :         return;
     782                 :            : }
     783                 :            : 
     784                 :            : EXPORT_SYMBOL(acpi_processor_unregister_performance);

Generated by: LCOV version 1.14