Power management fixes for 6.13-rc4

- Detect preferred core support in amd-pstate  before driver
    registration to avoid initialization ordering issues (K Prateek
    Nayak).
 
  - Fix issues with with boost numerator handling in amd-pstate leading
    to inconsistently programmed CPPC max performance values (Mario
    Limonciello).
 -----BEGIN PGP SIGNATURE-----
 
 iQJGBAABCAAwFiEE4fcc61cGeeHD/fCwgsRv/nhiVHEFAmdl1RMSHHJqd0Byand5
 c29ja2kubmV0AAoJEILEb/54YlRxapEQAKlXuqhjYEl2x1RuGuHO81YEMjoDIBHQ
 1Mhfzidz+QZgLj3cJXdSDinz/JFeSyMmObKKp3VTtysIsxf1N0OohpOW6jVr5GX5
 PzOe15bWwCO12hriAEH4TcImejzJaTv9l/GjeI+GtvA2sFB3TqnuwcKVUUciZ/tf
 pVV+oPsi1XjFVbjpwATu0BHNd+oOMgsVBDE6/A2NiRGz/4pHbfPCn1+V4CfMvgHv
 Zh7g0s+kLAikxf4iT6ExFyXM3H6lUsUBeBLkXrCzG0rsFE681Slrm6R+eKfqrQHS
 0ijJyZyumol4JnAZ0Sn/VxWQ3/A++EbELJrft2+ZK99NiuBhasucHBuHSQL9kF4D
 PpZxSTA+aEAY4EwolhSqgvl9Yz5RPOa/tKWwinfMErKgA9bt4ibnHr3dQSILqu10
 dO5TRdM0VIRUh+6lVxqsNRRib5BZlZJjp05/RZiH79DWS1saPiSkQBO0elLkscsk
 zwOHi/XAq+DbwsriWpSMGFX07CNZXdDih9oVYqsLsr7tOl4hMpCZSUs1613PL66j
 kih8YqBykgdSH8YAKP9StZeu32pjDHRwQfuPTC5wN6rNU5n11botO+SnGILRZSP3
 27lpkCeMAnvdNpRvj2PsohDywlMnD4XzzN+5vxGncPRAKGwTg8bXRgiRjr5SHJR7
 +gmHVhvrpdMA
 =Blf/
 -----END PGP SIGNATURE-----

Merge tag 'pm-6.13-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull power management fixes from Rafael Wysocki:
 "These fix some amd-pstate driver issues:

   - Detect preferred core support in amd-pstate before driver
     registration to avoid initialization ordering issues (K Prateek
     Nayak)

   - Fix issues with with boost numerator handling in amd-pstate leading
     to inconsistently programmed CPPC max performance values (Mario
     Limonciello)"

* tag 'pm-6.13-rc4' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  cpufreq/amd-pstate: Use boost numerator for upper bound of frequencies
  cpufreq/amd-pstate: Store the boost numerator as highest perf again
  cpufreq/amd-pstate: Detect preferred core support before driver registration
This commit is contained in:
Linus Torvalds 2024-12-21 10:47:47 -08:00
commit 78b1346123
2 changed files with 27 additions and 27 deletions

View File

@ -251,9 +251,7 @@ performance supported in `AMD CPPC Performance Capability <perf_cap_>`_).
In some ASICs, the highest CPPC performance is not the one in the ``_CPC`` In some ASICs, the highest CPPC performance is not the one in the ``_CPC``
table, so we need to expose it to sysfs. If boost is not active, but table, so we need to expose it to sysfs. If boost is not active, but
still supported, this maximum frequency will be larger than the one in still supported, this maximum frequency will be larger than the one in
``cpuinfo``. On systems that support preferred core, the driver will have ``cpuinfo``.
different values for some cores than others and this will reflect the values
advertised by the platform at bootup.
This attribute is read-only. This attribute is read-only.
``amd_pstate_lowest_nonlinear_freq`` ``amd_pstate_lowest_nonlinear_freq``

View File

@ -374,15 +374,19 @@ static inline int amd_pstate_cppc_enable(bool enable)
static int msr_init_perf(struct amd_cpudata *cpudata) static int msr_init_perf(struct amd_cpudata *cpudata)
{ {
u64 cap1; u64 cap1, numerator;
int ret = rdmsrl_safe_on_cpu(cpudata->cpu, MSR_AMD_CPPC_CAP1, int ret = rdmsrl_safe_on_cpu(cpudata->cpu, MSR_AMD_CPPC_CAP1,
&cap1); &cap1);
if (ret) if (ret)
return ret; return ret;
WRITE_ONCE(cpudata->highest_perf, AMD_CPPC_HIGHEST_PERF(cap1)); ret = amd_get_boost_ratio_numerator(cpudata->cpu, &numerator);
WRITE_ONCE(cpudata->max_limit_perf, AMD_CPPC_HIGHEST_PERF(cap1)); if (ret)
return ret;
WRITE_ONCE(cpudata->highest_perf, numerator);
WRITE_ONCE(cpudata->max_limit_perf, numerator);
WRITE_ONCE(cpudata->nominal_perf, AMD_CPPC_NOMINAL_PERF(cap1)); WRITE_ONCE(cpudata->nominal_perf, AMD_CPPC_NOMINAL_PERF(cap1));
WRITE_ONCE(cpudata->lowest_nonlinear_perf, AMD_CPPC_LOWNONLIN_PERF(cap1)); WRITE_ONCE(cpudata->lowest_nonlinear_perf, AMD_CPPC_LOWNONLIN_PERF(cap1));
WRITE_ONCE(cpudata->lowest_perf, AMD_CPPC_LOWEST_PERF(cap1)); WRITE_ONCE(cpudata->lowest_perf, AMD_CPPC_LOWEST_PERF(cap1));
@ -394,13 +398,18 @@ static int msr_init_perf(struct amd_cpudata *cpudata)
static int shmem_init_perf(struct amd_cpudata *cpudata) static int shmem_init_perf(struct amd_cpudata *cpudata)
{ {
struct cppc_perf_caps cppc_perf; struct cppc_perf_caps cppc_perf;
u64 numerator;
int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf); int ret = cppc_get_perf_caps(cpudata->cpu, &cppc_perf);
if (ret) if (ret)
return ret; return ret;
WRITE_ONCE(cpudata->highest_perf, cppc_perf.highest_perf); ret = amd_get_boost_ratio_numerator(cpudata->cpu, &numerator);
WRITE_ONCE(cpudata->max_limit_perf, cppc_perf.highest_perf); if (ret)
return ret;
WRITE_ONCE(cpudata->highest_perf, numerator);
WRITE_ONCE(cpudata->max_limit_perf, numerator);
WRITE_ONCE(cpudata->nominal_perf, cppc_perf.nominal_perf); WRITE_ONCE(cpudata->nominal_perf, cppc_perf.nominal_perf);
WRITE_ONCE(cpudata->lowest_nonlinear_perf, WRITE_ONCE(cpudata->lowest_nonlinear_perf,
cppc_perf.lowest_nonlinear_perf); cppc_perf.lowest_nonlinear_perf);
@ -561,16 +570,13 @@ static int amd_pstate_verify(struct cpufreq_policy_data *policy_data)
static int amd_pstate_update_min_max_limit(struct cpufreq_policy *policy) static int amd_pstate_update_min_max_limit(struct cpufreq_policy *policy)
{ {
u32 max_limit_perf, min_limit_perf, lowest_perf, max_perf; u32 max_limit_perf, min_limit_perf, lowest_perf, max_perf, max_freq;
struct amd_cpudata *cpudata = policy->driver_data; struct amd_cpudata *cpudata = policy->driver_data;
if (cpudata->boost_supported && !policy->boost_enabled) max_perf = READ_ONCE(cpudata->highest_perf);
max_perf = READ_ONCE(cpudata->nominal_perf); max_freq = READ_ONCE(cpudata->max_freq);
else max_limit_perf = div_u64(policy->max * max_perf, max_freq);
max_perf = READ_ONCE(cpudata->highest_perf); min_limit_perf = div_u64(policy->min * max_perf, max_freq);
max_limit_perf = div_u64(policy->max * max_perf, policy->cpuinfo.max_freq);
min_limit_perf = div_u64(policy->min * max_perf, policy->cpuinfo.max_freq);
lowest_perf = READ_ONCE(cpudata->lowest_perf); lowest_perf = READ_ONCE(cpudata->lowest_perf);
if (min_limit_perf < lowest_perf) if (min_limit_perf < lowest_perf)
@ -889,7 +895,6 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
{ {
int ret; int ret;
u32 min_freq, max_freq; u32 min_freq, max_freq;
u64 numerator;
u32 nominal_perf, nominal_freq; u32 nominal_perf, nominal_freq;
u32 lowest_nonlinear_perf, lowest_nonlinear_freq; u32 lowest_nonlinear_perf, lowest_nonlinear_freq;
u32 boost_ratio, lowest_nonlinear_ratio; u32 boost_ratio, lowest_nonlinear_ratio;
@ -911,10 +916,7 @@ static int amd_pstate_init_freq(struct amd_cpudata *cpudata)
nominal_perf = READ_ONCE(cpudata->nominal_perf); nominal_perf = READ_ONCE(cpudata->nominal_perf);
ret = amd_get_boost_ratio_numerator(cpudata->cpu, &numerator); boost_ratio = div_u64(cpudata->highest_perf << SCHED_CAPACITY_SHIFT, nominal_perf);
if (ret)
return ret;
boost_ratio = div_u64(numerator << SCHED_CAPACITY_SHIFT, nominal_perf);
max_freq = (nominal_freq * boost_ratio >> SCHED_CAPACITY_SHIFT) * 1000; max_freq = (nominal_freq * boost_ratio >> SCHED_CAPACITY_SHIFT) * 1000;
lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf); lowest_nonlinear_perf = READ_ONCE(cpudata->lowest_nonlinear_perf);
@ -1869,18 +1871,18 @@ static int __init amd_pstate_init(void)
static_call_update(amd_pstate_update_perf, shmem_update_perf); static_call_update(amd_pstate_update_perf, shmem_update_perf);
} }
ret = amd_pstate_register_driver(cppc_state);
if (ret) {
pr_err("failed to register with return %d\n", ret);
return ret;
}
if (amd_pstate_prefcore) { if (amd_pstate_prefcore) {
ret = amd_detect_prefcore(&amd_pstate_prefcore); ret = amd_detect_prefcore(&amd_pstate_prefcore);
if (ret) if (ret)
return ret; return ret;
} }
ret = amd_pstate_register_driver(cppc_state);
if (ret) {
pr_err("failed to register with return %d\n", ret);
return ret;
}
dev_root = bus_get_dev_root(&cpu_subsys); dev_root = bus_get_dev_root(&cpu_subsys);
if (dev_root) { if (dev_root) {
ret = sysfs_create_group(&dev_root->kobj, &amd_pstate_global_attr_group); ret = sysfs_create_group(&dev_root->kobj, &amd_pstate_global_attr_group);