1 | // SPDX-License-Identifier: GPL-2.0-or-later |
---|---|
2 | /* |
3 | * amd-pstate.c - AMD Processor P-state Frequency Driver |
4 | * |
5 | * Copyright (C) 2021 Advanced Micro Devices, Inc. All Rights Reserved. |
6 | * |
7 | * Author: Huang Rui <ray.huang@amd.com> |
8 | * |
9 | * AMD P-State introduces a new CPU performance scaling design for AMD |
10 | * processors using the ACPI Collaborative Performance and Power Control (CPPC) |
11 | * feature which works with the AMD SMU firmware providing a finer grained |
12 | * frequency control range. It is to replace the legacy ACPI P-States control, |
13 | * allows a flexible, low-latency interface for the Linux kernel to directly |
14 | * communicate the performance hints to hardware. |
15 | * |
16 | * AMD P-State is supported on recent AMD Zen base CPU series include some of |
17 | * Zen2 and Zen3 processors. _CPC needs to be present in the ACPI tables of AMD |
18 | * P-State supported system. And there are two types of hardware implementations |
19 | * for AMD P-State: 1) Full MSR Solution and 2) Shared Memory Solution. |
20 | * X86_FEATURE_CPPC CPU feature flag is used to distinguish the different types. |
21 | */ |
22 | |
23 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
24 | |
25 | #include <linux/bitfield.h> |
26 | #include <linux/kernel.h> |
27 | #include <linux/module.h> |
28 | #include <linux/init.h> |
29 | #include <linux/smp.h> |
30 | #include <linux/sched.h> |
31 | #include <linux/cpufreq.h> |
32 | #include <linux/compiler.h> |
33 | #include <linux/dmi.h> |
34 | #include <linux/slab.h> |
35 | #include <linux/acpi.h> |
36 | #include <linux/io.h> |
37 | #include <linux/delay.h> |
38 | #include <linux/uaccess.h> |
39 | #include <linux/static_call.h> |
40 | #include <linux/topology.h> |
41 | |
42 | #include <acpi/processor.h> |
43 | #include <acpi/cppc_acpi.h> |
44 | |
45 | #include <asm/msr.h> |
46 | #include <asm/processor.h> |
47 | #include <asm/cpufeature.h> |
48 | #include <asm/cpu_device_id.h> |
49 | |
50 | #include "amd-pstate.h" |
51 | #include "amd-pstate-trace.h" |
52 | |
53 | #define AMD_PSTATE_TRANSITION_LATENCY 20000 |
54 | #define AMD_PSTATE_TRANSITION_DELAY 1000 |
55 | #define AMD_PSTATE_FAST_CPPC_TRANSITION_DELAY 600 |
56 | |
57 | #define AMD_CPPC_EPP_PERFORMANCE 0x00 |
58 | #define AMD_CPPC_EPP_BALANCE_PERFORMANCE 0x80 |
59 | #define AMD_CPPC_EPP_BALANCE_POWERSAVE 0xBF |
60 | #define AMD_CPPC_EPP_POWERSAVE 0xFF |
61 | |
62 | static const char * const amd_pstate_mode_string[] = { |
63 | [AMD_PSTATE_UNDEFINED] = "undefined", |
64 | [AMD_PSTATE_DISABLE] = "disable", |
65 | [AMD_PSTATE_PASSIVE] = "passive", |
66 | [AMD_PSTATE_ACTIVE] = "active", |
67 | [AMD_PSTATE_GUIDED] = "guided", |
68 | NULL, |
69 | }; |
70 | |
71 | const char *amd_pstate_get_mode_string(enum amd_pstate_mode mode) |
72 | { |
73 | if (mode < 0 || mode >= AMD_PSTATE_MAX) |
74 | return NULL; |
75 | return amd_pstate_mode_string[mode]; |
76 | } |
77 | EXPORT_SYMBOL_GPL(amd_pstate_get_mode_string); |
78 | |
79 | struct quirk_entry { |
80 | u32 nominal_freq; |
81 | u32 lowest_freq; |
82 | }; |
83 | |
84 | static struct cpufreq_driver *current_pstate_driver; |
85 | static struct cpufreq_driver amd_pstate_driver; |
86 | static struct cpufreq_driver amd_pstate_epp_driver; |
87 | static int cppc_state = AMD_PSTATE_UNDEFINED; |
88 | static bool amd_pstate_prefcore = true; |
89 | static struct quirk_entry *quirks; |
90 | |
91 | /* |
92 | * AMD Energy Preference Performance (EPP) |
93 | * The EPP is used in the CCLK DPM controller to drive |
94 | * the frequency that a core is going to operate during |
95 | * short periods of activity. EPP values will be utilized for |
96 | * different OS profiles (balanced, performance, power savings) |
97 | * display strings corresponding to EPP index in the |
98 | * energy_perf_strings[] |
99 | * index String |
100 | *------------------------------------- |
101 | * 0 default |
102 | * 1 performance |
103 | * 2 balance_performance |
104 | * 3 balance_power |
105 | * 4 power |
106 | */ |
107 | enum energy_perf_value_index { |
108 | EPP_INDEX_DEFAULT = 0, |
109 | EPP_INDEX_PERFORMANCE, |
110 | EPP_INDEX_BALANCE_PERFORMANCE, |
111 | EPP_INDEX_BALANCE_POWERSAVE, |
112 | EPP_INDEX_POWERSAVE, |
113 | }; |
114 | |
115 | static const char * const energy_perf_strings[] = { |
116 | [EPP_INDEX_DEFAULT] = "default", |
117 | [EPP_INDEX_PERFORMANCE] = "performance", |
118 | [EPP_INDEX_BALANCE_PERFORMANCE] = "balance_performance", |
119 | [EPP_INDEX_BALANCE_POWERSAVE] = "balance_power", |
120 | [EPP_INDEX_POWERSAVE] = "power", |
121 | NULL |
122 | }; |
123 | |
124 | static unsigned int epp_values[] = { |
125 | [EPP_INDEX_DEFAULT] = 0, |
126 | [EPP_INDEX_PERFORMANCE] = AMD_CPPC_EPP_PERFORMANCE, |
127 | [EPP_INDEX_BALANCE_PERFORMANCE] = AMD_CPPC_EPP_BALANCE_PERFORMANCE, |
128 | [EPP_INDEX_BALANCE_POWERSAVE] = AMD_CPPC_EPP_BALANCE_POWERSAVE, |
129 | [EPP_INDEX_POWERSAVE] = AMD_CPPC_EPP_POWERSAVE, |
130 | }; |
131 | |
132 | typedef int (*cppc_mode_transition_fn)(int); |
133 | |
134 | static struct quirk_entry quirk_amd_7k62 = { |
135 | .nominal_freq = 2600, |
136 | .lowest_freq = 550, |
137 | }; |
138 | |
139 | static inline u8 freq_to_perf(union perf_cached perf, u32 nominal_freq, unsigned int freq_val) |
140 | { |
141 | u32 perf_val = DIV_ROUND_UP_ULL((u64)freq_val * perf.nominal_perf, nominal_freq); |
142 | |
143 | return (u8)clamp(perf_val, perf.lowest_perf, perf.highest_perf); |
144 | } |
145 | |
146 | static inline u32 perf_to_freq(union perf_cached perf, u32 nominal_freq, u8 perf_val) |
147 | { |
148 | return DIV_ROUND_UP_ULL((u64)nominal_freq * perf_val, |
149 | perf.nominal_perf); |
150 | } |
151 | |
152 | static int __init dmi_matched_7k62_bios_bug(const struct dmi_system_id *dmi) |
153 | { |
154 | /** |
155 | * match the broken bios for family 17h processor support CPPC V2 |
156 | * broken BIOS lack of nominal_freq and lowest_freq capabilities |
157 | * definition in ACPI tables |
158 | */ |
159 | if (cpu_feature_enabled(X86_FEATURE_ZEN2)) { |
160 | quirks = dmi->driver_data; |
161 | pr_info("Overriding nominal and lowest frequencies for %s\n", dmi->ident); |
162 | return 1; |
163 | } |
164 | |
165 | return 0; |
166 | } |
167 | |
168 | static const struct dmi_system_id amd_pstate_quirks_table[] __initconst = { |
169 | { |
170 | .callback = dmi_matched_7k62_bios_bug, |
171 | .ident = "AMD EPYC 7K62", |
172 | .matches = { |
173 | DMI_MATCH(DMI_BIOS_VERSION, "5.14"), |
174 | DMI_MATCH(DMI_BIOS_RELEASE, "12/12/2019"), |
175 | }, |
176 | .driver_data = &quirk_amd_7k62, |
177 | }, |
178 | {} |
179 | }; |
180 | MODULE_DEVICE_TABLE(dmi, amd_pstate_quirks_table); |
181 | |
182 | static inline int get_mode_idx_from_str(const char *str, size_t size) |
183 | { |
184 | int i; |
185 | |
186 | for (i=0; i < AMD_PSTATE_MAX; i++) { |
187 | if (!strncmp(str, amd_pstate_mode_string[i], size)) |
188 | return i; |
189 | } |
190 | return -EINVAL; |
191 | } |
192 | |
193 | static DEFINE_MUTEX(amd_pstate_driver_lock); |
194 | |
195 | static u8 msr_get_epp(struct amd_cpudata *cpudata) |
196 | { |
197 | u64 value; |
198 | int ret; |
199 | |
200 | ret = rdmsrq_on_cpu(cpu: cpudata->cpu, MSR_AMD_CPPC_REQ, q: &value); |
201 | if (ret < 0) { |
202 | pr_debug("Could not retrieve energy perf value (%d)\n", ret); |
203 | return ret; |
204 | } |
205 | |
206 | return FIELD_GET(AMD_CPPC_EPP_PERF_MASK, value); |
207 | } |
208 | |
209 | DEFINE_STATIC_CALL(amd_pstate_get_epp, msr_get_epp); |
210 | |
211 | static inline s16 amd_pstate_get_epp(struct amd_cpudata *cpudata) |
212 | { |
213 | return static_call(amd_pstate_get_epp)(cpudata); |
214 | } |
215 | |
216 | static u8 shmem_get_epp(struct amd_cpudata *cpudata) |
217 | { |
218 | u64 epp; |
219 | int ret; |
220 | |
221 | ret = cppc_get_epp_perf(cpunum: cpudata->cpu, epp_perf: &epp); |
222 | if (ret < 0) { |
223 | pr_debug("Could not retrieve energy perf value (%d)\n", ret); |
224 | return ret; |
225 | } |
226 | |
227 | return FIELD_GET(AMD_CPPC_EPP_PERF_MASK, epp); |
228 | } |
229 | |
230 | static int msr_update_perf(struct cpufreq_policy *policy, u8 min_perf, |
231 | u8 des_perf, u8 max_perf, u8 epp, bool fast_switch) |
232 | { |
233 | struct amd_cpudata *cpudata = policy->driver_data; |
234 | u64 value, prev; |
235 | |
236 | value = prev = READ_ONCE(cpudata->cppc_req_cached); |
237 | |
238 | value &= ~(AMD_CPPC_MAX_PERF_MASK | AMD_CPPC_MIN_PERF_MASK | |
239 | AMD_CPPC_DES_PERF_MASK | AMD_CPPC_EPP_PERF_MASK); |
240 | value |= FIELD_PREP(AMD_CPPC_MAX_PERF_MASK, max_perf); |
241 | value |= FIELD_PREP(AMD_CPPC_DES_PERF_MASK, des_perf); |
242 | value |= FIELD_PREP(AMD_CPPC_MIN_PERF_MASK, min_perf); |
243 | value |= FIELD_PREP(AMD_CPPC_EPP_PERF_MASK, epp); |
244 | |
245 | if (trace_amd_pstate_epp_perf_enabled()) { |
246 | union perf_cached perf = READ_ONCE(cpudata->perf); |
247 | |
248 | trace_amd_pstate_epp_perf(cpu_id: cpudata->cpu, |
249 | highest_perf: perf.highest_perf, |
250 | epp, |
251 | min_perf, |
252 | max_perf, |
253 | boost: policy->boost_enabled, |
254 | changed: value != prev); |
255 | } |
256 | |
257 | if (value == prev) |
258 | return 0; |
259 | |
260 | if (fast_switch) { |
261 | wrmsrq(MSR_AMD_CPPC_REQ, val: value); |
262 | return 0; |
263 | } else { |
264 | int ret = wrmsrq_on_cpu(cpu: cpudata->cpu, MSR_AMD_CPPC_REQ, q: value); |
265 | |
266 | if (ret) |
267 | return ret; |
268 | } |
269 | |
270 | WRITE_ONCE(cpudata->cppc_req_cached, value); |
271 | |
272 | return 0; |
273 | } |
274 | |
275 | DEFINE_STATIC_CALL(amd_pstate_update_perf, msr_update_perf); |
276 | |
277 | static inline int amd_pstate_update_perf(struct cpufreq_policy *policy, |
278 | u8 min_perf, u8 des_perf, |
279 | u8 max_perf, u8 epp, |
280 | bool fast_switch) |
281 | { |
282 | return static_call(amd_pstate_update_perf)(policy, min_perf, des_perf, |
283 | max_perf, epp, fast_switch); |
284 | } |
285 | |
286 | static int msr_set_epp(struct cpufreq_policy *policy, u8 epp) |
287 | { |
288 | struct amd_cpudata *cpudata = policy->driver_data; |
289 | u64 value, prev; |
290 | int ret; |
291 | |
292 | value = prev = READ_ONCE(cpudata->cppc_req_cached); |
293 | value &= ~AMD_CPPC_EPP_PERF_MASK; |
294 | value |= FIELD_PREP(AMD_CPPC_EPP_PERF_MASK, epp); |
295 | |
296 | if (trace_amd_pstate_epp_perf_enabled()) { |
297 | union perf_cached perf = cpudata->perf; |
298 | |
299 | trace_amd_pstate_epp_perf(cpu_id: cpudata->cpu, highest_perf: perf.highest_perf, |
300 | epp, |
301 | FIELD_GET(AMD_CPPC_MIN_PERF_MASK, |
302 | cpudata->cppc_req_cached), |
303 | FIELD_GET(AMD_CPPC_MAX_PERF_MASK, |
304 | cpudata->cppc_req_cached), |
305 | boost: policy->boost_enabled, |
306 | changed: value != prev); |
307 | } |
308 | |
309 | if (value == prev) |
310 | return 0; |
311 | |
312 | ret = wrmsrq_on_cpu(cpu: cpudata->cpu, MSR_AMD_CPPC_REQ, q: value); |
313 | if (ret) { |
314 | pr_err("failed to set energy perf value (%d)\n", ret); |
315 | return ret; |
316 | } |
317 | |
318 | /* update both so that msr_update_perf() can effectively check */ |
319 | WRITE_ONCE(cpudata->cppc_req_cached, value); |
320 | |
321 | return ret; |
322 | } |
323 | |
324 | DEFINE_STATIC_CALL(amd_pstate_set_epp, msr_set_epp); |
325 | |
326 | static inline int amd_pstate_set_epp(struct cpufreq_policy *policy, u8 epp) |
327 | { |
328 | return static_call(amd_pstate_set_epp)(policy, epp); |
329 | } |
330 | |
331 | static int shmem_set_epp(struct cpufreq_policy *policy, u8 epp) |
332 | { |
333 | struct amd_cpudata *cpudata = policy->driver_data; |
334 | struct cppc_perf_ctrls perf_ctrls; |
335 | u8 epp_cached; |
336 | u64 value; |
337 | int ret; |
338 | |
339 | |
340 | epp_cached = FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached); |
341 | if (trace_amd_pstate_epp_perf_enabled()) { |
342 | union perf_cached perf = cpudata->perf; |
343 | |
344 | trace_amd_pstate_epp_perf(cpu_id: cpudata->cpu, highest_perf: perf.highest_perf, |
345 | epp, |
346 | FIELD_GET(AMD_CPPC_MIN_PERF_MASK, |
347 | cpudata->cppc_req_cached), |
348 | FIELD_GET(AMD_CPPC_MAX_PERF_MASK, |
349 | cpudata->cppc_req_cached), |
350 | boost: policy->boost_enabled, |
351 | changed: epp != epp_cached); |
352 | } |
353 | |
354 | if (epp == epp_cached) |
355 | return 0; |
356 | |
357 | perf_ctrls.energy_perf = epp; |
358 | ret = cppc_set_epp_perf(cpu: cpudata->cpu, perf_ctrls: &perf_ctrls, enable: 1); |
359 | if (ret) { |
360 | pr_debug("failed to set energy perf value (%d)\n", ret); |
361 | return ret; |
362 | } |
363 | |
364 | value = READ_ONCE(cpudata->cppc_req_cached); |
365 | value &= ~AMD_CPPC_EPP_PERF_MASK; |
366 | value |= FIELD_PREP(AMD_CPPC_EPP_PERF_MASK, epp); |
367 | WRITE_ONCE(cpudata->cppc_req_cached, value); |
368 | |
369 | return ret; |
370 | } |
371 | |
372 | static inline int msr_cppc_enable(struct cpufreq_policy *policy) |
373 | { |
374 | return wrmsrq_safe_on_cpu(cpu: policy->cpu, MSR_AMD_CPPC_ENABLE, q: 1); |
375 | } |
376 | |
377 | static int shmem_cppc_enable(struct cpufreq_policy *policy) |
378 | { |
379 | return cppc_set_enable(cpu: policy->cpu, enable: 1); |
380 | } |
381 | |
382 | DEFINE_STATIC_CALL(amd_pstate_cppc_enable, msr_cppc_enable); |
383 | |
384 | static inline int amd_pstate_cppc_enable(struct cpufreq_policy *policy) |
385 | { |
386 | return static_call(amd_pstate_cppc_enable)(policy); |
387 | } |
388 | |
389 | static int msr_init_perf(struct amd_cpudata *cpudata) |
390 | { |
391 | union perf_cached perf = READ_ONCE(cpudata->perf); |
392 | u64 cap1, numerator, cppc_req; |
393 | u8 min_perf; |
394 | |
395 | int ret = rdmsrq_safe_on_cpu(cpu: cpudata->cpu, MSR_AMD_CPPC_CAP1, |
396 | q: &cap1); |
397 | if (ret) |
398 | return ret; |
399 | |
400 | ret = amd_get_boost_ratio_numerator(cpu: cpudata->cpu, numerator: &numerator); |
401 | if (ret) |
402 | return ret; |
403 | |
404 | ret = rdmsrl_on_cpu(cpudata->cpu, MSR_AMD_CPPC_REQ, &cppc_req); |
405 | if (ret) |
406 | return ret; |
407 | |
408 | WRITE_ONCE(cpudata->cppc_req_cached, cppc_req); |
409 | min_perf = FIELD_GET(AMD_CPPC_MIN_PERF_MASK, cppc_req); |
410 | |
411 | /* |
412 | * Clear out the min_perf part to check if the rest of the MSR is 0, if yes, this is an |
413 | * indication that the min_perf value is the one specified through the BIOS option |
414 | */ |
415 | cppc_req &= ~(AMD_CPPC_MIN_PERF_MASK); |
416 | |
417 | if (!cppc_req) |
418 | perf.bios_min_perf = min_perf; |
419 | |
420 | perf.highest_perf = numerator; |
421 | perf.max_limit_perf = numerator; |
422 | perf.min_limit_perf = FIELD_GET(AMD_CPPC_LOWEST_PERF_MASK, cap1); |
423 | perf.nominal_perf = FIELD_GET(AMD_CPPC_NOMINAL_PERF_MASK, cap1); |
424 | perf.lowest_nonlinear_perf = FIELD_GET(AMD_CPPC_LOWNONLIN_PERF_MASK, cap1); |
425 | perf.lowest_perf = FIELD_GET(AMD_CPPC_LOWEST_PERF_MASK, cap1); |
426 | WRITE_ONCE(cpudata->perf, perf); |
427 | WRITE_ONCE(cpudata->prefcore_ranking, FIELD_GET(AMD_CPPC_HIGHEST_PERF_MASK, cap1)); |
428 | |
429 | return 0; |
430 | } |
431 | |
432 | static int shmem_init_perf(struct amd_cpudata *cpudata) |
433 | { |
434 | struct cppc_perf_caps cppc_perf; |
435 | union perf_cached perf = READ_ONCE(cpudata->perf); |
436 | u64 numerator; |
437 | bool auto_sel; |
438 | |
439 | int ret = cppc_get_perf_caps(cpu: cpudata->cpu, caps: &cppc_perf); |
440 | if (ret) |
441 | return ret; |
442 | |
443 | ret = amd_get_boost_ratio_numerator(cpu: cpudata->cpu, numerator: &numerator); |
444 | if (ret) |
445 | return ret; |
446 | |
447 | perf.highest_perf = numerator; |
448 | perf.max_limit_perf = numerator; |
449 | perf.min_limit_perf = cppc_perf.lowest_perf; |
450 | perf.nominal_perf = cppc_perf.nominal_perf; |
451 | perf.lowest_nonlinear_perf = cppc_perf.lowest_nonlinear_perf; |
452 | perf.lowest_perf = cppc_perf.lowest_perf; |
453 | WRITE_ONCE(cpudata->perf, perf); |
454 | WRITE_ONCE(cpudata->prefcore_ranking, cppc_perf.highest_perf); |
455 | |
456 | if (cppc_state == AMD_PSTATE_ACTIVE) |
457 | return 0; |
458 | |
459 | ret = cppc_get_auto_sel(cpu: cpudata->cpu, enable: &auto_sel); |
460 | if (ret) { |
461 | pr_warn("failed to get auto_sel, ret: %d\n", ret); |
462 | return 0; |
463 | } |
464 | |
465 | ret = cppc_set_auto_sel(cpu: cpudata->cpu, |
466 | enable: (cppc_state == AMD_PSTATE_PASSIVE) ? 0 : 1); |
467 | |
468 | if (ret) |
469 | pr_warn("failed to set auto_sel, ret: %d\n", ret); |
470 | |
471 | return ret; |
472 | } |
473 | |
474 | DEFINE_STATIC_CALL(amd_pstate_init_perf, msr_init_perf); |
475 | |
476 | static inline int amd_pstate_init_perf(struct amd_cpudata *cpudata) |
477 | { |
478 | return static_call(amd_pstate_init_perf)(cpudata); |
479 | } |
480 | |
481 | static int shmem_update_perf(struct cpufreq_policy *policy, u8 min_perf, |
482 | u8 des_perf, u8 max_perf, u8 epp, bool fast_switch) |
483 | { |
484 | struct amd_cpudata *cpudata = policy->driver_data; |
485 | struct cppc_perf_ctrls perf_ctrls; |
486 | u64 value, prev; |
487 | int ret; |
488 | |
489 | if (cppc_state == AMD_PSTATE_ACTIVE) { |
490 | int ret = shmem_set_epp(policy, epp); |
491 | |
492 | if (ret) |
493 | return ret; |
494 | } |
495 | |
496 | value = prev = READ_ONCE(cpudata->cppc_req_cached); |
497 | |
498 | value &= ~(AMD_CPPC_MAX_PERF_MASK | AMD_CPPC_MIN_PERF_MASK | |
499 | AMD_CPPC_DES_PERF_MASK | AMD_CPPC_EPP_PERF_MASK); |
500 | value |= FIELD_PREP(AMD_CPPC_MAX_PERF_MASK, max_perf); |
501 | value |= FIELD_PREP(AMD_CPPC_DES_PERF_MASK, des_perf); |
502 | value |= FIELD_PREP(AMD_CPPC_MIN_PERF_MASK, min_perf); |
503 | value |= FIELD_PREP(AMD_CPPC_EPP_PERF_MASK, epp); |
504 | |
505 | if (trace_amd_pstate_epp_perf_enabled()) { |
506 | union perf_cached perf = READ_ONCE(cpudata->perf); |
507 | |
508 | trace_amd_pstate_epp_perf(cpu_id: cpudata->cpu, |
509 | highest_perf: perf.highest_perf, |
510 | epp, |
511 | min_perf, |
512 | max_perf, |
513 | boost: policy->boost_enabled, |
514 | changed: value != prev); |
515 | } |
516 | |
517 | if (value == prev) |
518 | return 0; |
519 | |
520 | perf_ctrls.max_perf = max_perf; |
521 | perf_ctrls.min_perf = min_perf; |
522 | perf_ctrls.desired_perf = des_perf; |
523 | |
524 | ret = cppc_set_perf(cpu: cpudata->cpu, perf_ctrls: &perf_ctrls); |
525 | if (ret) |
526 | return ret; |
527 | |
528 | WRITE_ONCE(cpudata->cppc_req_cached, value); |
529 | |
530 | return 0; |
531 | } |
532 | |
533 | static inline bool amd_pstate_sample(struct amd_cpudata *cpudata) |
534 | { |
535 | u64 aperf, mperf, tsc; |
536 | unsigned long flags; |
537 | |
538 | local_irq_save(flags); |
539 | rdmsrq(MSR_IA32_APERF, aperf); |
540 | rdmsrq(MSR_IA32_MPERF, mperf); |
541 | tsc = rdtsc(); |
542 | |
543 | if (cpudata->prev.mperf == mperf || cpudata->prev.tsc == tsc) { |
544 | local_irq_restore(flags); |
545 | return false; |
546 | } |
547 | |
548 | local_irq_restore(flags); |
549 | |
550 | cpudata->cur.aperf = aperf; |
551 | cpudata->cur.mperf = mperf; |
552 | cpudata->cur.tsc = tsc; |
553 | cpudata->cur.aperf -= cpudata->prev.aperf; |
554 | cpudata->cur.mperf -= cpudata->prev.mperf; |
555 | cpudata->cur.tsc -= cpudata->prev.tsc; |
556 | |
557 | cpudata->prev.aperf = aperf; |
558 | cpudata->prev.mperf = mperf; |
559 | cpudata->prev.tsc = tsc; |
560 | |
561 | cpudata->freq = div64_u64(dividend: (cpudata->cur.aperf * cpu_khz), divisor: cpudata->cur.mperf); |
562 | |
563 | return true; |
564 | } |
565 | |
566 | static void amd_pstate_update(struct amd_cpudata *cpudata, u8 min_perf, |
567 | u8 des_perf, u8 max_perf, bool fast_switch, int gov_flags) |
568 | { |
569 | struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu: cpudata->cpu); |
570 | union perf_cached perf = READ_ONCE(cpudata->perf); |
571 | |
572 | if (!policy) |
573 | return; |
574 | |
575 | /* limit the max perf when core performance boost feature is disabled */ |
576 | if (!cpudata->boost_supported) |
577 | max_perf = min_t(u8, perf.nominal_perf, max_perf); |
578 | |
579 | des_perf = clamp_t(u8, des_perf, min_perf, max_perf); |
580 | |
581 | policy->cur = perf_to_freq(perf, nominal_freq: cpudata->nominal_freq, perf_val: des_perf); |
582 | |
583 | if ((cppc_state == AMD_PSTATE_GUIDED) && (gov_flags & CPUFREQ_GOV_DYNAMIC_SWITCHING)) { |
584 | min_perf = des_perf; |
585 | des_perf = 0; |
586 | } |
587 | |
588 | if (trace_amd_pstate_perf_enabled() && amd_pstate_sample(cpudata)) { |
589 | trace_amd_pstate_perf(min_perf, target_perf: des_perf, capacity: max_perf, freq: cpudata->freq, |
590 | mperf: cpudata->cur.mperf, aperf: cpudata->cur.aperf, tsc: cpudata->cur.tsc, |
591 | cpu_id: cpudata->cpu, fast_switch); |
592 | } |
593 | |
594 | amd_pstate_update_perf(policy, min_perf, des_perf, max_perf, epp: 0, fast_switch); |
595 | } |
596 | |
597 | static int amd_pstate_verify(struct cpufreq_policy_data *policy_data) |
598 | { |
599 | /* |
600 | * Initialize lower frequency limit (i.e.policy->min) with |
601 | * lowest_nonlinear_frequency or the min frequency (if) specified in BIOS, |
602 | * Override the initial value set by cpufreq core and amd-pstate qos_requests. |
603 | */ |
604 | if (policy_data->min == FREQ_QOS_MIN_DEFAULT_VALUE) { |
605 | struct cpufreq_policy *policy __free(put_cpufreq_policy) = |
606 | cpufreq_cpu_get(cpu: policy_data->cpu); |
607 | struct amd_cpudata *cpudata; |
608 | union perf_cached perf; |
609 | |
610 | if (!policy) |
611 | return -EINVAL; |
612 | |
613 | cpudata = policy->driver_data; |
614 | perf = READ_ONCE(cpudata->perf); |
615 | |
616 | if (perf.bios_min_perf) |
617 | policy_data->min = perf_to_freq(perf, nominal_freq: cpudata->nominal_freq, |
618 | perf_val: perf.bios_min_perf); |
619 | else |
620 | policy_data->min = cpudata->lowest_nonlinear_freq; |
621 | } |
622 | |
623 | cpufreq_verify_within_cpu_limits(policy: policy_data); |
624 | |
625 | return 0; |
626 | } |
627 | |
628 | static void amd_pstate_update_min_max_limit(struct cpufreq_policy *policy) |
629 | { |
630 | struct amd_cpudata *cpudata = policy->driver_data; |
631 | union perf_cached perf = READ_ONCE(cpudata->perf); |
632 | |
633 | perf.max_limit_perf = freq_to_perf(perf, nominal_freq: cpudata->nominal_freq, freq_val: policy->max); |
634 | WRITE_ONCE(cpudata->max_limit_freq, policy->max); |
635 | |
636 | if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) { |
637 | perf.min_limit_perf = min(perf.nominal_perf, perf.max_limit_perf); |
638 | WRITE_ONCE(cpudata->min_limit_freq, min(cpudata->nominal_freq, cpudata->max_limit_freq)); |
639 | } else { |
640 | perf.min_limit_perf = freq_to_perf(perf, nominal_freq: cpudata->nominal_freq, freq_val: policy->min); |
641 | WRITE_ONCE(cpudata->min_limit_freq, policy->min); |
642 | } |
643 | |
644 | WRITE_ONCE(cpudata->perf, perf); |
645 | } |
646 | |
647 | static int amd_pstate_update_freq(struct cpufreq_policy *policy, |
648 | unsigned int target_freq, bool fast_switch) |
649 | { |
650 | struct cpufreq_freqs freqs; |
651 | struct amd_cpudata *cpudata; |
652 | union perf_cached perf; |
653 | u8 des_perf; |
654 | |
655 | cpudata = policy->driver_data; |
656 | |
657 | if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq) |
658 | amd_pstate_update_min_max_limit(policy); |
659 | |
660 | perf = READ_ONCE(cpudata->perf); |
661 | |
662 | freqs.old = policy->cur; |
663 | freqs.new = target_freq; |
664 | |
665 | des_perf = freq_to_perf(perf, nominal_freq: cpudata->nominal_freq, freq_val: target_freq); |
666 | |
667 | WARN_ON(fast_switch && !policy->fast_switch_enabled); |
668 | /* |
669 | * If fast_switch is desired, then there aren't any registered |
670 | * transition notifiers. See comment for |
671 | * cpufreq_enable_fast_switch(). |
672 | */ |
673 | if (!fast_switch) |
674 | cpufreq_freq_transition_begin(policy, freqs: &freqs); |
675 | |
676 | amd_pstate_update(cpudata, min_perf: perf.min_limit_perf, des_perf, |
677 | max_perf: perf.max_limit_perf, fast_switch, |
678 | gov_flags: policy->governor->flags); |
679 | |
680 | if (!fast_switch) |
681 | cpufreq_freq_transition_end(policy, freqs: &freqs, transition_failed: false); |
682 | |
683 | return 0; |
684 | } |
685 | |
686 | static int amd_pstate_target(struct cpufreq_policy *policy, |
687 | unsigned int target_freq, |
688 | unsigned int relation) |
689 | { |
690 | return amd_pstate_update_freq(policy, target_freq, fast_switch: false); |
691 | } |
692 | |
693 | static unsigned int amd_pstate_fast_switch(struct cpufreq_policy *policy, |
694 | unsigned int target_freq) |
695 | { |
696 | if (!amd_pstate_update_freq(policy, target_freq, fast_switch: true)) |
697 | return target_freq; |
698 | return policy->cur; |
699 | } |
700 | |
701 | static void amd_pstate_adjust_perf(unsigned int cpu, |
702 | unsigned long _min_perf, |
703 | unsigned long target_perf, |
704 | unsigned long capacity) |
705 | { |
706 | u8 max_perf, min_perf, des_perf, cap_perf; |
707 | struct cpufreq_policy *policy __free(put_cpufreq_policy) = cpufreq_cpu_get(cpu); |
708 | struct amd_cpudata *cpudata; |
709 | union perf_cached perf; |
710 | |
711 | if (!policy) |
712 | return; |
713 | |
714 | cpudata = policy->driver_data; |
715 | |
716 | if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq) |
717 | amd_pstate_update_min_max_limit(policy); |
718 | |
719 | perf = READ_ONCE(cpudata->perf); |
720 | cap_perf = perf.highest_perf; |
721 | |
722 | des_perf = cap_perf; |
723 | if (target_perf < capacity) |
724 | des_perf = DIV_ROUND_UP(cap_perf * target_perf, capacity); |
725 | |
726 | if (_min_perf < capacity) |
727 | min_perf = DIV_ROUND_UP(cap_perf * _min_perf, capacity); |
728 | else |
729 | min_perf = cap_perf; |
730 | |
731 | if (min_perf < perf.min_limit_perf) |
732 | min_perf = perf.min_limit_perf; |
733 | |
734 | max_perf = perf.max_limit_perf; |
735 | if (max_perf < min_perf) |
736 | max_perf = min_perf; |
737 | |
738 | amd_pstate_update(cpudata, min_perf, des_perf, max_perf, fast_switch: true, |
739 | gov_flags: policy->governor->flags); |
740 | } |
741 | |
742 | static int amd_pstate_cpu_boost_update(struct cpufreq_policy *policy, bool on) |
743 | { |
744 | struct amd_cpudata *cpudata = policy->driver_data; |
745 | union perf_cached perf = READ_ONCE(cpudata->perf); |
746 | u32 nominal_freq, max_freq; |
747 | int ret = 0; |
748 | |
749 | nominal_freq = READ_ONCE(cpudata->nominal_freq); |
750 | max_freq = perf_to_freq(perf, nominal_freq: cpudata->nominal_freq, perf_val: perf.highest_perf); |
751 | |
752 | if (on) |
753 | policy->cpuinfo.max_freq = max_freq; |
754 | else if (policy->cpuinfo.max_freq > nominal_freq) |
755 | policy->cpuinfo.max_freq = nominal_freq; |
756 | |
757 | policy->max = policy->cpuinfo.max_freq; |
758 | |
759 | if (cppc_state == AMD_PSTATE_PASSIVE) { |
760 | ret = freq_qos_update_request(req: &cpudata->req[1], new_value: policy->cpuinfo.max_freq); |
761 | if (ret < 0) |
762 | pr_debug("Failed to update freq constraint: CPU%d\n", cpudata->cpu); |
763 | } |
764 | |
765 | return ret < 0 ? ret : 0; |
766 | } |
767 | |
768 | static int amd_pstate_set_boost(struct cpufreq_policy *policy, int state) |
769 | { |
770 | struct amd_cpudata *cpudata = policy->driver_data; |
771 | int ret; |
772 | |
773 | if (!cpudata->boost_supported) { |
774 | pr_err("Boost mode is not supported by this processor or SBIOS\n"); |
775 | return -EOPNOTSUPP; |
776 | } |
777 | |
778 | ret = amd_pstate_cpu_boost_update(policy, on: state); |
779 | refresh_frequency_limits(policy); |
780 | |
781 | return ret; |
782 | } |
783 | |
784 | static int amd_pstate_init_boost_support(struct amd_cpudata *cpudata) |
785 | { |
786 | u64 boost_val; |
787 | int ret = -1; |
788 | |
789 | /* |
790 | * If platform has no CPB support or disable it, initialize current driver |
791 | * boost_enabled state to be false, it is not an error for cpufreq core to handle. |
792 | */ |
793 | if (!cpu_feature_enabled(X86_FEATURE_CPB)) { |
794 | pr_debug_once("Boost CPB capabilities not present in the processor\n"); |
795 | ret = 0; |
796 | goto exit_err; |
797 | } |
798 | |
799 | ret = rdmsrq_on_cpu(cpu: cpudata->cpu, MSR_K7_HWCR, q: &boost_val); |
800 | if (ret) { |
801 | pr_err_once("failed to read initial CPU boost state!\n"); |
802 | ret = -EIO; |
803 | goto exit_err; |
804 | } |
805 | |
806 | if (!(boost_val & MSR_K7_HWCR_CPB_DIS)) |
807 | cpudata->boost_supported = true; |
808 | |
809 | return 0; |
810 | |
811 | exit_err: |
812 | cpudata->boost_supported = false; |
813 | return ret; |
814 | } |
815 | |
816 | static void amd_perf_ctl_reset(unsigned int cpu) |
817 | { |
818 | wrmsrq_on_cpu(cpu, MSR_AMD_PERF_CTL, q: 0); |
819 | } |
820 | |
821 | #define CPPC_MAX_PERF U8_MAX |
822 | |
823 | static void amd_pstate_init_prefcore(struct amd_cpudata *cpudata) |
824 | { |
825 | /* user disabled or not detected */ |
826 | if (!amd_pstate_prefcore) |
827 | return; |
828 | |
829 | cpudata->hw_prefcore = true; |
830 | |
831 | /* Priorities must be initialized before ITMT support can be toggled on. */ |
832 | sched_set_itmt_core_prio(prio: (int)READ_ONCE(cpudata->prefcore_ranking), core_cpu: cpudata->cpu); |
833 | } |
834 | |
835 | static void amd_pstate_update_limits(struct cpufreq_policy *policy) |
836 | { |
837 | struct amd_cpudata *cpudata; |
838 | u32 prev_high = 0, cur_high = 0; |
839 | bool highest_perf_changed = false; |
840 | unsigned int cpu = policy->cpu; |
841 | |
842 | if (!amd_pstate_prefcore) |
843 | return; |
844 | |
845 | if (amd_get_highest_perf(cpu, highest_perf: &cur_high)) |
846 | return; |
847 | |
848 | cpudata = policy->driver_data; |
849 | |
850 | prev_high = READ_ONCE(cpudata->prefcore_ranking); |
851 | highest_perf_changed = (prev_high != cur_high); |
852 | if (highest_perf_changed) { |
853 | WRITE_ONCE(cpudata->prefcore_ranking, cur_high); |
854 | |
855 | if (cur_high < CPPC_MAX_PERF) { |
856 | sched_set_itmt_core_prio(prio: (int)cur_high, core_cpu: cpu); |
857 | sched_update_asym_prefer_cpu(cpu, old_prio: prev_high, new_prio: cur_high); |
858 | } |
859 | } |
860 | } |
861 | |
862 | /* |
863 | * Get pstate transition delay time from ACPI tables that firmware set |
864 | * instead of using hardcode value directly. |
865 | */ |
866 | static u32 amd_pstate_get_transition_delay_us(unsigned int cpu) |
867 | { |
868 | u32 transition_delay_ns; |
869 | |
870 | transition_delay_ns = cppc_get_transition_latency(cpu); |
871 | if (transition_delay_ns == CPUFREQ_ETERNAL) { |
872 | if (cpu_feature_enabled(X86_FEATURE_AMD_FAST_CPPC)) |
873 | return AMD_PSTATE_FAST_CPPC_TRANSITION_DELAY; |
874 | else |
875 | return AMD_PSTATE_TRANSITION_DELAY; |
876 | } |
877 | |
878 | return transition_delay_ns / NSEC_PER_USEC; |
879 | } |
880 | |
881 | /* |
882 | * Get pstate transition latency value from ACPI tables that firmware |
883 | * set instead of using hardcode value directly. |
884 | */ |
885 | static u32 amd_pstate_get_transition_latency(unsigned int cpu) |
886 | { |
887 | u32 transition_latency; |
888 | |
889 | transition_latency = cppc_get_transition_latency(cpu); |
890 | if (transition_latency == CPUFREQ_ETERNAL) |
891 | return AMD_PSTATE_TRANSITION_LATENCY; |
892 | |
893 | return transition_latency; |
894 | } |
895 | |
896 | /* |
897 | * amd_pstate_init_freq: Initialize the nominal_freq and lowest_nonlinear_freq |
898 | * for the @cpudata object. |
899 | * |
900 | * Requires: all perf members of @cpudata to be initialized. |
901 | * |
902 | * Returns 0 on success, non-zero value on failure. |
903 | */ |
904 | static int amd_pstate_init_freq(struct amd_cpudata *cpudata) |
905 | { |
906 | u32 min_freq, max_freq, nominal_freq, lowest_nonlinear_freq; |
907 | struct cppc_perf_caps cppc_perf; |
908 | union perf_cached perf; |
909 | int ret; |
910 | |
911 | ret = cppc_get_perf_caps(cpu: cpudata->cpu, caps: &cppc_perf); |
912 | if (ret) |
913 | return ret; |
914 | perf = READ_ONCE(cpudata->perf); |
915 | |
916 | if (quirks && quirks->nominal_freq) |
917 | nominal_freq = quirks->nominal_freq; |
918 | else |
919 | nominal_freq = cppc_perf.nominal_freq; |
920 | nominal_freq *= 1000; |
921 | |
922 | if (quirks && quirks->lowest_freq) { |
923 | min_freq = quirks->lowest_freq; |
924 | perf.lowest_perf = freq_to_perf(perf, nominal_freq, freq_val: min_freq); |
925 | WRITE_ONCE(cpudata->perf, perf); |
926 | } else |
927 | min_freq = cppc_perf.lowest_freq; |
928 | |
929 | min_freq *= 1000; |
930 | |
931 | WRITE_ONCE(cpudata->nominal_freq, nominal_freq); |
932 | |
933 | max_freq = perf_to_freq(perf, nominal_freq, perf_val: perf.highest_perf); |
934 | lowest_nonlinear_freq = perf_to_freq(perf, nominal_freq, perf_val: perf.lowest_nonlinear_perf); |
935 | WRITE_ONCE(cpudata->lowest_nonlinear_freq, lowest_nonlinear_freq); |
936 | |
937 | /** |
938 | * Below values need to be initialized correctly, otherwise driver will fail to load |
939 | * max_freq is calculated according to (nominal_freq * highest_perf)/nominal_perf |
940 | * lowest_nonlinear_freq is a value between [min_freq, nominal_freq] |
941 | * Check _CPC in ACPI table objects if any values are incorrect |
942 | */ |
943 | if (min_freq <= 0 || max_freq <= 0 || nominal_freq <= 0 || min_freq > max_freq) { |
944 | pr_err("min_freq(%d) or max_freq(%d) or nominal_freq(%d) value is incorrect\n", |
945 | min_freq, max_freq, nominal_freq); |
946 | return -EINVAL; |
947 | } |
948 | |
949 | if (lowest_nonlinear_freq <= min_freq || lowest_nonlinear_freq > nominal_freq) { |
950 | pr_err("lowest_nonlinear_freq(%d) value is out of range [min_freq(%d), nominal_freq(%d)]\n", |
951 | lowest_nonlinear_freq, min_freq, nominal_freq); |
952 | return -EINVAL; |
953 | } |
954 | |
955 | return 0; |
956 | } |
957 | |
958 | static int amd_pstate_cpu_init(struct cpufreq_policy *policy) |
959 | { |
960 | struct amd_cpudata *cpudata; |
961 | union perf_cached perf; |
962 | struct device *dev; |
963 | int ret; |
964 | |
965 | /* |
966 | * Resetting PERF_CTL_MSR will put the CPU in P0 frequency, |
967 | * which is ideal for initialization process. |
968 | */ |
969 | amd_perf_ctl_reset(cpu: policy->cpu); |
970 | dev = get_cpu_device(cpu: policy->cpu); |
971 | if (!dev) |
972 | return -ENODEV; |
973 | |
974 | cpudata = kzalloc(sizeof(*cpudata), GFP_KERNEL); |
975 | if (!cpudata) |
976 | return -ENOMEM; |
977 | |
978 | cpudata->cpu = policy->cpu; |
979 | |
980 | ret = amd_pstate_init_perf(cpudata); |
981 | if (ret) |
982 | goto free_cpudata1; |
983 | |
984 | amd_pstate_init_prefcore(cpudata); |
985 | |
986 | ret = amd_pstate_init_freq(cpudata); |
987 | if (ret) |
988 | goto free_cpudata1; |
989 | |
990 | ret = amd_pstate_init_boost_support(cpudata); |
991 | if (ret) |
992 | goto free_cpudata1; |
993 | |
994 | policy->cpuinfo.transition_latency = amd_pstate_get_transition_latency(cpu: policy->cpu); |
995 | policy->transition_delay_us = amd_pstate_get_transition_delay_us(cpu: policy->cpu); |
996 | |
997 | perf = READ_ONCE(cpudata->perf); |
998 | |
999 | policy->cpuinfo.min_freq = policy->min = perf_to_freq(perf, |
1000 | nominal_freq: cpudata->nominal_freq, |
1001 | perf_val: perf.lowest_perf); |
1002 | policy->cpuinfo.max_freq = policy->max = perf_to_freq(perf, |
1003 | nominal_freq: cpudata->nominal_freq, |
1004 | perf_val: perf.highest_perf); |
1005 | |
1006 | ret = amd_pstate_cppc_enable(policy); |
1007 | if (ret) |
1008 | goto free_cpudata1; |
1009 | |
1010 | policy->boost_supported = READ_ONCE(cpudata->boost_supported); |
1011 | |
1012 | /* It will be updated by governor */ |
1013 | policy->cur = policy->cpuinfo.min_freq; |
1014 | |
1015 | if (cpu_feature_enabled(X86_FEATURE_CPPC)) |
1016 | policy->fast_switch_possible = true; |
1017 | |
1018 | ret = freq_qos_add_request(qos: &policy->constraints, req: &cpudata->req[0], |
1019 | type: FREQ_QOS_MIN, FREQ_QOS_MIN_DEFAULT_VALUE); |
1020 | if (ret < 0) { |
1021 | dev_err(dev, "Failed to add min-freq constraint (%d)\n", ret); |
1022 | goto free_cpudata1; |
1023 | } |
1024 | |
1025 | ret = freq_qos_add_request(qos: &policy->constraints, req: &cpudata->req[1], |
1026 | type: FREQ_QOS_MAX, value: policy->cpuinfo.max_freq); |
1027 | if (ret < 0) { |
1028 | dev_err(dev, "Failed to add max-freq constraint (%d)\n", ret); |
1029 | goto free_cpudata2; |
1030 | } |
1031 | |
1032 | policy->driver_data = cpudata; |
1033 | |
1034 | if (!current_pstate_driver->adjust_perf) |
1035 | current_pstate_driver->adjust_perf = amd_pstate_adjust_perf; |
1036 | |
1037 | return 0; |
1038 | |
1039 | free_cpudata2: |
1040 | freq_qos_remove_request(req: &cpudata->req[0]); |
1041 | free_cpudata1: |
1042 | pr_warn("Failed to initialize CPU %d: %d\n", policy->cpu, ret); |
1043 | kfree(objp: cpudata); |
1044 | return ret; |
1045 | } |
1046 | |
1047 | static void amd_pstate_cpu_exit(struct cpufreq_policy *policy) |
1048 | { |
1049 | struct amd_cpudata *cpudata = policy->driver_data; |
1050 | union perf_cached perf = READ_ONCE(cpudata->perf); |
1051 | |
1052 | /* Reset CPPC_REQ MSR to the BIOS value */ |
1053 | amd_pstate_update_perf(policy, min_perf: perf.bios_min_perf, des_perf: 0U, max_perf: 0U, epp: 0U, fast_switch: false); |
1054 | |
1055 | freq_qos_remove_request(req: &cpudata->req[1]); |
1056 | freq_qos_remove_request(req: &cpudata->req[0]); |
1057 | policy->fast_switch_possible = false; |
1058 | kfree(objp: cpudata); |
1059 | } |
1060 | |
1061 | /* Sysfs attributes */ |
1062 | |
1063 | /* |
1064 | * This frequency is to indicate the maximum hardware frequency. |
1065 | * If boost is not active but supported, the frequency will be larger than the |
1066 | * one in cpuinfo. |
1067 | */ |
1068 | static ssize_t show_amd_pstate_max_freq(struct cpufreq_policy *policy, |
1069 | char *buf) |
1070 | { |
1071 | struct amd_cpudata *cpudata; |
1072 | union perf_cached perf; |
1073 | |
1074 | cpudata = policy->driver_data; |
1075 | perf = READ_ONCE(cpudata->perf); |
1076 | |
1077 | return sysfs_emit(buf, fmt: "%u\n", |
1078 | perf_to_freq(perf, nominal_freq: cpudata->nominal_freq, perf_val: perf.highest_perf)); |
1079 | } |
1080 | |
1081 | static ssize_t show_amd_pstate_lowest_nonlinear_freq(struct cpufreq_policy *policy, |
1082 | char *buf) |
1083 | { |
1084 | struct amd_cpudata *cpudata; |
1085 | union perf_cached perf; |
1086 | |
1087 | cpudata = policy->driver_data; |
1088 | perf = READ_ONCE(cpudata->perf); |
1089 | |
1090 | return sysfs_emit(buf, fmt: "%u\n", |
1091 | perf_to_freq(perf, nominal_freq: cpudata->nominal_freq, perf_val: perf.lowest_nonlinear_perf)); |
1092 | } |
1093 | |
1094 | /* |
1095 | * In some of ASICs, the highest_perf is not the one in the _CPC table, so we |
1096 | * need to expose it to sysfs. |
1097 | */ |
1098 | static ssize_t show_amd_pstate_highest_perf(struct cpufreq_policy *policy, |
1099 | char *buf) |
1100 | { |
1101 | struct amd_cpudata *cpudata; |
1102 | |
1103 | cpudata = policy->driver_data; |
1104 | |
1105 | return sysfs_emit(buf, fmt: "%u\n", cpudata->perf.highest_perf); |
1106 | } |
1107 | |
1108 | static ssize_t show_amd_pstate_prefcore_ranking(struct cpufreq_policy *policy, |
1109 | char *buf) |
1110 | { |
1111 | u8 perf; |
1112 | struct amd_cpudata *cpudata = policy->driver_data; |
1113 | |
1114 | perf = READ_ONCE(cpudata->prefcore_ranking); |
1115 | |
1116 | return sysfs_emit(buf, fmt: "%u\n", perf); |
1117 | } |
1118 | |
1119 | static ssize_t show_amd_pstate_hw_prefcore(struct cpufreq_policy *policy, |
1120 | char *buf) |
1121 | { |
1122 | bool hw_prefcore; |
1123 | struct amd_cpudata *cpudata = policy->driver_data; |
1124 | |
1125 | hw_prefcore = READ_ONCE(cpudata->hw_prefcore); |
1126 | |
1127 | return sysfs_emit(buf, fmt: "%s\n", str_enabled_disabled(v: hw_prefcore)); |
1128 | } |
1129 | |
1130 | static ssize_t show_energy_performance_available_preferences( |
1131 | struct cpufreq_policy *policy, char *buf) |
1132 | { |
1133 | int i = 0; |
1134 | int offset = 0; |
1135 | struct amd_cpudata *cpudata = policy->driver_data; |
1136 | |
1137 | if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) |
1138 | return sysfs_emit_at(buf, at: offset, fmt: "%s\n", |
1139 | energy_perf_strings[EPP_INDEX_PERFORMANCE]); |
1140 | |
1141 | while (energy_perf_strings[i] != NULL) |
1142 | offset += sysfs_emit_at(buf, at: offset, fmt: "%s ", energy_perf_strings[i++]); |
1143 | |
1144 | offset += sysfs_emit_at(buf, at: offset, fmt: "\n"); |
1145 | |
1146 | return offset; |
1147 | } |
1148 | |
1149 | static ssize_t store_energy_performance_preference( |
1150 | struct cpufreq_policy *policy, const char *buf, size_t count) |
1151 | { |
1152 | struct amd_cpudata *cpudata = policy->driver_data; |
1153 | char str_preference[21]; |
1154 | ssize_t ret; |
1155 | u8 epp; |
1156 | |
1157 | ret = sscanf(buf, "%20s", str_preference); |
1158 | if (ret != 1) |
1159 | return -EINVAL; |
1160 | |
1161 | ret = match_string(array: energy_perf_strings, n: -1, string: str_preference); |
1162 | if (ret < 0) |
1163 | return -EINVAL; |
1164 | |
1165 | if (!ret) |
1166 | epp = cpudata->epp_default; |
1167 | else |
1168 | epp = epp_values[ret]; |
1169 | |
1170 | if (epp > 0 && policy->policy == CPUFREQ_POLICY_PERFORMANCE) { |
1171 | pr_debug("EPP cannot be set under performance policy\n"); |
1172 | return -EBUSY; |
1173 | } |
1174 | |
1175 | ret = amd_pstate_set_epp(policy, epp); |
1176 | |
1177 | return ret ? ret : count; |
1178 | } |
1179 | |
1180 | static ssize_t show_energy_performance_preference( |
1181 | struct cpufreq_policy *policy, char *buf) |
1182 | { |
1183 | struct amd_cpudata *cpudata = policy->driver_data; |
1184 | u8 preference, epp; |
1185 | |
1186 | epp = FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached); |
1187 | |
1188 | switch (epp) { |
1189 | case AMD_CPPC_EPP_PERFORMANCE: |
1190 | preference = EPP_INDEX_PERFORMANCE; |
1191 | break; |
1192 | case AMD_CPPC_EPP_BALANCE_PERFORMANCE: |
1193 | preference = EPP_INDEX_BALANCE_PERFORMANCE; |
1194 | break; |
1195 | case AMD_CPPC_EPP_BALANCE_POWERSAVE: |
1196 | preference = EPP_INDEX_BALANCE_POWERSAVE; |
1197 | break; |
1198 | case AMD_CPPC_EPP_POWERSAVE: |
1199 | preference = EPP_INDEX_POWERSAVE; |
1200 | break; |
1201 | default: |
1202 | return -EINVAL; |
1203 | } |
1204 | |
1205 | return sysfs_emit(buf, fmt: "%s\n", energy_perf_strings[preference]); |
1206 | } |
1207 | |
1208 | static void amd_pstate_driver_cleanup(void) |
1209 | { |
1210 | if (amd_pstate_prefcore) |
1211 | sched_clear_itmt_support(); |
1212 | |
1213 | cppc_state = AMD_PSTATE_DISABLE; |
1214 | current_pstate_driver = NULL; |
1215 | } |
1216 | |
1217 | static int amd_pstate_set_driver(int mode_idx) |
1218 | { |
1219 | if (mode_idx >= AMD_PSTATE_DISABLE && mode_idx < AMD_PSTATE_MAX) { |
1220 | cppc_state = mode_idx; |
1221 | if (cppc_state == AMD_PSTATE_DISABLE) |
1222 | pr_info("driver is explicitly disabled\n"); |
1223 | |
1224 | if (cppc_state == AMD_PSTATE_ACTIVE) |
1225 | current_pstate_driver = &amd_pstate_epp_driver; |
1226 | |
1227 | if (cppc_state == AMD_PSTATE_PASSIVE || cppc_state == AMD_PSTATE_GUIDED) |
1228 | current_pstate_driver = &amd_pstate_driver; |
1229 | |
1230 | return 0; |
1231 | } |
1232 | |
1233 | return -EINVAL; |
1234 | } |
1235 | |
1236 | static int amd_pstate_register_driver(int mode) |
1237 | { |
1238 | int ret; |
1239 | |
1240 | ret = amd_pstate_set_driver(mode_idx: mode); |
1241 | if (ret) |
1242 | return ret; |
1243 | |
1244 | cppc_state = mode; |
1245 | |
1246 | /* at least one CPU supports CPB */ |
1247 | current_pstate_driver->boost_enabled = cpu_feature_enabled(X86_FEATURE_CPB); |
1248 | |
1249 | ret = cpufreq_register_driver(driver_data: current_pstate_driver); |
1250 | if (ret) { |
1251 | amd_pstate_driver_cleanup(); |
1252 | return ret; |
1253 | } |
1254 | |
1255 | /* Enable ITMT support once all CPUs have initialized their asym priorities. */ |
1256 | if (amd_pstate_prefcore) |
1257 | sched_set_itmt_support(); |
1258 | |
1259 | return 0; |
1260 | } |
1261 | |
1262 | static int amd_pstate_unregister_driver(int dummy) |
1263 | { |
1264 | cpufreq_unregister_driver(driver_data: current_pstate_driver); |
1265 | amd_pstate_driver_cleanup(); |
1266 | return 0; |
1267 | } |
1268 | |
1269 | static int amd_pstate_change_mode_without_dvr_change(int mode) |
1270 | { |
1271 | int cpu = 0; |
1272 | |
1273 | cppc_state = mode; |
1274 | |
1275 | if (cpu_feature_enabled(X86_FEATURE_CPPC) || cppc_state == AMD_PSTATE_ACTIVE) |
1276 | return 0; |
1277 | |
1278 | for_each_present_cpu(cpu) { |
1279 | cppc_set_auto_sel(cpu, enable: (cppc_state == AMD_PSTATE_PASSIVE) ? 0 : 1); |
1280 | } |
1281 | |
1282 | return 0; |
1283 | } |
1284 | |
1285 | static int amd_pstate_change_driver_mode(int mode) |
1286 | { |
1287 | int ret; |
1288 | |
1289 | ret = amd_pstate_unregister_driver(dummy: 0); |
1290 | if (ret) |
1291 | return ret; |
1292 | |
1293 | ret = amd_pstate_register_driver(mode); |
1294 | if (ret) |
1295 | return ret; |
1296 | |
1297 | return 0; |
1298 | } |
1299 | |
1300 | static cppc_mode_transition_fn mode_state_machine[AMD_PSTATE_MAX][AMD_PSTATE_MAX] = { |
1301 | [AMD_PSTATE_DISABLE] = { |
1302 | [AMD_PSTATE_DISABLE] = NULL, |
1303 | [AMD_PSTATE_PASSIVE] = amd_pstate_register_driver, |
1304 | [AMD_PSTATE_ACTIVE] = amd_pstate_register_driver, |
1305 | [AMD_PSTATE_GUIDED] = amd_pstate_register_driver, |
1306 | }, |
1307 | [AMD_PSTATE_PASSIVE] = { |
1308 | [AMD_PSTATE_DISABLE] = amd_pstate_unregister_driver, |
1309 | [AMD_PSTATE_PASSIVE] = NULL, |
1310 | [AMD_PSTATE_ACTIVE] = amd_pstate_change_driver_mode, |
1311 | [AMD_PSTATE_GUIDED] = amd_pstate_change_mode_without_dvr_change, |
1312 | }, |
1313 | [AMD_PSTATE_ACTIVE] = { |
1314 | [AMD_PSTATE_DISABLE] = amd_pstate_unregister_driver, |
1315 | [AMD_PSTATE_PASSIVE] = amd_pstate_change_driver_mode, |
1316 | [AMD_PSTATE_ACTIVE] = NULL, |
1317 | [AMD_PSTATE_GUIDED] = amd_pstate_change_driver_mode, |
1318 | }, |
1319 | [AMD_PSTATE_GUIDED] = { |
1320 | [AMD_PSTATE_DISABLE] = amd_pstate_unregister_driver, |
1321 | [AMD_PSTATE_PASSIVE] = amd_pstate_change_mode_without_dvr_change, |
1322 | [AMD_PSTATE_ACTIVE] = amd_pstate_change_driver_mode, |
1323 | [AMD_PSTATE_GUIDED] = NULL, |
1324 | }, |
1325 | }; |
1326 | |
1327 | static ssize_t amd_pstate_show_status(char *buf) |
1328 | { |
1329 | if (!current_pstate_driver) |
1330 | return sysfs_emit(buf, fmt: "disable\n"); |
1331 | |
1332 | return sysfs_emit(buf, fmt: "%s\n", amd_pstate_mode_string[cppc_state]); |
1333 | } |
1334 | |
1335 | int amd_pstate_get_status(void) |
1336 | { |
1337 | return cppc_state; |
1338 | } |
1339 | EXPORT_SYMBOL_GPL(amd_pstate_get_status); |
1340 | |
1341 | int amd_pstate_update_status(const char *buf, size_t size) |
1342 | { |
1343 | int mode_idx; |
1344 | |
1345 | if (size > strlen("passive") || size < strlen( "active")) |
1346 | return -EINVAL; |
1347 | |
1348 | mode_idx = get_mode_idx_from_str(str: buf, size); |
1349 | |
1350 | if (mode_idx < 0 || mode_idx >= AMD_PSTATE_MAX) |
1351 | return -EINVAL; |
1352 | |
1353 | if (mode_state_machine[cppc_state][mode_idx]) { |
1354 | guard(mutex)(T: &amd_pstate_driver_lock); |
1355 | return mode_state_machine[cppc_state][mode_idx](mode_idx); |
1356 | } |
1357 | |
1358 | return 0; |
1359 | } |
1360 | EXPORT_SYMBOL_GPL(amd_pstate_update_status); |
1361 | |
1362 | static ssize_t status_show(struct device *dev, |
1363 | struct device_attribute *attr, char *buf) |
1364 | { |
1365 | |
1366 | guard(mutex)(T: &amd_pstate_driver_lock); |
1367 | |
1368 | return amd_pstate_show_status(buf); |
1369 | } |
1370 | |
1371 | static ssize_t status_store(struct device *a, struct device_attribute *b, |
1372 | const char *buf, size_t count) |
1373 | { |
1374 | char *p = memchr(p: buf, c: '\n', size: count); |
1375 | int ret; |
1376 | |
1377 | ret = amd_pstate_update_status(buf, p ? p - buf : count); |
1378 | |
1379 | return ret < 0 ? ret : count; |
1380 | } |
1381 | |
1382 | static ssize_t prefcore_show(struct device *dev, |
1383 | struct device_attribute *attr, char *buf) |
1384 | { |
1385 | return sysfs_emit(buf, fmt: "%s\n", str_enabled_disabled(v: amd_pstate_prefcore)); |
1386 | } |
1387 | |
1388 | cpufreq_freq_attr_ro(amd_pstate_max_freq); |
1389 | cpufreq_freq_attr_ro(amd_pstate_lowest_nonlinear_freq); |
1390 | |
1391 | cpufreq_freq_attr_ro(amd_pstate_highest_perf); |
1392 | cpufreq_freq_attr_ro(amd_pstate_prefcore_ranking); |
1393 | cpufreq_freq_attr_ro(amd_pstate_hw_prefcore); |
1394 | cpufreq_freq_attr_rw(energy_performance_preference); |
1395 | cpufreq_freq_attr_ro(energy_performance_available_preferences); |
1396 | static DEVICE_ATTR_RW(status); |
1397 | static DEVICE_ATTR_RO(prefcore); |
1398 | |
1399 | static struct freq_attr *amd_pstate_attr[] = { |
1400 | &amd_pstate_max_freq, |
1401 | &amd_pstate_lowest_nonlinear_freq, |
1402 | &amd_pstate_highest_perf, |
1403 | &amd_pstate_prefcore_ranking, |
1404 | &amd_pstate_hw_prefcore, |
1405 | NULL, |
1406 | }; |
1407 | |
1408 | static struct freq_attr *amd_pstate_epp_attr[] = { |
1409 | &amd_pstate_max_freq, |
1410 | &amd_pstate_lowest_nonlinear_freq, |
1411 | &amd_pstate_highest_perf, |
1412 | &amd_pstate_prefcore_ranking, |
1413 | &amd_pstate_hw_prefcore, |
1414 | &energy_performance_preference, |
1415 | &energy_performance_available_preferences, |
1416 | NULL, |
1417 | }; |
1418 | |
1419 | static struct attribute *pstate_global_attributes[] = { |
1420 | &dev_attr_status.attr, |
1421 | &dev_attr_prefcore.attr, |
1422 | NULL |
1423 | }; |
1424 | |
1425 | static const struct attribute_group amd_pstate_global_attr_group = { |
1426 | .name = "amd_pstate", |
1427 | .attrs = pstate_global_attributes, |
1428 | }; |
1429 | |
1430 | static bool amd_pstate_acpi_pm_profile_server(void) |
1431 | { |
1432 | switch (acpi_gbl_FADT.preferred_profile) { |
1433 | case PM_ENTERPRISE_SERVER: |
1434 | case PM_SOHO_SERVER: |
1435 | case PM_PERFORMANCE_SERVER: |
1436 | return true; |
1437 | } |
1438 | return false; |
1439 | } |
1440 | |
1441 | static bool amd_pstate_acpi_pm_profile_undefined(void) |
1442 | { |
1443 | if (acpi_gbl_FADT.preferred_profile == PM_UNSPECIFIED) |
1444 | return true; |
1445 | if (acpi_gbl_FADT.preferred_profile >= NR_PM_PROFILES) |
1446 | return true; |
1447 | return false; |
1448 | } |
1449 | |
1450 | static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) |
1451 | { |
1452 | struct amd_cpudata *cpudata; |
1453 | union perf_cached perf; |
1454 | struct device *dev; |
1455 | int ret; |
1456 | |
1457 | /* |
1458 | * Resetting PERF_CTL_MSR will put the CPU in P0 frequency, |
1459 | * which is ideal for initialization process. |
1460 | */ |
1461 | amd_perf_ctl_reset(cpu: policy->cpu); |
1462 | dev = get_cpu_device(cpu: policy->cpu); |
1463 | if (!dev) |
1464 | return -ENODEV; |
1465 | |
1466 | cpudata = kzalloc(sizeof(*cpudata), GFP_KERNEL); |
1467 | if (!cpudata) |
1468 | return -ENOMEM; |
1469 | |
1470 | cpudata->cpu = policy->cpu; |
1471 | |
1472 | ret = amd_pstate_init_perf(cpudata); |
1473 | if (ret) |
1474 | goto free_cpudata1; |
1475 | |
1476 | amd_pstate_init_prefcore(cpudata); |
1477 | |
1478 | ret = amd_pstate_init_freq(cpudata); |
1479 | if (ret) |
1480 | goto free_cpudata1; |
1481 | |
1482 | ret = amd_pstate_init_boost_support(cpudata); |
1483 | if (ret) |
1484 | goto free_cpudata1; |
1485 | |
1486 | perf = READ_ONCE(cpudata->perf); |
1487 | |
1488 | policy->cpuinfo.min_freq = policy->min = perf_to_freq(perf, |
1489 | nominal_freq: cpudata->nominal_freq, |
1490 | perf_val: perf.lowest_perf); |
1491 | policy->cpuinfo.max_freq = policy->max = perf_to_freq(perf, |
1492 | nominal_freq: cpudata->nominal_freq, |
1493 | perf_val: perf.highest_perf); |
1494 | policy->driver_data = cpudata; |
1495 | |
1496 | ret = amd_pstate_cppc_enable(policy); |
1497 | if (ret) |
1498 | goto free_cpudata1; |
1499 | |
1500 | /* It will be updated by governor */ |
1501 | policy->cur = policy->cpuinfo.min_freq; |
1502 | |
1503 | |
1504 | policy->boost_supported = READ_ONCE(cpudata->boost_supported); |
1505 | |
1506 | /* |
1507 | * Set the policy to provide a valid fallback value in case |
1508 | * the default cpufreq governor is neither powersave nor performance. |
1509 | */ |
1510 | if (amd_pstate_acpi_pm_profile_server() || |
1511 | amd_pstate_acpi_pm_profile_undefined()) { |
1512 | policy->policy = CPUFREQ_POLICY_PERFORMANCE; |
1513 | cpudata->epp_default = amd_pstate_get_epp(cpudata); |
1514 | } else { |
1515 | policy->policy = CPUFREQ_POLICY_POWERSAVE; |
1516 | cpudata->epp_default = AMD_CPPC_EPP_BALANCE_PERFORMANCE; |
1517 | } |
1518 | |
1519 | ret = amd_pstate_set_epp(policy, epp: cpudata->epp_default); |
1520 | if (ret) |
1521 | return ret; |
1522 | |
1523 | current_pstate_driver->adjust_perf = NULL; |
1524 | |
1525 | return 0; |
1526 | |
1527 | free_cpudata1: |
1528 | pr_warn("Failed to initialize CPU %d: %d\n", policy->cpu, ret); |
1529 | kfree(objp: cpudata); |
1530 | return ret; |
1531 | } |
1532 | |
1533 | static void amd_pstate_epp_cpu_exit(struct cpufreq_policy *policy) |
1534 | { |
1535 | struct amd_cpudata *cpudata = policy->driver_data; |
1536 | |
1537 | if (cpudata) { |
1538 | union perf_cached perf = READ_ONCE(cpudata->perf); |
1539 | |
1540 | /* Reset CPPC_REQ MSR to the BIOS value */ |
1541 | amd_pstate_update_perf(policy, min_perf: perf.bios_min_perf, des_perf: 0U, max_perf: 0U, epp: 0U, fast_switch: false); |
1542 | |
1543 | kfree(objp: cpudata); |
1544 | policy->driver_data = NULL; |
1545 | } |
1546 | |
1547 | pr_debug("CPU %d exiting\n", policy->cpu); |
1548 | } |
1549 | |
1550 | static int amd_pstate_epp_update_limit(struct cpufreq_policy *policy) |
1551 | { |
1552 | struct amd_cpudata *cpudata = policy->driver_data; |
1553 | union perf_cached perf; |
1554 | u8 epp; |
1555 | |
1556 | if (policy->min != cpudata->min_limit_freq || policy->max != cpudata->max_limit_freq) |
1557 | amd_pstate_update_min_max_limit(policy); |
1558 | |
1559 | if (cpudata->policy == CPUFREQ_POLICY_PERFORMANCE) |
1560 | epp = 0; |
1561 | else |
1562 | epp = FIELD_GET(AMD_CPPC_EPP_PERF_MASK, cpudata->cppc_req_cached); |
1563 | |
1564 | perf = READ_ONCE(cpudata->perf); |
1565 | |
1566 | return amd_pstate_update_perf(policy, min_perf: perf.min_limit_perf, des_perf: 0U, |
1567 | max_perf: perf.max_limit_perf, epp, fast_switch: false); |
1568 | } |
1569 | |
1570 | static int amd_pstate_epp_set_policy(struct cpufreq_policy *policy) |
1571 | { |
1572 | struct amd_cpudata *cpudata = policy->driver_data; |
1573 | int ret; |
1574 | |
1575 | if (!policy->cpuinfo.max_freq) |
1576 | return -ENODEV; |
1577 | |
1578 | cpudata->policy = policy->policy; |
1579 | |
1580 | ret = amd_pstate_epp_update_limit(policy); |
1581 | if (ret) |
1582 | return ret; |
1583 | |
1584 | /* |
1585 | * policy->cur is never updated with the amd_pstate_epp driver, but it |
1586 | * is used as a stale frequency value. So, keep it within limits. |
1587 | */ |
1588 | policy->cur = policy->min; |
1589 | |
1590 | return 0; |
1591 | } |
1592 | |
1593 | static int amd_pstate_cpu_online(struct cpufreq_policy *policy) |
1594 | { |
1595 | return amd_pstate_cppc_enable(policy); |
1596 | } |
1597 | |
1598 | static int amd_pstate_cpu_offline(struct cpufreq_policy *policy) |
1599 | { |
1600 | struct amd_cpudata *cpudata = policy->driver_data; |
1601 | union perf_cached perf = READ_ONCE(cpudata->perf); |
1602 | |
1603 | /* |
1604 | * Reset CPPC_REQ MSR to the BIOS value, this will allow us to retain the BIOS specified |
1605 | * min_perf value across kexec reboots. If this CPU is just onlined normally after this, the |
1606 | * limits, epp and desired perf will get reset to the cached values in cpudata struct |
1607 | */ |
1608 | return amd_pstate_update_perf(policy, min_perf: perf.bios_min_perf, des_perf: 0U, max_perf: 0U, epp: 0U, fast_switch: false); |
1609 | } |
1610 | |
1611 | static int amd_pstate_suspend(struct cpufreq_policy *policy) |
1612 | { |
1613 | struct amd_cpudata *cpudata = policy->driver_data; |
1614 | union perf_cached perf = READ_ONCE(cpudata->perf); |
1615 | int ret; |
1616 | |
1617 | /* |
1618 | * Reset CPPC_REQ MSR to the BIOS value, this will allow us to retain the BIOS specified |
1619 | * min_perf value across kexec reboots. If this CPU is just resumed back without kexec, |
1620 | * the limits, epp and desired perf will get reset to the cached values in cpudata struct |
1621 | */ |
1622 | ret = amd_pstate_update_perf(policy, min_perf: perf.bios_min_perf, des_perf: 0U, max_perf: 0U, epp: 0U, fast_switch: false); |
1623 | if (ret) |
1624 | return ret; |
1625 | |
1626 | /* invalidate to ensure it's rewritten during resume */ |
1627 | cpudata->cppc_req_cached = 0; |
1628 | |
1629 | /* set this flag to avoid setting core offline*/ |
1630 | cpudata->suspended = true; |
1631 | |
1632 | return 0; |
1633 | } |
1634 | |
1635 | static int amd_pstate_resume(struct cpufreq_policy *policy) |
1636 | { |
1637 | struct amd_cpudata *cpudata = policy->driver_data; |
1638 | union perf_cached perf = READ_ONCE(cpudata->perf); |
1639 | int cur_perf = freq_to_perf(perf, nominal_freq: cpudata->nominal_freq, freq_val: policy->cur); |
1640 | |
1641 | /* Set CPPC_REQ to last sane value until the governor updates it */ |
1642 | return amd_pstate_update_perf(policy, min_perf: perf.min_limit_perf, des_perf: cur_perf, max_perf: perf.max_limit_perf, |
1643 | epp: 0U, fast_switch: false); |
1644 | } |
1645 | |
1646 | static int amd_pstate_epp_resume(struct cpufreq_policy *policy) |
1647 | { |
1648 | struct amd_cpudata *cpudata = policy->driver_data; |
1649 | |
1650 | if (cpudata->suspended) { |
1651 | int ret; |
1652 | |
1653 | /* enable amd pstate from suspend state*/ |
1654 | ret = amd_pstate_epp_update_limit(policy); |
1655 | if (ret) |
1656 | return ret; |
1657 | |
1658 | cpudata->suspended = false; |
1659 | } |
1660 | |
1661 | return 0; |
1662 | } |
1663 | |
1664 | static struct cpufreq_driver amd_pstate_driver = { |
1665 | .flags = CPUFREQ_CONST_LOOPS | CPUFREQ_NEED_UPDATE_LIMITS, |
1666 | .verify = amd_pstate_verify, |
1667 | .target = amd_pstate_target, |
1668 | .fast_switch = amd_pstate_fast_switch, |
1669 | .init = amd_pstate_cpu_init, |
1670 | .exit = amd_pstate_cpu_exit, |
1671 | .online = amd_pstate_cpu_online, |
1672 | .offline = amd_pstate_cpu_offline, |
1673 | .suspend = amd_pstate_suspend, |
1674 | .resume = amd_pstate_resume, |
1675 | .set_boost = amd_pstate_set_boost, |
1676 | .update_limits = amd_pstate_update_limits, |
1677 | .name = "amd-pstate", |
1678 | .attr = amd_pstate_attr, |
1679 | }; |
1680 | |
1681 | static struct cpufreq_driver amd_pstate_epp_driver = { |
1682 | .flags = CPUFREQ_CONST_LOOPS, |
1683 | .verify = amd_pstate_verify, |
1684 | .setpolicy = amd_pstate_epp_set_policy, |
1685 | .init = amd_pstate_epp_cpu_init, |
1686 | .exit = amd_pstate_epp_cpu_exit, |
1687 | .offline = amd_pstate_cpu_offline, |
1688 | .online = amd_pstate_cpu_online, |
1689 | .suspend = amd_pstate_suspend, |
1690 | .resume = amd_pstate_epp_resume, |
1691 | .update_limits = amd_pstate_update_limits, |
1692 | .set_boost = amd_pstate_set_boost, |
1693 | .name = "amd-pstate-epp", |
1694 | .attr = amd_pstate_epp_attr, |
1695 | }; |
1696 | |
1697 | /* |
1698 | * CPPC function is not supported for family ID 17H with model_ID ranging from 0x10 to 0x2F. |
1699 | * show the debug message that helps to check if the CPU has CPPC support for loading issue. |
1700 | */ |
1701 | static bool amd_cppc_supported(void) |
1702 | { |
1703 | struct cpuinfo_x86 *c = &cpu_data(0); |
1704 | bool warn = false; |
1705 | |
1706 | if ((boot_cpu_data.x86 == 0x17) && (boot_cpu_data.x86_model < 0x30)) { |
1707 | pr_debug_once("CPPC feature is not supported by the processor\n"); |
1708 | return false; |
1709 | } |
1710 | |
1711 | /* |
1712 | * If the CPPC feature is disabled in the BIOS for processors |
1713 | * that support MSR-based CPPC, the AMD Pstate driver may not |
1714 | * function correctly. |
1715 | * |
1716 | * For such processors, check the CPPC flag and display a |
1717 | * warning message if the platform supports CPPC. |
1718 | * |
1719 | * Note: The code check below will not abort the driver |
1720 | * registration process because of the code is added for |
1721 | * debugging purposes. Besides, it may still be possible for |
1722 | * the driver to work using the shared-memory mechanism. |
1723 | */ |
1724 | if (!cpu_feature_enabled(X86_FEATURE_CPPC)) { |
1725 | if (cpu_feature_enabled(X86_FEATURE_ZEN2)) { |
1726 | switch (c->x86_model) { |
1727 | case 0x60 ... 0x6F: |
1728 | case 0x80 ... 0xAF: |
1729 | warn = true; |
1730 | break; |
1731 | } |
1732 | } else if (cpu_feature_enabled(X86_FEATURE_ZEN3) || |
1733 | cpu_feature_enabled(X86_FEATURE_ZEN4)) { |
1734 | switch (c->x86_model) { |
1735 | case 0x10 ... 0x1F: |
1736 | case 0x40 ... 0xAF: |
1737 | warn = true; |
1738 | break; |
1739 | } |
1740 | } else if (cpu_feature_enabled(X86_FEATURE_ZEN5)) { |
1741 | warn = true; |
1742 | } |
1743 | } |
1744 | |
1745 | if (warn) |
1746 | pr_warn_once("The CPPC feature is supported but currently disabled by the BIOS.\n" |
1747 | "Please enable it if your BIOS has the CPPC option.\n"); |
1748 | return true; |
1749 | } |
1750 | |
1751 | static int __init amd_pstate_init(void) |
1752 | { |
1753 | struct device *dev_root; |
1754 | int ret; |
1755 | |
1756 | if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) |
1757 | return -ENODEV; |
1758 | |
1759 | /* show debug message only if CPPC is not supported */ |
1760 | if (!amd_cppc_supported()) |
1761 | return -EOPNOTSUPP; |
1762 | |
1763 | /* show warning message when BIOS broken or ACPI disabled */ |
1764 | if (!acpi_cpc_valid()) { |
1765 | pr_warn_once("the _CPC object is not present in SBIOS or ACPI disabled\n"); |
1766 | return -ENODEV; |
1767 | } |
1768 | |
1769 | /* don't keep reloading if cpufreq_driver exists */ |
1770 | if (cpufreq_get_current_driver()) |
1771 | return -EEXIST; |
1772 | |
1773 | quirks = NULL; |
1774 | |
1775 | /* check if this machine need CPPC quirks */ |
1776 | dmi_check_system(list: amd_pstate_quirks_table); |
1777 | |
1778 | /* |
1779 | * determine the driver mode from the command line or kernel config. |
1780 | * If no command line input is provided, cppc_state will be AMD_PSTATE_UNDEFINED. |
1781 | * command line options will override the kernel config settings. |
1782 | */ |
1783 | |
1784 | if (cppc_state == AMD_PSTATE_UNDEFINED) { |
1785 | /* Disable on the following configs by default: |
1786 | * 1. Undefined platforms |
1787 | * 2. Server platforms with CPUs older than Family 0x1A. |
1788 | */ |
1789 | if (amd_pstate_acpi_pm_profile_undefined() || |
1790 | (amd_pstate_acpi_pm_profile_server() && boot_cpu_data.x86 < 0x1A)) { |
1791 | pr_info("driver load is disabled, boot with specific mode to enable this\n"); |
1792 | return -ENODEV; |
1793 | } |
1794 | /* get driver mode from kernel config option [1:4] */ |
1795 | cppc_state = CONFIG_X86_AMD_PSTATE_DEFAULT_MODE; |
1796 | } |
1797 | |
1798 | if (cppc_state == AMD_PSTATE_DISABLE) { |
1799 | pr_info("driver load is disabled, boot with specific mode to enable this\n"); |
1800 | return -ENODEV; |
1801 | } |
1802 | |
1803 | /* capability check */ |
1804 | if (cpu_feature_enabled(X86_FEATURE_CPPC)) { |
1805 | pr_debug("AMD CPPC MSR based functionality is supported\n"); |
1806 | } else { |
1807 | pr_debug("AMD CPPC shared memory based functionality is supported\n"); |
1808 | static_call_update(amd_pstate_cppc_enable, shmem_cppc_enable); |
1809 | static_call_update(amd_pstate_init_perf, shmem_init_perf); |
1810 | static_call_update(amd_pstate_update_perf, shmem_update_perf); |
1811 | static_call_update(amd_pstate_get_epp, shmem_get_epp); |
1812 | static_call_update(amd_pstate_set_epp, shmem_set_epp); |
1813 | } |
1814 | |
1815 | if (amd_pstate_prefcore) { |
1816 | ret = amd_detect_prefcore(detected: &amd_pstate_prefcore); |
1817 | if (ret) |
1818 | return ret; |
1819 | } |
1820 | |
1821 | ret = amd_pstate_register_driver(mode: cppc_state); |
1822 | if (ret) { |
1823 | pr_err("failed to register with return %d\n", ret); |
1824 | return ret; |
1825 | } |
1826 | |
1827 | dev_root = bus_get_dev_root(bus: &cpu_subsys); |
1828 | if (dev_root) { |
1829 | ret = sysfs_create_group(kobj: &dev_root->kobj, grp: &amd_pstate_global_attr_group); |
1830 | put_device(dev: dev_root); |
1831 | if (ret) { |
1832 | pr_err("sysfs attribute export failed with error %d.\n", ret); |
1833 | goto global_attr_free; |
1834 | } |
1835 | } |
1836 | |
1837 | return ret; |
1838 | |
1839 | global_attr_free: |
1840 | cpufreq_unregister_driver(driver_data: current_pstate_driver); |
1841 | return ret; |
1842 | } |
1843 | device_initcall(amd_pstate_init); |
1844 | |
1845 | static int __init amd_pstate_param(char *str) |
1846 | { |
1847 | size_t size; |
1848 | int mode_idx; |
1849 | |
1850 | if (!str) |
1851 | return -EINVAL; |
1852 | |
1853 | size = strlen(str); |
1854 | mode_idx = get_mode_idx_from_str(str, size); |
1855 | |
1856 | return amd_pstate_set_driver(mode_idx); |
1857 | } |
1858 | |
1859 | static int __init amd_prefcore_param(char *str) |
1860 | { |
1861 | if (!strcmp(str, "disable")) |
1862 | amd_pstate_prefcore = false; |
1863 | |
1864 | return 0; |
1865 | } |
1866 | |
1867 | early_param("amd_pstate", amd_pstate_param); |
1868 | early_param("amd_prefcore", amd_prefcore_param); |
1869 | |
1870 | MODULE_AUTHOR("Huang Rui <ray.huang@amd.com>"); |
1871 | MODULE_DESCRIPTION("AMD Processor P-state Frequency Driver"); |
1872 |
Definitions
- amd_pstate_mode_string
- amd_pstate_get_mode_string
- quirk_entry
- current_pstate_driver
- amd_pstate_driver
- amd_pstate_epp_driver
- cppc_state
- amd_pstate_prefcore
- quirks
- energy_perf_value_index
- energy_perf_strings
- epp_values
- quirk_amd_7k62
- freq_to_perf
- perf_to_freq
- dmi_matched_7k62_bios_bug
- amd_pstate_quirks_table
- get_mode_idx_from_str
- amd_pstate_driver_lock
- msr_get_epp
- amd_pstate_get_epp
- shmem_get_epp
- msr_update_perf
- amd_pstate_update_perf
- msr_set_epp
- amd_pstate_set_epp
- shmem_set_epp
- msr_cppc_enable
- shmem_cppc_enable
- amd_pstate_cppc_enable
- msr_init_perf
- shmem_init_perf
- amd_pstate_init_perf
- shmem_update_perf
- amd_pstate_sample
- amd_pstate_update
- amd_pstate_verify
- amd_pstate_update_min_max_limit
- amd_pstate_update_freq
- amd_pstate_target
- amd_pstate_fast_switch
- amd_pstate_adjust_perf
- amd_pstate_cpu_boost_update
- amd_pstate_set_boost
- amd_pstate_init_boost_support
- amd_perf_ctl_reset
- amd_pstate_init_prefcore
- amd_pstate_update_limits
- amd_pstate_get_transition_delay_us
- amd_pstate_get_transition_latency
- amd_pstate_init_freq
- amd_pstate_cpu_init
- amd_pstate_cpu_exit
- show_amd_pstate_max_freq
- show_amd_pstate_lowest_nonlinear_freq
- show_amd_pstate_highest_perf
- show_amd_pstate_prefcore_ranking
- show_amd_pstate_hw_prefcore
- show_energy_performance_available_preferences
- store_energy_performance_preference
- show_energy_performance_preference
- amd_pstate_driver_cleanup
- amd_pstate_set_driver
- amd_pstate_register_driver
- amd_pstate_unregister_driver
- amd_pstate_change_mode_without_dvr_change
- amd_pstate_change_driver_mode
- mode_state_machine
- amd_pstate_show_status
- amd_pstate_get_status
- amd_pstate_update_status
- status_show
- status_store
- prefcore_show
- amd_pstate_max_freq
- amd_pstate_lowest_nonlinear_freq
- amd_pstate_highest_perf
- amd_pstate_prefcore_ranking
- amd_pstate_hw_prefcore
- energy_performance_preference
- energy_performance_available_preferences
- amd_pstate_attr
- amd_pstate_epp_attr
- pstate_global_attributes
- amd_pstate_global_attr_group
- amd_pstate_acpi_pm_profile_server
- amd_pstate_acpi_pm_profile_undefined
- amd_pstate_epp_cpu_init
- amd_pstate_epp_cpu_exit
- amd_pstate_epp_update_limit
- amd_pstate_epp_set_policy
- amd_pstate_cpu_online
- amd_pstate_cpu_offline
- amd_pstate_suspend
- amd_pstate_resume
- amd_pstate_epp_resume
- amd_pstate_driver
- amd_pstate_epp_driver
- amd_cppc_supported
- amd_pstate_init
- amd_pstate_param
Improve your Profiling and Debugging skills
Find out more