[PATCH 1/3] cpufreq: Add a driver frequency resolution callback

Jie Zhan zhanjie9 at hisilicon.com
Wed Oct 14 20:57:16 PDT 2026



On 9/29/2026 6:29 PM, Christian Loehle wrote:
> Without a frequency table, cpufreq treats the policy range as continuous
> even when the driver selects discrete performance levels. Governors can
> then issue different kHz requests for the same driver setting.
> 
> Add ->resolve_freq() for table-less ->target() drivers to canonicalize
> requests within the supplied limits using CPUFREQ_RELATION_{L,H,C}.
> Document the callback and verification contracts so callers can safely
> cache resolved requests.
Hi Christian,

IIUC, ->target() + ->resolve_freq() should do almost the same work as
->target_index() + freq_table. Why not switch to ->target_index() if that's
intended?

I had a few unsent comments on the second CPPC patch but perhaps we discuss
this first.

Jie
> 
> Signed-off-by: Christian Loehle <christian.loehle at arm.com>
> ---
>  Documentation/admin-guide/pm/cpufreq.rst |  4 ++++
>  Documentation/cpu-freq/cpu-drivers.rst   | 19 +++++++++++++++++++
>  drivers/cpufreq/cpufreq.c                | 17 +++++++++++++++--
>  include/linux/cpufreq.h                  | 10 ++++++++++
>  4 files changed, 48 insertions(+), 2 deletions(-)
> 
[...]
>  
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index 54dde8419bdc..44bda2f32fcf 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -480,8 +480,12 @@ static unsigned int __resolve_freq(struct cpufreq_policy *policy,
>  
>  	target_freq = clamp_val(target_freq, min, max);
>  
> -	if (!policy->freq_table)
> +	if (!policy->freq_table) {
> +		if (cpufreq_driver->resolve_freq)
> +			return cpufreq_driver->resolve_freq(policy, target_freq, min, max,
> +							    relation & ~CPUFREQ_RELATION_E);
>  		return target_freq;
> +	}
>  
>  	idx = cpufreq_frequency_table_target(policy, target_freq, min, max, relation);
>  	policy->cached_resolved_idx = idx;
> @@ -495,7 +499,10 @@ static unsigned int __resolve_freq(struct cpufreq_policy *policy,
>   * @policy: associated policy to interrogate
>   * @target_freq: target frequency to resolve.
>   *
> - * The target to driver frequency mapping is cached in the policy.
> + * The frequency-table resolution path caches the mapping in the policy.
> + *
> + * Keep the policy active and exclude driver teardown; a policy reference
> + * alone does not protect driver-private data.
Do you mean the caller should ensure this?
This function doesn't seem to do this.
>   *
>   * Return: Lowest driver-supported frequency greater than or equal to the
>   * given target_freq, subject to policy (min/max) and driver limitations.
> @@ -1445,6 +1452,11 @@ static int cpufreq_policy_online(struct cpufreq_policy *policy,
>  		 * If there is a problem with its frequency table, take it
>  		 * offline and drop it.
>  		 */
> +		if (policy->freq_table && cpufreq_driver->resolve_freq) {
> +			ret = -EINVAL;
> +			goto out_offline_policy;
> +		}
> +
>  		ret = cpufreq_table_validate_and_sort(policy);
>  		if (ret)
>  			goto out_offline_policy;
> @@ -2925,6 +2937,7 @@ int cpufreq_register_driver(struct cpufreq_driver *driver_data)
>  
>  	if (!driver_data || !driver_data->verify || !driver_data->init ||
>  	     (driver_data->target_index && driver_data->target) ||
> +	     (driver_data->resolve_freq && !driver_data->target) ||
>  	     (!!driver_data->setpolicy == (driver_data->target_index || driver_data->target)) ||
>  	     (!driver_data->get_intermediate != !driver_data->target_intermediate) ||
>  	     (!driver_data->online != !driver_data->offline) ||
[...]



More information about the linux-arm-kernel mailing list