[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH v9 7/8] xen/cpufreq: Adapt SET/GET_CPUFREQ_CPPC xen_sysctl_pm_op for amd-cppc driver
On 04.09.2025 08:35, Penny Zheng wrote: > Introduce helper set_amd_cppc_para() and get_amd_cppc_para() to > SET/GET CPPC-related para for amd-cppc/amd-cppc-epp driver. > > In get_cpufreq_cppc()/set_cpufreq_cppc(), we include > "processor_pminfo[cpuid]->init & XEN_CPPC_INIT" condition check to deal with > cpufreq driver in amd-cppc. > We borrow governor field to indicate policy info for CPPC active mode, > so we need to move the copying of the governor name out of the > !cpufreq_is_governorless() guard. Well, as said in my v8 comment - it's not so much the "what" that needs covering, but the "why is it correct / safe to do so". See my respective reply to patch 5, and also to Jason's response on the v8 thread. Perhaps with the union there removed this doesn't need calling out explicitly anymore. > --- > v8 -> v9 > - add description of "moving the copying of the governor name" > - Adapt to changes of "Embed struct amd_cppc_drv_data{} into struct > cpufreq_policy{}" Except that again problems extend to here as well. > --- a/xen/arch/x86/acpi/cpufreq/amd-cppc.c > +++ b/xen/arch/x86/acpi/cpufreq/amd-cppc.c > @@ -561,6 +561,169 @@ static int cf_check amd_cppc_epp_set_policy(struct > cpufreq_policy *policy) > return 0; > } > > +#ifdef CONFIG_PM_OP > +int amd_cppc_get_para(const struct cpufreq_policy *policy, > + struct xen_get_cppc_para *cppc_para) > +{ > + const struct amd_cppc_drv_data *data = policy->u.amd_cppc; > + > + if ( data == NULL ) > + return -ENODATA; > + > + cppc_para->lowest = data->caps.lowest_perf; > + cppc_para->lowest_nonlinear = data->caps.lowest_nonlinear_perf; > + cppc_para->nominal = data->caps.nominal_perf; > + cppc_para->highest = data->caps.highest_perf; > + cppc_para->minimum = data->req.min_perf; > + cppc_para->maximum = data->req.max_perf; > + cppc_para->desired = data->req.des_perf; > + cppc_para->energy_perf = data->req.epp; > + > + return 0; > +} > + > +int amd_cppc_set_para(struct cpufreq_policy *policy, > + const struct xen_set_cppc_para *set_cppc) > +{ > + struct amd_cppc_drv_data *data = policy->u.amd_cppc; > + uint8_t max_perf, min_perf, des_perf, epp; > + bool active_mode = cpufreq_is_governorless(policy->cpu); > + > + if ( data == NULL ) > + return -ENOENT; > + > + /* Only allow values if params bit is set. */ > + if ( (!(set_cppc->set_params & XEN_SYSCTL_CPPC_SET_DESIRED) && > + set_cppc->desired) || > + (!(set_cppc->set_params & XEN_SYSCTL_CPPC_SET_MINIMUM) && > + set_cppc->minimum) || > + (!(set_cppc->set_params & XEN_SYSCTL_CPPC_SET_MAXIMUM) && > + set_cppc->maximum) || > + (!(set_cppc->set_params & XEN_SYSCTL_CPPC_SET_ENERGY_PERF) && > + set_cppc->energy_perf) ) > + return -EINVAL; > + > + /* Return if there is nothing to do. */ > + if ( set_cppc->set_params == 0 ) > + return 0; > + > + /* > + * Validate all parameters > + * Maximum performance may be set to any performance value in the range > + * [Nonlinear Lowest Performance, Highest Performance], inclusive but > must > + * be set to a value that is larger than or equal to minimum Performance. > + */ > + if ( (set_cppc->set_params & XEN_SYSCTL_CPPC_SET_MAXIMUM) && > + (set_cppc->maximum > data->caps.highest_perf || > + (set_cppc->maximum < > + (set_cppc->set_params & XEN_SYSCTL_CPPC_SET_MINIMUM > + ? set_cppc->minimum > + : data->req.min_perf))) ) > + return -EINVAL; > + /* > + * Minimum performance may be set to any performance value in the range > + * [Nonlinear Lowest Performance, Highest Performance], inclusive but > must > + * be set to a value that is less than or equal to Maximum Performance. > + */ > + if ( (set_cppc->set_params & XEN_SYSCTL_CPPC_SET_MINIMUM) && > + (set_cppc->minimum < data->caps.lowest_nonlinear_perf || > + (set_cppc->minimum > > + (set_cppc->set_params & XEN_SYSCTL_CPPC_SET_MAXIMUM > + ? set_cppc->maximum > + : data->req.max_perf))) ) > + return -EINVAL; > + /* > + * Desired performance may be set to any performance value in the range > + * [Minimum Performance, Maximum Performance], inclusive. > + */ > + if ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_DESIRED ) > + { > + if ( active_mode ) > + return -EOPNOTSUPP; > + > + if ( (set_cppc->desired > > + (set_cppc->set_params & XEN_SYSCTL_CPPC_SET_MAXIMUM > + ? set_cppc->maximum > + : data->req.max_perf)) || > + (set_cppc->desired < > + (set_cppc->set_params & XEN_SYSCTL_CPPC_SET_MINIMUM > + ? set_cppc->minimum > + : data->req.min_perf)) ) > + return -EINVAL; > + } > + /* > + * Energy Performance Preference may be set with a range of values > + * from 0 to 0xFF > + */ > + if ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_ENERGY_PERF ) > + { > + if ( !active_mode ) > + return -EOPNOTSUPP; > + > + if ( set_cppc->energy_perf > UINT8_MAX ) > + return -EINVAL; > + } > + > + /* Activity window not supported in MSR */ > + if ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_ACT_WINDOW ) > + return -EOPNOTSUPP; > + > + des_perf = data->req.des_perf; > + /* > + * Apply presets: > + * XEN_SYSCTL_CPPC_SET_PRESET_POWERSAVE/PERFORMANCE/ONDEMAND are > + * only available when CPPC in active mode > + */ > + switch ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_PRESET_MASK ) > + { > + case XEN_SYSCTL_CPPC_SET_PRESET_POWERSAVE: > + if ( !active_mode ) > + return -EINVAL; > + policy->policy = CPUFREQ_POLICY_POWERSAVE; > + break; > + > + case XEN_SYSCTL_CPPC_SET_PRESET_PERFORMANCE: > + if ( !active_mode ) > + return -EINVAL; > + policy->policy = CPUFREQ_POLICY_PERFORMANCE; > + break; > + > + case XEN_SYSCTL_CPPC_SET_PRESET_ONDEMAND: > + if ( !active_mode ) > + return -EINVAL; > + policy->policy = CPUFREQ_POLICY_ONDEMAND; > + break; > + > + case XEN_SYSCTL_CPPC_SET_PRESET_NONE: > + if ( active_mode ) > + policy->policy = CPUFREQ_POLICY_UNKNOWN; > + break; > + > + default: > + return -EINVAL; > + } > + amd_cppc_prepare_policy(policy, &max_perf, &min_perf, &epp); > + > + /* Further customize presets if needed */ > + if ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_MINIMUM ) > + min_perf = set_cppc->minimum; > + > + if ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_MAXIMUM ) > + max_perf = set_cppc->maximum; > + > + if ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_ENERGY_PERF ) > + epp = set_cppc->energy_perf; > + > + if ( set_cppc->set_params & XEN_SYSCTL_CPPC_SET_DESIRED ) > + des_perf = set_cppc->desired; > + > + amd_cppc_write_request(policy->cpu, data, Like elsewhere, policy->cpu may not be online. > --- a/xen/drivers/acpi/pm-op.c > +++ b/xen/drivers/acpi/pm-op.c > @@ -84,6 +84,8 @@ static int get_cpufreq_cppc(unsigned int cpu, > > if ( hwp_active() ) > ret = get_hwp_para(cpu, cppc_para); > + else if ( processor_pminfo[cpu]->init & XEN_CPPC_INIT ) > + ret = amd_cppc_get_para(per_cpu(cpufreq_cpu_policy, cpu), cppc_para); > > return ret; > } > @@ -154,6 +156,17 @@ static int get_cpufreq_para(struct xen_sysctl_pm_op *op) > else > strlcpy(op->u.get_para.scaling_driver, "Unknown", CPUFREQ_NAME_LEN); > > + /* > + * In CPPC active mode, we are borrowing governor field to indicate > + * policy info. > + */ > + if ( policy->governor->name[0] ) > + strlcpy(op->u.get_para.u.s.scaling_governor, > + policy->governor->name, CPUFREQ_NAME_LEN); > + else > + strlcpy(op->u.get_para.u.s.scaling_governor, "Unknown", > + CPUFREQ_NAME_LEN); > + > if ( !cpufreq_is_governorless(op->cpuid) ) > { > if ( !(scaling_available_governors = > @@ -178,13 +191,6 @@ static int get_cpufreq_para(struct xen_sysctl_pm_op *op) > op->u.get_para.u.s.scaling_max_freq = policy->max; > op->u.get_para.u.s.scaling_min_freq = policy->min; > > - if ( policy->governor->name[0] ) > - strlcpy(op->u.get_para.u.s.scaling_governor, > - policy->governor->name, CPUFREQ_NAME_LEN); > - else > - strlcpy(op->u.get_para.u.s.scaling_governor, "Unknown", > - CPUFREQ_NAME_LEN); Just to re-iterate here: Pulling this out is okay because the union has no other member anymore, and hence other date cannot be badly impacted. Jan
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |