On Mon, Aug 26, 2024 at 04:13:55PM -0500, Mario Limonciello wrote: > From: Mario Limonciello <mario.limonciello@xxxxxxx> > > AMD systems that support preferred cores will use "166" as their > numerator for max frequency calculations instead of "255". > > Add a function for detecting preferred cores by looking at the > highest perf value on all cores. > > If preferred cores are enabled return 166 and if disabled the > value in the highest perf register. As the function will be called > multiple times, cache the values for the boost numerator and if > preferred cores will be enabled in global variables. > > Signed-off-by: Mario Limonciello <mario.limonciello@xxxxxxx> > --- [..snip..] > /** > * amd_get_boost_ratio_numerator: Get the numerator to use for boost ratio calculation > * @cpu: CPU to get numerator for. > @@ -162,20 +232,19 @@ EXPORT_SYMBOL_GPL(amd_get_highest_perf); > */ > int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator) > { > - struct cpuinfo_x86 *c = &boot_cpu_data; > + bool prefcore; > + int ret; > > - if (c->x86 == 0x17 && ((c->x86_model >= 0x30 && c->x86_model < 0x40) || > - (c->x86_model >= 0x70 && c->x86_model < 0x80))) { > - *numerator = 166; > - return 0; > - } > + ret = amd_detect_prefcore(&prefcore); > + if (ret) > + return ret; > > - if (c->x86 == 0x19 && ((c->x86_model >= 0x20 && c->x86_model < 0x30) || > - (c->x86_model >= 0x40 && c->x86_model < 0x70))) { > - *numerator = 166; > + /* without preferred cores, return the highest perf register value */ > + if (!prefcore) { > + *numerator = boost_numerator; > return 0; > } > - *numerator = 255; > + *numerator = CPPC_HIGHEST_PERF_PREFCORE; Interesting. So even when the user boots a system that supports preferred-cores with "amd_preferred=disable", amd_get_boost_ratio_numerator() will return CPPC_HIGHEST_PERF_PREFCORE as the call prefcore == true here. I suppose that is as intended, since even though the user may not want to use the preferred core logic for task-scheduling/load-balancing, the numerator for the boost-ratio is purely dependent on the h/w capability. Is this understanding correct? If so, can this be included as a comment in the code ? The rest of the patch looks good to me. Reviewed-by: Gautham R. Shenoy <gautham.shenoy@xxxxxxx> -- Thanks and Regards gautham. > > return 0; > } > diff --git a/drivers/cpufreq/amd-pstate.c b/drivers/cpufreq/amd-pstate.c > index f470b5700db58..ec32c830abc1d 100644 > --- a/drivers/cpufreq/amd-pstate.c > +++ b/drivers/cpufreq/amd-pstate.c > @@ -807,32 +807,18 @@ static DECLARE_WORK(sched_prefcore_work, amd_pstste_sched_prefcore_workfn); > > static void amd_pstate_init_prefcore(struct amd_cpudata *cpudata) > { > - int ret, prio; > - u32 highest_perf; > - > - ret = amd_get_highest_perf(cpudata->cpu, &highest_perf); > - if (ret) > + /* user disabled or not detected */ > + if (!amd_pstate_prefcore) > return; > > cpudata->hw_prefcore = true; > - /* check if CPPC preferred core feature is enabled*/ > - if (highest_perf < CPPC_MAX_PERF) > - prio = (int)highest_perf; > - else { > - pr_debug("AMD CPPC preferred core is unsupported!\n"); > - cpudata->hw_prefcore = false; > - return; > - } > - > - if (!amd_pstate_prefcore) > - return; > > /* > * The priorities can be set regardless of whether or not > * sched_set_itmt_support(true) has been called and it is valid to > * update them at any time after it has been called. > */ > - sched_set_itmt_core_prio(prio, cpudata->cpu); > + sched_set_itmt_core_prio((int)READ_ONCE(cpudata->highest_perf), cpudata->cpu); > > schedule_work(&sched_prefcore_work); > } > @@ -998,12 +984,12 @@ static int amd_pstate_cpu_init(struct cpufreq_policy *policy) > > cpudata->cpu = policy->cpu; > > - amd_pstate_init_prefcore(cpudata); > - > ret = amd_pstate_init_perf(cpudata); > if (ret) > goto free_cpudata1; > > + amd_pstate_init_prefcore(cpudata); > + > ret = amd_pstate_init_freq(cpudata); > if (ret) > goto free_cpudata1; > @@ -1453,12 +1439,12 @@ static int amd_pstate_epp_cpu_init(struct cpufreq_policy *policy) > cpudata->cpu = policy->cpu; > cpudata->epp_policy = 0; > > - amd_pstate_init_prefcore(cpudata); > - > ret = amd_pstate_init_perf(cpudata); > if (ret) > goto free_cpudata1; > > + amd_pstate_init_prefcore(cpudata); > + > ret = amd_pstate_init_freq(cpudata); > if (ret) > goto free_cpudata1; > @@ -1903,6 +1889,12 @@ static int __init amd_pstate_init(void) > static_call_update(amd_pstate_update_perf, cppc_update_perf); > } > > + if (amd_pstate_prefcore) { > + ret = amd_detect_prefcore(&amd_pstate_prefcore); > + if (ret) > + return ret; > + } > + > /* enable amd pstate feature */ > ret = amd_pstate_enable(true); > if (ret) { > diff --git a/include/acpi/cppc_acpi.h b/include/acpi/cppc_acpi.h > index 2246ce0630362..1d79320a23490 100644 > --- a/include/acpi/cppc_acpi.h > +++ b/include/acpi/cppc_acpi.h > @@ -137,10 +137,12 @@ struct cppc_cpudata { > }; > > #ifdef CONFIG_CPU_SUP_AMD > +extern int amd_detect_prefcore(bool *detected); > extern int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf); > extern int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator); > #else /* !CONFIG_CPU_SUP_AMD */ > static inline int amd_get_highest_perf(unsigned int cpu, u32 *highest_perf) { return -ENODEV; } > +static inline int amd_detect_prefcore(bool *detected) { return -ENODEV; } > static inline int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator) { return -ENODEV; } > #endif /* !CONFIG_CPU_SUP_AMD */ > > -- > 2.43.0 >