hc
2024-02-20 102a0743326a03cd1a1202ceda21e175b7d3575c
kernel/drivers/acpi/processor_perflib.c
....@@ -1,3 +1,4 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * processor_perflib.c - ACPI Processor P-States Library ($Revision: 71 $)
34 *
....@@ -6,20 +7,6 @@
67 * Copyright (C) 2004 Dominik Brodowski <linux@brodo.de>
78 * Copyright (C) 2004 Anil S Keshavamurthy <anil.s.keshavamurthy@intel.com>
89 * - 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
- *
2310 */
2411
2512 #include <linux/kernel.h>
....@@ -63,57 +50,15 @@
6350 MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \
6451 "limited by BIOS, this should help");
6552
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;
11154
11255 static int acpi_processor_get_platform_limit(struct acpi_processor *pr)
11356 {
11457 acpi_status status = 0;
11558 unsigned long long ppc = 0;
116
-
59
+ s32 qos_value;
60
+ int index;
61
+ int ret;
11762
11863 if (!pr)
11964 return -EINVAL;
....@@ -125,17 +70,41 @@
12570 status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc);
12671
12772 if (status != AE_NOT_FOUND)
128
- acpi_processor_ppc_status |= PPC_IN_USE;
73
+ acpi_processor_ppc_in_use = true;
12974
13075 if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) {
13176 ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PPC"));
13277 return -ENODEV;
13378 }
13479
135
- pr_debug("CPU %d: _PPC is %d - frequency %s limited\n", pr->id,
136
- (int)ppc, ppc ? "" : "not");
80
+ index = ppc;
13781
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
+ }
139108
140109 return 0;
141110 }
....@@ -181,7 +150,7 @@
181150 acpi_processor_ppc_ost(pr->handle, 0);
182151 }
183152 if (ret >= 0)
184
- cpufreq_update_policy(pr->id);
153
+ cpufreq_update_limits(pr->id);
185154 }
186155
187156 int acpi_processor_get_bios_limit(int cpu, unsigned int *limit)
....@@ -197,23 +166,49 @@
197166 }
198167 EXPORT_SYMBOL(acpi_processor_get_bios_limit);
199168
200
-void acpi_processor_ppc_init(void)
169
+void acpi_processor_ignore_ppc_init(void)
201170 {
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;
208173 }
209174
210
-void acpi_processor_ppc_exit(void)
175
+void acpi_processor_ppc_init(struct cpufreq_policy *policy)
211176 {
212
- if (acpi_processor_ppc_status & PPC_REGISTERED)
213
- cpufreq_unregister_notifier(&acpi_ppc_notifier_block,
214
- CPUFREQ_POLICY_NOTIFIER);
177
+ unsigned int cpu;
215178
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
+ }
217212 }
218213
219214 static int acpi_processor_get_performance_control(struct acpi_processor *pr)
....@@ -381,7 +376,7 @@
381376 (u32) px->control, (u32) px->status));
382377
383378 /*
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
385380 */
386381 if (!px->core_frequency ||
387382 ((u32)(px->core_frequency * 1000) !=
....@@ -490,7 +485,7 @@
490485 static int is_done = 0;
491486 int result;
492487
493
- if (!(acpi_processor_ppc_status & PPC_REGISTERED))
488
+ if (!acpi_processor_cpufreq_init)
494489 return -EBUSY;
495490
496491 if (!try_module_get(calling_module))
....@@ -526,7 +521,7 @@
526521 * we can allow the cpufreq driver to be rmmod'ed. */
527522 is_done = 1;
528523
529
- if (!(acpi_processor_ppc_status & PPC_IN_USE))
524
+ if (!acpi_processor_ppc_in_use)
530525 module_put(calling_module);
531526
532527 return 0;
....@@ -654,7 +649,7 @@
654649 goto err_ret;
655650
656651 /*
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
658653 * domain info.
659654 */
660655 for_each_possible_cpu(i) {
....@@ -720,7 +715,7 @@
720715 if (match_pdomain->domain != pdomain->domain)
721716 continue;
722717
723
- match_pr->performance->shared_type =
718
+ match_pr->performance->shared_type =
724719 pr->performance->shared_type;
725720 cpumask_copy(match_pr->performance->shared_cpu_map,
726721 pr->performance->shared_cpu_map);
....@@ -755,7 +750,7 @@
755750 {
756751 struct acpi_processor *pr;
757752
758
- if (!(acpi_processor_ppc_status & PPC_REGISTERED))
753
+ if (!acpi_processor_cpufreq_init)
759754 return -EINVAL;
760755
761756 mutex_lock(&performance_mutex);