[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v5 10/18] xen/cpufreq: introduce a new amd cppc driver for cpufreq scaling
On 27.05.2025 10:48, Penny Zheng wrote: > --- a/xen/arch/x86/acpi/cpufreq/amd-cppc.c > +++ b/xen/arch/x86/acpi/cpufreq/amd-cppc.c > @@ -14,7 +14,56 @@ > #include <xen/domain.h> > #include <xen/init.h> > #include <xen/param.h> > +#include <xen/percpu.h> > +#include <xen/xvmalloc.h> > #include <acpi/cpufreq/cpufreq.h> > +#include <asm/amd.h> > +#include <asm/msr-index.h> > + > +#define amd_cppc_err(cpu, fmt, args...) \ > + printk(XENLOG_ERR "AMD_CPPC: CPU%u error: " fmt, cpu, ## args) > +#define amd_cppc_warn(cpu, fmt, args...) \ > + printk(XENLOG_WARNING "AMD_CPPC: CPU%u warning: " fmt, cpu, ## args) > +#define amd_cppc_verbose(cpu, fmt, args...) \ > +({ \ > + if ( cpufreq_verbose ) \ > + printk(XENLOG_DEBUG "AMD_CPPC: CPU%u " fmt, cpu, ## args); \ > +}) Nit: Much like in the file name, would you mind using AMD-CPPC in favor of AMD_CPPC here, too? > @@ -50,10 +99,323 @@ int __init amd_cppc_cmdline_parse(const char *s, const > char *e) > return 0; > } > > +/* > + * If CPPC lowest_freq and nominal_freq registers are exposed then we can > + * use them to convert perf to freq and vice versa. The conversion is > + * extrapolated as an linear function passing by the 2 points: > + * - (Low perf, Low freq) > + * - (Nominal perf, Nominal freq) > + * Parameter freq is always in kHz. > + */ > +static int amd_cppc_khz_to_perf(const struct amd_cppc_drv_data *data, > + unsigned int freq, uint8_t *perf) > +{ > + const struct xen_processor_cppc *cppc_data = data->cppc_data; > + unsigned int mul, div; > + int offset = 0, res; > + > + if ( cppc_data->cpc.lowest_mhz && cppc_data->cpc.nominal_mhz ) > + { > + mul = data->caps.nominal_perf - data->caps.lowest_perf; > + div = cppc_data->cpc.nominal_mhz - cppc_data->cpc.lowest_mhz; What guarantees both of these values to be non-zero? > + /* > + * We don't need to convert to kHz for computing offset and can > + * directly use nominal_mhz and lowest_mhz as the division > + * will remove the frequency unit. > + */ > + offset = data->caps.nominal_perf - > + (mul * cppc_data->cpc.nominal_mhz) / div; > + } > + else > + { > + /* Read Processor Max Speed(MHz) as anchor point */ > + mul = data->caps.highest_perf; > + div = this_cpu(pxfreq_mhz); > + if ( !div ) > + return -EINVAL; What's wrong about the function arguments in this case? (Same question again on further uses of EINVAL below.) > +static int cf_check amd_cppc_cpufreq_target(struct cpufreq_policy *policy, > + unsigned int target_freq, > + unsigned int relation) > +{ > + unsigned int cpu = policy->cpu; > + const struct amd_cppc_drv_data *data = per_cpu(amd_cppc_drv_data, cpu); > + uint8_t des_perf; > + int res; > + > + if ( unlikely(!target_freq) ) > + return 0; > + > + res = amd_cppc_khz_to_perf(data, target_freq, &des_perf); > + if ( res ) > + return res; > + > + /* > + * Setting with "lowest_nonlinear_perf" to ensure governoring > + * performance in P-state range. > + */ > + amd_cppc_write_request(policy->cpu, data->caps.lowest_nonlinear_perf, > + des_perf, data->caps.highest_perf); I fear I don't understand the comment, and hence it remains unclear to me why lowest_nonlinear_perf is being used here. > +static int cf_check amd_cppc_cpufreq_cpu_init(struct cpufreq_policy *policy) > +{ > + unsigned int cpu = policy->cpu; > + struct amd_cppc_drv_data *data; > + > + data = xvzalloc(struct amd_cppc_drv_data); > + if ( !data ) > + return -ENOMEM; > + > + data->cppc_data = &processor_pminfo[cpu]->cppc_data; > + > + per_cpu(amd_cppc_drv_data, cpu) = data; > + > + on_selected_cpus(cpumask_of(cpu), amd_cppc_init_msrs, policy, 1); > + > + /* > + * The enable bit is sticky, as we need to enable it at the very first > + * begining, before CPPC capability values sanity check. > + * If error path takes effective, not only amd-cppc cpufreq core fails Nit: "takes effect" or "is taken". > + * to initialize, but also we could not fall back to legacy P-states > + * driver, irrespective of the command line specifying a fallback option. > + */ > + if ( data->err ) > + { > + amd_cppc_err(cpu, "Could not initialize cpufreq cores in CPPC > mode\n"); Why "cores" (plural)? Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |