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