.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | * processor_perflib.c - ACPI Processor P-States Library ($Revision: 71 $) |
---|
3 | 4 | * |
---|
.. | .. |
---|
6 | 7 | * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de> |
---|
7 | 8 | * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com> |
---|
8 | 9 | * - 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 | 10 | */ |
---|
24 | 11 | |
---|
25 | 12 | #include <linux/kernel.h> |
---|
.. | .. |
---|
63 | 50 | MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \ |
---|
64 | 51 | "limited by BIOS, this should help"); |
---|
65 | 52 | |
---|
66 | | -#define PPC_REGISTERED 1 |
---|
67 | | -#define PPC_IN_USE 2 |
---|
68 | | - |
---|
69 | | -static int acpi_processor_ppc_status; |
---|
70 | | - |
---|
71 | | -static int acpi_processor_ppc_notifier(struct notifier_block *nb, |
---|
72 | | - unsigned long event, void *data) |
---|
73 | | -{ |
---|
74 | | - struct cpufreq_policy *policy = data; |
---|
75 | | - struct acpi_processor *pr; |
---|
76 | | - unsigned int ppc = 0; |
---|
77 | | - |
---|
78 | | - if (ignore_ppc < 0) |
---|
79 | | - ignore_ppc = 0; |
---|
80 | | - |
---|
81 | | - if (ignore_ppc) |
---|
82 | | - return 0; |
---|
83 | | - |
---|
84 | | - if (event != CPUFREQ_ADJUST) |
---|
85 | | - return 0; |
---|
86 | | - |
---|
87 | | - mutex_lock(&performance_mutex); |
---|
88 | | - |
---|
89 | | - pr = per_cpu(processors, policy->cpu); |
---|
90 | | - if (!pr || !pr->performance) |
---|
91 | | - goto out; |
---|
92 | | - |
---|
93 | | - ppc = (unsigned int)pr->performance_platform_limit; |
---|
94 | | - |
---|
95 | | - if (ppc >= pr->performance->state_count) |
---|
96 | | - goto out; |
---|
97 | | - |
---|
98 | | - cpufreq_verify_within_limits(policy, 0, |
---|
99 | | - pr->performance->states[ppc]. |
---|
100 | | - core_frequency * 1000); |
---|
101 | | - |
---|
102 | | - out: |
---|
103 | | - mutex_unlock(&performance_mutex); |
---|
104 | | - |
---|
105 | | - return 0; |
---|
106 | | -} |
---|
107 | | - |
---|
108 | | -static struct notifier_block acpi_ppc_notifier_block = { |
---|
109 | | - .notifier_call = acpi_processor_ppc_notifier, |
---|
110 | | -}; |
---|
| 53 | +static bool acpi_processor_ppc_in_use; |
---|
111 | 54 | |
---|
112 | 55 | static int acpi_processor_get_platform_limit(struct acpi_processor *pr) |
---|
113 | 56 | { |
---|
114 | 57 | acpi_status status = 0; |
---|
115 | 58 | unsigned long long ppc = 0; |
---|
116 | | - |
---|
| 59 | + s32 qos_value; |
---|
| 60 | + int index; |
---|
| 61 | + int ret; |
---|
117 | 62 | |
---|
118 | 63 | if (!pr) |
---|
119 | 64 | return -EINVAL; |
---|
.. | .. |
---|
125 | 70 | status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc); |
---|
126 | 71 | |
---|
127 | 72 | if (status != AE_NOT_FOUND) |
---|
128 | | - acpi_processor_ppc_status |= PPC_IN_USE; |
---|
| 73 | + acpi_processor_ppc_in_use = true; |
---|
129 | 74 | |
---|
130 | 75 | if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { |
---|
131 | 76 | ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PPC")); |
---|
132 | 77 | return -ENODEV; |
---|
133 | 78 | } |
---|
134 | 79 | |
---|
135 | | - pr_debug("CPU %d: _PPC is %d - frequency %s limited\n", pr->id, |
---|
136 | | - (int)ppc, ppc ? "" : "not"); |
---|
| 80 | + index = ppc; |
---|
137 | 81 | |
---|
138 | | - pr->performance_platform_limit = (int)ppc; |
---|
| 82 | + if (pr->performance_platform_limit == index || |
---|
| 83 | + ppc >= pr->performance->state_count) |
---|
| 84 | + return 0; |
---|
| 85 | + |
---|
| 86 | + pr_debug("CPU %d: _PPC is %d - frequency %s limited\n", pr->id, |
---|
| 87 | + index, index ? "is" : "is not"); |
---|
| 88 | + |
---|
| 89 | + pr->performance_platform_limit = index; |
---|
| 90 | + |
---|
| 91 | + if (unlikely(!freq_qos_request_active(&pr->perflib_req))) |
---|
| 92 | + return 0; |
---|
| 93 | + |
---|
| 94 | + /* |
---|
| 95 | + * If _PPC returns 0, it means that all of the available states can be |
---|
| 96 | + * used ("no limit"). |
---|
| 97 | + */ |
---|
| 98 | + if (index == 0) |
---|
| 99 | + qos_value = FREQ_QOS_MAX_DEFAULT_VALUE; |
---|
| 100 | + else |
---|
| 101 | + qos_value = pr->performance->states[index].core_frequency * 1000; |
---|
| 102 | + |
---|
| 103 | + ret = freq_qos_update_request(&pr->perflib_req, qos_value); |
---|
| 104 | + if (ret < 0) { |
---|
| 105 | + pr_warn("Failed to update perflib freq constraint: CPU%d (%d)\n", |
---|
| 106 | + pr->id, ret); |
---|
| 107 | + } |
---|
139 | 108 | |
---|
140 | 109 | return 0; |
---|
141 | 110 | } |
---|
.. | .. |
---|
181 | 150 | acpi_processor_ppc_ost(pr->handle, 0); |
---|
182 | 151 | } |
---|
183 | 152 | if (ret >= 0) |
---|
184 | | - cpufreq_update_policy(pr->id); |
---|
| 153 | + cpufreq_update_limits(pr->id); |
---|
185 | 154 | } |
---|
186 | 155 | |
---|
187 | 156 | int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) |
---|
.. | .. |
---|
197 | 166 | } |
---|
198 | 167 | EXPORT_SYMBOL(acpi_processor_get_bios_limit); |
---|
199 | 168 | |
---|
200 | | -void acpi_processor_ppc_init(void) |
---|
| 169 | +void acpi_processor_ignore_ppc_init(void) |
---|
201 | 170 | { |
---|
202 | | - if (!cpufreq_register_notifier |
---|
203 | | - (&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER)) |
---|
204 | | - acpi_processor_ppc_status |= PPC_REGISTERED; |
---|
205 | | - else |
---|
206 | | - printk(KERN_DEBUG |
---|
207 | | - "Warning: Processor Platform Limit not supported.\n"); |
---|
| 171 | + if (ignore_ppc < 0) |
---|
| 172 | + ignore_ppc = 0; |
---|
208 | 173 | } |
---|
209 | 174 | |
---|
210 | | -void acpi_processor_ppc_exit(void) |
---|
| 175 | +void acpi_processor_ppc_init(struct cpufreq_policy *policy) |
---|
211 | 176 | { |
---|
212 | | - if (acpi_processor_ppc_status & PPC_REGISTERED) |
---|
213 | | - cpufreq_unregister_notifier(&acpi_ppc_notifier_block, |
---|
214 | | - CPUFREQ_POLICY_NOTIFIER); |
---|
| 177 | + unsigned int cpu; |
---|
215 | 178 | |
---|
216 | | - acpi_processor_ppc_status &= ~PPC_REGISTERED; |
---|
| 179 | + for_each_cpu(cpu, policy->related_cpus) { |
---|
| 180 | + struct acpi_processor *pr = per_cpu(processors, cpu); |
---|
| 181 | + int ret; |
---|
| 182 | + |
---|
| 183 | + if (!pr) |
---|
| 184 | + continue; |
---|
| 185 | + |
---|
| 186 | + /* |
---|
| 187 | + * Reset performance_platform_limit in case there is a stale |
---|
| 188 | + * value in it, so as to make it match the "no limit" QoS value |
---|
| 189 | + * below. |
---|
| 190 | + */ |
---|
| 191 | + pr->performance_platform_limit = 0; |
---|
| 192 | + |
---|
| 193 | + ret = freq_qos_add_request(&policy->constraints, |
---|
| 194 | + &pr->perflib_req, FREQ_QOS_MAX, |
---|
| 195 | + FREQ_QOS_MAX_DEFAULT_VALUE); |
---|
| 196 | + if (ret < 0) |
---|
| 197 | + pr_err("Failed to add freq constraint for CPU%d (%d)\n", |
---|
| 198 | + cpu, ret); |
---|
| 199 | + } |
---|
| 200 | +} |
---|
| 201 | + |
---|
| 202 | +void acpi_processor_ppc_exit(struct cpufreq_policy *policy) |
---|
| 203 | +{ |
---|
| 204 | + unsigned int cpu; |
---|
| 205 | + |
---|
| 206 | + for_each_cpu(cpu, policy->related_cpus) { |
---|
| 207 | + struct acpi_processor *pr = per_cpu(processors, cpu); |
---|
| 208 | + |
---|
| 209 | + if (pr) |
---|
| 210 | + freq_qos_remove_request(&pr->perflib_req); |
---|
| 211 | + } |
---|
217 | 212 | } |
---|
218 | 213 | |
---|
219 | 214 | static int acpi_processor_get_performance_control(struct acpi_processor *pr) |
---|
.. | .. |
---|
381 | 376 | (u32) px->control, (u32) px->status)); |
---|
382 | 377 | |
---|
383 | 378 | /* |
---|
384 | | - * Check that ACPI's u64 MHz will be valid as u32 KHz in cpufreq |
---|
| 379 | + * Check that ACPI's u64 MHz will be valid as u32 KHz in cpufreq |
---|
385 | 380 | */ |
---|
386 | 381 | if (!px->core_frequency || |
---|
387 | 382 | ((u32)(px->core_frequency * 1000) != |
---|
.. | .. |
---|
490 | 485 | static int is_done = 0; |
---|
491 | 486 | int result; |
---|
492 | 487 | |
---|
493 | | - if (!(acpi_processor_ppc_status & PPC_REGISTERED)) |
---|
| 488 | + if (!acpi_processor_cpufreq_init) |
---|
494 | 489 | return -EBUSY; |
---|
495 | 490 | |
---|
496 | 491 | if (!try_module_get(calling_module)) |
---|
.. | .. |
---|
526 | 521 | * we can allow the cpufreq driver to be rmmod'ed. */ |
---|
527 | 522 | is_done = 1; |
---|
528 | 523 | |
---|
529 | | - if (!(acpi_processor_ppc_status & PPC_IN_USE)) |
---|
| 524 | + if (!acpi_processor_ppc_in_use) |
---|
530 | 525 | module_put(calling_module); |
---|
531 | 526 | |
---|
532 | 527 | return 0; |
---|
.. | .. |
---|
654 | 649 | goto err_ret; |
---|
655 | 650 | |
---|
656 | 651 | /* |
---|
657 | | - * Now that we have _PSD data from all CPUs, lets setup P-state |
---|
| 652 | + * Now that we have _PSD data from all CPUs, lets setup P-state |
---|
658 | 653 | * domain info. |
---|
659 | 654 | */ |
---|
660 | 655 | for_each_possible_cpu(i) { |
---|
.. | .. |
---|
720 | 715 | if (match_pdomain->domain != pdomain->domain) |
---|
721 | 716 | continue; |
---|
722 | 717 | |
---|
723 | | - match_pr->performance->shared_type = |
---|
| 718 | + match_pr->performance->shared_type = |
---|
724 | 719 | pr->performance->shared_type; |
---|
725 | 720 | cpumask_copy(match_pr->performance->shared_cpu_map, |
---|
726 | 721 | pr->performance->shared_cpu_map); |
---|
.. | .. |
---|
755 | 750 | { |
---|
756 | 751 | struct acpi_processor *pr; |
---|
757 | 752 | |
---|
758 | | - if (!(acpi_processor_ppc_status & PPC_REGISTERED)) |
---|
| 753 | + if (!acpi_processor_cpufreq_init) |
---|
759 | 754 | return -EINVAL; |
---|
760 | 755 | |
---|
761 | 756 | mutex_lock(&performance_mutex); |
---|