Hi Lukasz,

When accessing the max_freq and min_freq at devfreq-cooling.c,
even if can access 'user_max_freq' and 'lock' by using the 'devfreq' instance,
I think that the direct access of variables (lock/user_max_freq/user_min_freq)
of struct devfreq are not good.

Instead, how about using the 'DEVFREQ_TRANSITION_NOTIFIER'
notification with following changes of 'struct devfreq_freq'?
Also, need to add codes into devfreq_set_target() for initializing
'new_max_freq' and 'new_min_freq' before sending the DEVFREQ_POSTCHANGE
notification.

diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
index 147a229056d2..d5726592d362 100644
--- a/include/linux/devfreq.h
+++ b/include/linux/devfreq.h
@@ -207,6 +207,8 @@ struct devfreq {
 struct devfreq_freqs {
        unsigned long old;
        unsigned long new;
+       unsigned long new_max_freq;
+       unsigned long new_min_freq;
 };


And I think that new 'user_min_freq'/'user_max_freq' are not necessary.
You can get the current max_freq/min_freq by using the following steps:

        get_freq_range(devfreq, &min_freq, &max_freq);
        dev_pm_opp_find_freq_floor(pdev, &min_freq);
        dev_pm_opp_find_freq_floor(pdev, &max_freq);

So that you can get the 'max_freq/min_freq' and then
initialize the 'freqs.new_max_freq and freqs.new_min_freq'
with them as following:

in devfreq_set_target()
        get_freq_range(devfreq, &min_freq, &max_freq);
        dev_pm_opp_find_freq_floor(pdev, &min_freq);
        dev_pm_opp_find_freq_floor(pdev, &max_freq);
        freqs.new_max_freq = min_freq;
        freqs.new_max_freq = max_freq;
        devfreq_notify_transition(devfreq, &freqs, DEVFREQ_POSTCHANGE);


On 1/26/21 7:39 PM, Lukasz Luba wrote:
> The new fields inside devfreq struct allow to check the frequency limits
> set by the user via sysfs. These limits are important for thermal governor
> Intelligent Power Allocation (IPA) which needs to know the maximum allowed
> power consumption of the device.
> 
> Signed-off-by: Lukasz Luba <lukasz.l...@arm.com>
> ---
>  drivers/devfreq/devfreq.c | 41 +++++++++++++++++++++++++++++++++++----
>  include/linux/devfreq.h   |  4 ++++
>  2 files changed, 41 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
> index 94cc25fd68da..e985a76e5ff3 100644
> --- a/drivers/devfreq/devfreq.c
> +++ b/drivers/devfreq/devfreq.c
> @@ -843,6 +843,9 @@ struct devfreq *devfreq_add_device(struct device *dev,
>               goto err_dev;
>       }
>  
> +     devfreq->user_min_freq = devfreq->scaling_min_freq;
> +     devfreq->user_max_freq = devfreq->scaling_max_freq;
> +
>       devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
>       atomic_set(&devfreq->suspend_count, 0);
>  
> @@ -1513,6 +1516,8 @@ static ssize_t min_freq_store(struct device *dev, 
> struct device_attribute *attr,
>                             const char *buf, size_t count)
>  {
>       struct devfreq *df = to_devfreq(dev);
> +     struct device *pdev = df->dev.parent;
> +     struct dev_pm_opp *opp;
>       unsigned long value;
>       int ret;
>  
> @@ -1533,6 +1538,19 @@ static ssize_t min_freq_store(struct device *dev, 
> struct device_attribute *attr,
>       if (ret < 0)
>               return ret;
>  
> +     if (!value)
> +             value = df->scaling_min_freq;
> +
> +     opp = dev_pm_opp_find_freq_ceil(pdev, &value);
> +     if (IS_ERR(opp))
> +             return count;
> +
> +     dev_pm_opp_put(opp);
> +
> +     mutex_lock(&df->lock);
> +     df->user_min_freq = value;
> +     mutex_unlock(&df->lock);
> +
>       return count;
>  }
>  
> @@ -1554,7 +1572,9 @@ static ssize_t max_freq_store(struct device *dev, 
> struct device_attribute *attr,
>                             const char *buf, size_t count)
>  {
>       struct devfreq *df = to_devfreq(dev);
> -     unsigned long value;
> +     struct device *pdev = df->dev.parent;
> +     unsigned long value, value_khz;
> +     struct dev_pm_opp *opp;
>       int ret;
>  
>       /*
> @@ -1579,14 +1599,27 @@ static ssize_t max_freq_store(struct device *dev, 
> struct device_attribute *attr,
>        * A value of zero means "no limit".
>        */
>       if (value)
> -             value = DIV_ROUND_UP(value, HZ_PER_KHZ);
> +             value_khz = DIV_ROUND_UP(value, HZ_PER_KHZ);
>       else
> -             value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
> +             value_khz = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
>  
> -     ret = dev_pm_qos_update_request(&df->user_max_freq_req, value);
> +     ret = dev_pm_qos_update_request(&df->user_max_freq_req, value_khz);
>       if (ret < 0)
>               return ret;
>  
> +     if (!value)
> +             value = df->scaling_max_freq;
> +
> +     opp = dev_pm_opp_find_freq_floor(pdev, &value);
> +     if (IS_ERR(opp))
> +             return count;
> +
> +     dev_pm_opp_put(opp);
> +
> +     mutex_lock(&df->lock);
> +     df->user_max_freq = value;
> +     mutex_unlock(&df->lock);
> +
>       return count;
>  }
>  
> diff --git a/include/linux/devfreq.h b/include/linux/devfreq.h
> index b6d3bae1c74d..147a229056d2 100644
> --- a/include/linux/devfreq.h
> +++ b/include/linux/devfreq.h
> @@ -147,6 +147,8 @@ struct devfreq_stats {
>   *           touch this.
>   * @user_min_freq_req:       PM QoS minimum frequency request from user (via 
> sysfs)
>   * @user_max_freq_req:       PM QoS maximum frequency request from user (via 
> sysfs)
> + * @user_min_freq:   User's minimum frequency
> + * @user_max_freq:   User's maximum frequency
>   * @scaling_min_freq:        Limit minimum frequency requested by OPP 
> interface
>   * @scaling_max_freq:        Limit maximum frequency requested by OPP 
> interface
>   * @stop_polling:     devfreq polling status of a device.
> @@ -185,6 +187,8 @@ struct devfreq {
>       struct dev_pm_qos_request user_max_freq_req;
>       unsigned long scaling_min_freq;
>       unsigned long scaling_max_freq;
> +     unsigned long user_min_freq;
> +     unsigned long user_max_freq;
>       bool stop_polling;
>  
>       unsigned long suspend_freq;
> 


-- 
Best Regards,
Chanwoo Choi
Samsung Electronics

Reply via email to