All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed
@ 2023-07-19 13:05 Xuewen Yan
  2023-07-21 22:19 ` Qais Yousef
                   ` (2 more replies)
  0 siblings, 3 replies; 14+ messages in thread
From: Xuewen Yan @ 2023-07-19 13:05 UTC (permalink / raw)
  To: rafael, viresh.kumar, mingo, peterz, vincent.guittot
  Cc: dietmar.eggemann, rostedt, bsegall, mgorman, bristot, vschneid,
	guohua.yan, qyousef, linux-pm, linux-kernel

When cpufreq's policy is single, there is a scenario that will
cause sg_policy's next_freq to be unable to update.

When the cpu's util is always max, the cpufreq will be max,
and then if we change the policy's scaling_max_freq to be a
lower freq, indeed, the sg_policy's next_freq need change to
be the lower freq, however, because the cpu_is_busy, the next_freq
would keep the max_freq.

For example:
The cpu7 is single cpu:

unisoc:/sys/devices/system/cpu/cpufreq/policy7 # while true;do done&
[1] 4737
unisoc:/sys/devices/system/cpu/cpufreq/policy7 # taskset -p 80 4737
pid 4737's current affinity mask: ff
pid 4737's new affinity mask: 80
unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
2301000
unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_cur_freq
2301000
unisoc:/sys/devices/system/cpu/cpufreq/policy7 # echo 2171000 > scaling_max_freq
unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
2171000

At this time, the sg_policy's next_freq would keep 2301000.

To prevent the case happen, add the judgment of the need_freq_update flag.

Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com>
Co-developed-by: Guohua Yan <guohua.yan@unisoc.com>
Signed-off-by: Guohua Yan <guohua.yan@unisoc.com>
---
 kernel/sched/cpufreq_schedutil.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 4492608b7d7f..458d359f5991 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
 	 * Except when the rq is capped by uclamp_max.
 	 */
 	if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) &&
-	    sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
+	    sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq &&
+	    !sg_policy->need_freq_update) {
 		next_f = sg_policy->next_freq;
 
 		/* Restore cached freq as next_freq has changed */
-- 
2.25.1


^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed
  2023-07-19 13:05 [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed Xuewen Yan
@ 2023-07-21 22:19 ` Qais Yousef
  2023-07-24  3:36   ` Xuewen Yan
  2023-10-05 11:26 ` Ingo Molnar
  2023-10-05 20:23 ` [tip: sched/urgent] cpufreq: schedutil: Update next_freq when cpufreq_limits change tip-bot2 for Xuewen Yan
  2 siblings, 1 reply; 14+ messages in thread
From: Qais Yousef @ 2023-07-21 22:19 UTC (permalink / raw)
  To: Xuewen Yan
  Cc: rafael, viresh.kumar, mingo, peterz, vincent.guittot,
	dietmar.eggemann, rostedt, bsegall, mgorman, bristot, vschneid,
	guohua.yan, linux-pm, linux-kernel

On 07/19/23 21:05, Xuewen Yan wrote:
> When cpufreq's policy is single, there is a scenario that will
> cause sg_policy's next_freq to be unable to update.
> 
> When the cpu's util is always max, the cpufreq will be max,
> and then if we change the policy's scaling_max_freq to be a
> lower freq, indeed, the sg_policy's next_freq need change to
> be the lower freq, however, because the cpu_is_busy, the next_freq
> would keep the max_freq.
> 
> For example:
> The cpu7 is single cpu:
> 
> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # while true;do done&
> [1] 4737
> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # taskset -p 80 4737
> pid 4737's current affinity mask: ff
> pid 4737's new affinity mask: 80
> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> 2301000
> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_cur_freq
> 2301000
> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # echo 2171000 > scaling_max_freq
> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> 2171000
> 
> At this time, the sg_policy's next_freq would keep 2301000.
> 
> To prevent the case happen, add the judgment of the need_freq_update flag.
> 
> Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com>
> Co-developed-by: Guohua Yan <guohua.yan@unisoc.com>
> Signed-off-by: Guohua Yan <guohua.yan@unisoc.com>
> ---
>  kernel/sched/cpufreq_schedutil.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> index 4492608b7d7f..458d359f5991 100644
> --- a/kernel/sched/cpufreq_schedutil.c
> +++ b/kernel/sched/cpufreq_schedutil.c
> @@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
>  	 * Except when the rq is capped by uclamp_max.
>  	 */
>  	if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) &&
> -	    sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
> +	    sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq &&
> +	    !sg_policy->need_freq_update) {

What about sugov_update_single_perf()? It seems to have the same problem, no?

LGTM otherwise.


Cheers

--
Qais Yousef

>  		next_f = sg_policy->next_freq;
>  
>  		/* Restore cached freq as next_freq has changed */
> -- 
> 2.25.1
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed
  2023-07-21 22:19 ` Qais Yousef
@ 2023-07-24  3:36   ` Xuewen Yan
  2023-07-24 15:33     ` Pierre Gondois
  2023-07-24 15:53     ` Qais Yousef
  0 siblings, 2 replies; 14+ messages in thread
From: Xuewen Yan @ 2023-07-24  3:36 UTC (permalink / raw)
  To: Qais Yousef
  Cc: Xuewen Yan, rafael, viresh.kumar, mingo, peterz, vincent.guittot,
	dietmar.eggemann, rostedt, bsegall, mgorman, bristot, vschneid,
	guohua.yan, linux-pm, linux-kernel

On Sat, Jul 22, 2023 at 7:02 AM Qais Yousef <qyousef@layalina.io> wrote:
>
> On 07/19/23 21:05, Xuewen Yan wrote:
> > When cpufreq's policy is single, there is a scenario that will
> > cause sg_policy's next_freq to be unable to update.
> >
> > When the cpu's util is always max, the cpufreq will be max,
> > and then if we change the policy's scaling_max_freq to be a
> > lower freq, indeed, the sg_policy's next_freq need change to
> > be the lower freq, however, because the cpu_is_busy, the next_freq
> > would keep the max_freq.
> >
> > For example:
> > The cpu7 is single cpu:
> >
> > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # while true;do done&
> > [1] 4737
> > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # taskset -p 80 4737
> > pid 4737's current affinity mask: ff
> > pid 4737's new affinity mask: 80
> > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > 2301000
> > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_cur_freq
> > 2301000
> > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # echo 2171000 > scaling_max_freq
> > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > 2171000
> >
> > At this time, the sg_policy's next_freq would keep 2301000.
> >
> > To prevent the case happen, add the judgment of the need_freq_update flag.
> >
> > Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com>
> > Co-developed-by: Guohua Yan <guohua.yan@unisoc.com>
> > Signed-off-by: Guohua Yan <guohua.yan@unisoc.com>
> > ---
> >  kernel/sched/cpufreq_schedutil.c | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> > index 4492608b7d7f..458d359f5991 100644
> > --- a/kernel/sched/cpufreq_schedutil.c
> > +++ b/kernel/sched/cpufreq_schedutil.c
> > @@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
> >        * Except when the rq is capped by uclamp_max.
> >        */
> >       if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) &&
> > -         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
> > +         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq &&
> > +         !sg_policy->need_freq_update) {
>
> What about sugov_update_single_perf()? It seems to have the same problem, no?

There is no problem in sugov_update_single_perf, because the next_freq
is updated by drivers, maybe the next_freq is not used when using
sugov_update_single_perf..

But  for the last_freq_update_time, I think there are some problems
when using sugov_update_single_perf:
Now, there is no judgment condition for the update of the
last_freq_update_time. That means the last_freq_update_time is always
updated in sugov_update_single_perf.
And in sugov_should_update_freq: it would judge the
freq_update_delay_ns. As a result, If we use the
sugov_update_single_perf, the cpu frequency would only be periodically
updated according to freq_update_delay_ns.
Maybe we should judge the cpufreq_driver_adjust_perf's return value,
if the freq is not updated, the last_freq_update_time also does not
have to update.

Just like:
---
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 458d359f5991..10f18b054f01 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -381,6 +381,7 @@ static void sugov_update_single_perf(struct
update_util_data *hook, u64 time,
        struct sugov_cpu *sg_cpu = container_of(hook, struct
sugov_cpu, update_util);
        unsigned long prev_util = sg_cpu->util;
        unsigned long max_cap;
+       bool freq_updated;

        /*
         * Fall back to the "frequency" path if frequency invariance is not
@@ -407,10 +408,11 @@ static void sugov_update_single_perf(struct
update_util_data *hook, u64 time,
            sugov_cpu_is_busy(sg_cpu) && sg_cpu->util < prev_util)
                sg_cpu->util = prev_util;

-       cpufreq_driver_adjust_perf(sg_cpu->cpu, map_util_perf(sg_cpu->bw_dl),
+       freq_updated = cpufreq_driver_adjust_perf(sg_cpu->cpu,
map_util_perf(sg_cpu->bw_dl),
                                   map_util_perf(sg_cpu->util), max_cap);

-       sg_cpu->sg_policy->last_freq_update_time = time;
+       if (freq_updated)
+               sg_cpu->sg_policy->last_freq_update_time = time;
 }


BR
Thanks!

---
xuewen
>
> LGTM otherwise.
>
>
> Cheers
>
> --
> Qais Yousef
>
> >               next_f = sg_policy->next_freq;
> >
> >               /* Restore cached freq as next_freq has changed */
> > --
> > 2.25.1
> >

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed
  2023-07-24  3:36   ` Xuewen Yan
@ 2023-07-24 15:33     ` Pierre Gondois
  2023-07-25  2:01       ` Xuewen Yan
  2023-07-24 15:53     ` Qais Yousef
  1 sibling, 1 reply; 14+ messages in thread
From: Pierre Gondois @ 2023-07-24 15:33 UTC (permalink / raw)
  To: Xuewen Yan, Qais Yousef
  Cc: Xuewen Yan, rafael, viresh.kumar, mingo, peterz, vincent.guittot,
	dietmar.eggemann, rostedt, bsegall, mgorman, bristot, vschneid,
	guohua.yan, linux-pm, linux-kernel



On 7/24/23 05:36, Xuewen Yan wrote:
> On Sat, Jul 22, 2023 at 7:02 AM Qais Yousef <qyousef@layalina.io> wrote:
>>
>> On 07/19/23 21:05, Xuewen Yan wrote:
>>> When cpufreq's policy is single, there is a scenario that will
>>> cause sg_policy's next_freq to be unable to update.
>>>
>>> When the cpu's util is always max, the cpufreq will be max,
>>> and then if we change the policy's scaling_max_freq to be a
>>> lower freq, indeed, the sg_policy's next_freq need change to
>>> be the lower freq, however, because the cpu_is_busy, the next_freq
>>> would keep the max_freq.
>>>
>>> For example:
>>> The cpu7 is single cpu:
>>>
>>> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # while true;do done&
>>> [1] 4737
>>> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # taskset -p 80 4737
>>> pid 4737's current affinity mask: ff
>>> pid 4737's new affinity mask: 80
>>> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
>>> 2301000
>>> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_cur_freq
>>> 2301000
>>> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # echo 2171000 > scaling_max_freq
>>> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
>>> 2171000
>>>
>>> At this time, the sg_policy's next_freq would keep 2301000.
>>>
>>> To prevent the case happen, add the judgment of the need_freq_update flag.
>>>
>>> Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com>
>>> Co-developed-by: Guohua Yan <guohua.yan@unisoc.com>
>>> Signed-off-by: Guohua Yan <guohua.yan@unisoc.com>
>>> ---
>>>   kernel/sched/cpufreq_schedutil.c | 3 ++-
>>>   1 file changed, 2 insertions(+), 1 deletion(-)
>>>
>>> diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
>>> index 4492608b7d7f..458d359f5991 100644
>>> --- a/kernel/sched/cpufreq_schedutil.c
>>> +++ b/kernel/sched/cpufreq_schedutil.c
>>> @@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
>>>         * Except when the rq is capped by uclamp_max.
>>>         */
>>>        if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) &&
>>> -         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
>>> +         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq &&
>>> +         !sg_policy->need_freq_update) {
>>
>> What about sugov_update_single_perf()? It seems to have the same problem, no?
> 
> There is no problem in sugov_update_single_perf, because the next_freq
> is updated by drivers, maybe the next_freq is not used when using
> sugov_update_single_perf..
> 
> But  for the last_freq_update_time, I think there are some problems
> when using sugov_update_single_perf:
> Now, there is no judgment condition for the update of the
> last_freq_update_time. That means the last_freq_update_time is always
> updated in sugov_update_single_perf.
> And in sugov_should_update_freq: it would judge the
> freq_update_delay_ns. As a result, If we use the
> sugov_update_single_perf, the cpu frequency would only be periodically
> updated according to freq_update_delay_ns.
> Maybe we should judge the cpufreq_driver_adjust_perf's return value,
> if the freq is not updated, the last_freq_update_time also does not
> have to update.
> 
> Just like:
> ---
> diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> index 458d359f5991..10f18b054f01 100644
> --- a/kernel/sched/cpufreq_schedutil.c
> +++ b/kernel/sched/cpufreq_schedutil.c
> @@ -381,6 +381,7 @@ static void sugov_update_single_perf(struct
> update_util_data *hook, u64 time,
>          struct sugov_cpu *sg_cpu = container_of(hook, struct
> sugov_cpu, update_util);
>          unsigned long prev_util = sg_cpu->util;
>          unsigned long max_cap;
> +       bool freq_updated;
> 
>          /*
>           * Fall back to the "frequency" path if frequency invariance is not
> @@ -407,10 +408,11 @@ static void sugov_update_single_perf(struct
> update_util_data *hook, u64 time,
>              sugov_cpu_is_busy(sg_cpu) && sg_cpu->util < prev_util)
>                  sg_cpu->util = prev_util;
> 
> -       cpufreq_driver_adjust_perf(sg_cpu->cpu, map_util_perf(sg_cpu->bw_dl),
> +       freq_updated = cpufreq_driver_adjust_perf(sg_cpu->cpu,
> map_util_perf(sg_cpu->bw_dl),
>                                     map_util_perf(sg_cpu->util), max_cap);
> 
> -       sg_cpu->sg_policy->last_freq_update_time = time;
> +       if (freq_updated)
> +               sg_cpu->sg_policy->last_freq_update_time = time;
>   }
> 

Hello Xuewen,
FWIW, the patch and explanation for sugov_update_single_perf() seem sensible to
me. Just a comment about cpufreq_driver_adjust_perf() and
(struct cpufreq_driver)->adjust_perf(): wouldn't their prototype need to be
updated (i.e. not return void) to do the change suggested above ?

Regards,
Pierre

> 
> BR
> Thanks!
> 
> ---
> xuewen
>>
>> LGTM otherwise.
>>
>>
>> Cheers
>>
>> --
>> Qais Yousef
>>
>>>                next_f = sg_policy->next_freq;
>>>
>>>                /* Restore cached freq as next_freq has changed */
>>> --
>>> 2.25.1
>>>
> 

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed
  2023-07-24  3:36   ` Xuewen Yan
  2023-07-24 15:33     ` Pierre Gondois
@ 2023-07-24 15:53     ` Qais Yousef
  2023-07-25  2:21       ` Xuewen Yan
  1 sibling, 1 reply; 14+ messages in thread
From: Qais Yousef @ 2023-07-24 15:53 UTC (permalink / raw)
  To: Xuewen Yan
  Cc: Xuewen Yan, rafael, viresh.kumar, mingo, peterz, vincent.guittot,
	dietmar.eggemann, rostedt, bsegall, mgorman, bristot, vschneid,
	guohua.yan, linux-pm, linux-kernel

On 07/24/23 11:36, Xuewen Yan wrote:
> On Sat, Jul 22, 2023 at 7:02 AM Qais Yousef <qyousef@layalina.io> wrote:
> >
> > On 07/19/23 21:05, Xuewen Yan wrote:
> > > When cpufreq's policy is single, there is a scenario that will
> > > cause sg_policy's next_freq to be unable to update.
> > >
> > > When the cpu's util is always max, the cpufreq will be max,
> > > and then if we change the policy's scaling_max_freq to be a
> > > lower freq, indeed, the sg_policy's next_freq need change to
> > > be the lower freq, however, because the cpu_is_busy, the next_freq
> > > would keep the max_freq.
> > >
> > > For example:
> > > The cpu7 is single cpu:
> > >
> > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # while true;do done&
> > > [1] 4737
> > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # taskset -p 80 4737
> > > pid 4737's current affinity mask: ff
> > > pid 4737's new affinity mask: 80
> > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > > 2301000
> > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_cur_freq
> > > 2301000
> > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # echo 2171000 > scaling_max_freq
> > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > > 2171000
> > >
> > > At this time, the sg_policy's next_freq would keep 2301000.
> > >
> > > To prevent the case happen, add the judgment of the need_freq_update flag.
> > >
> > > Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com>
> > > Co-developed-by: Guohua Yan <guohua.yan@unisoc.com>
> > > Signed-off-by: Guohua Yan <guohua.yan@unisoc.com>
> > > ---
> > >  kernel/sched/cpufreq_schedutil.c | 3 ++-
> > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> > > index 4492608b7d7f..458d359f5991 100644
> > > --- a/kernel/sched/cpufreq_schedutil.c
> > > +++ b/kernel/sched/cpufreq_schedutil.c
> > > @@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
> > >        * Except when the rq is capped by uclamp_max.
> > >        */
> > >       if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) &&
> > > -         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
> > > +         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq &&
> > > +         !sg_policy->need_freq_update) {
> >
> > What about sugov_update_single_perf()? It seems to have the same problem, no?
> 
> There is no problem in sugov_update_single_perf, because the next_freq
> is updated by drivers, maybe the next_freq is not used when using
> sugov_update_single_perf..

Ah I see; we just use prev_util but the request will go through and the driver
should observe the new limit regardless of what util value we pass to it. Got
ya.

> 
> But  for the last_freq_update_time, I think there are some problems
> when using sugov_update_single_perf:
> Now, there is no judgment condition for the update of the
> last_freq_update_time. That means the last_freq_update_time is always
> updated in sugov_update_single_perf.
> And in sugov_should_update_freq: it would judge the
> freq_update_delay_ns. As a result, If we use the
> sugov_update_single_perf, the cpu frequency would only be periodically
> updated according to freq_update_delay_ns.
> Maybe we should judge the cpufreq_driver_adjust_perf's return value,
> if the freq is not updated, the last_freq_update_time also does not
> have to update.
> 
> Just like:
> ---
> diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> index 458d359f5991..10f18b054f01 100644
> --- a/kernel/sched/cpufreq_schedutil.c
> +++ b/kernel/sched/cpufreq_schedutil.c
> @@ -381,6 +381,7 @@ static void sugov_update_single_perf(struct
> update_util_data *hook, u64 time,
>         struct sugov_cpu *sg_cpu = container_of(hook, struct
> sugov_cpu, update_util);
>         unsigned long prev_util = sg_cpu->util;
>         unsigned long max_cap;
> +       bool freq_updated;
> 
>         /*
>          * Fall back to the "frequency" path if frequency invariance is not
> @@ -407,10 +408,11 @@ static void sugov_update_single_perf(struct
> update_util_data *hook, u64 time,
>             sugov_cpu_is_busy(sg_cpu) && sg_cpu->util < prev_util)
>                 sg_cpu->util = prev_util;
> 
> -       cpufreq_driver_adjust_perf(sg_cpu->cpu, map_util_perf(sg_cpu->bw_dl),
> +       freq_updated = cpufreq_driver_adjust_perf(sg_cpu->cpu,
> map_util_perf(sg_cpu->bw_dl),
>                                    map_util_perf(sg_cpu->util), max_cap);
> 
> -       sg_cpu->sg_policy->last_freq_update_time = time;
> +       if (freq_updated)
> +               sg_cpu->sg_policy->last_freq_update_time = time;
>  }

Sound reasonable in principle, but it could lead to overhead; for example when
the system is busy and maxed out, the last_freq_update_time will never be
updated and will end up continuously calling to the driver to change frequency
without any rate limit AFAICS. Which might not be an acceptable overhead,
I don't know. Logically this is wasted cycles preventing the tasks from doing
useful work. I think we need to look at such corner cases and treat them
appropriately to not call the driver if we go with this approach.


Cheers

--
Qais Yousef

> 
> 
> BR
> Thanks!
> 
> ---
> xuewen
> >
> > LGTM otherwise.
> >
> >
> > Cheers
> >
> > --
> > Qais Yousef
> >
> > >               next_f = sg_policy->next_freq;
> > >
> > >               /* Restore cached freq as next_freq has changed */
> > > --
> > > 2.25.1
> > >

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed
  2023-07-24 15:33     ` Pierre Gondois
@ 2023-07-25  2:01       ` Xuewen Yan
  0 siblings, 0 replies; 14+ messages in thread
From: Xuewen Yan @ 2023-07-25  2:01 UTC (permalink / raw)
  To: Pierre Gondois
  Cc: Qais Yousef, Xuewen Yan, rafael, viresh.kumar, mingo, peterz,
	vincent.guittot, dietmar.eggemann, rostedt, bsegall, mgorman,
	bristot, vschneid, guohua.yan, linux-pm, linux-kernel

Hi Pierre,

On Mon, Jul 24, 2023 at 11:33 PM Pierre Gondois <pierre.gondois@arm.com> wrote:
>
>
>
> On 7/24/23 05:36, Xuewen Yan wrote:
> > On Sat, Jul 22, 2023 at 7:02 AM Qais Yousef <qyousef@layalina.io> wrote:
> >>
> >> On 07/19/23 21:05, Xuewen Yan wrote:
> >>> When cpufreq's policy is single, there is a scenario that will
> >>> cause sg_policy's next_freq to be unable to update.
> >>>
> >>> When the cpu's util is always max, the cpufreq will be max,
> >>> and then if we change the policy's scaling_max_freq to be a
> >>> lower freq, indeed, the sg_policy's next_freq need change to
> >>> be the lower freq, however, because the cpu_is_busy, the next_freq
> >>> would keep the max_freq.
> >>>
> >>> For example:
> >>> The cpu7 is single cpu:
> >>>
> >>> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # while true;do done&
> >>> [1] 4737
> >>> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # taskset -p 80 4737
> >>> pid 4737's current affinity mask: ff
> >>> pid 4737's new affinity mask: 80
> >>> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> >>> 2301000
> >>> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_cur_freq
> >>> 2301000
> >>> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # echo 2171000 > scaling_max_freq
> >>> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> >>> 2171000
> >>>
> >>> At this time, the sg_policy's next_freq would keep 2301000.
> >>>
> >>> To prevent the case happen, add the judgment of the need_freq_update flag.
> >>>
> >>> Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com>
> >>> Co-developed-by: Guohua Yan <guohua.yan@unisoc.com>
> >>> Signed-off-by: Guohua Yan <guohua.yan@unisoc.com>
> >>> ---
> >>>   kernel/sched/cpufreq_schedutil.c | 3 ++-
> >>>   1 file changed, 2 insertions(+), 1 deletion(-)
> >>>
> >>> diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> >>> index 4492608b7d7f..458d359f5991 100644
> >>> --- a/kernel/sched/cpufreq_schedutil.c
> >>> +++ b/kernel/sched/cpufreq_schedutil.c
> >>> @@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
> >>>         * Except when the rq is capped by uclamp_max.
> >>>         */
> >>>        if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) &&
> >>> -         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
> >>> +         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq &&
> >>> +         !sg_policy->need_freq_update) {
> >>
> >> What about sugov_update_single_perf()? It seems to have the same problem, no?
> >
> > There is no problem in sugov_update_single_perf, because the next_freq
> > is updated by drivers, maybe the next_freq is not used when using
> > sugov_update_single_perf..
> >
> > But  for the last_freq_update_time, I think there are some problems
> > when using sugov_update_single_perf:
> > Now, there is no judgment condition for the update of the
> > last_freq_update_time. That means the last_freq_update_time is always
> > updated in sugov_update_single_perf.
> > And in sugov_should_update_freq: it would judge the
> > freq_update_delay_ns. As a result, If we use the
> > sugov_update_single_perf, the cpu frequency would only be periodically
> > updated according to freq_update_delay_ns.
> > Maybe we should judge the cpufreq_driver_adjust_perf's return value,
> > if the freq is not updated, the last_freq_update_time also does not
> > have to update.
> >
> > Just like:
> > ---
> > diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> > index 458d359f5991..10f18b054f01 100644
> > --- a/kernel/sched/cpufreq_schedutil.c
> > +++ b/kernel/sched/cpufreq_schedutil.c
> > @@ -381,6 +381,7 @@ static void sugov_update_single_perf(struct
> > update_util_data *hook, u64 time,
> >          struct sugov_cpu *sg_cpu = container_of(hook, struct
> > sugov_cpu, update_util);
> >          unsigned long prev_util = sg_cpu->util;
> >          unsigned long max_cap;
> > +       bool freq_updated;
> >
> >          /*
> >           * Fall back to the "frequency" path if frequency invariance is not
> > @@ -407,10 +408,11 @@ static void sugov_update_single_perf(struct
> > update_util_data *hook, u64 time,
> >              sugov_cpu_is_busy(sg_cpu) && sg_cpu->util < prev_util)
> >                  sg_cpu->util = prev_util;
> >
> > -       cpufreq_driver_adjust_perf(sg_cpu->cpu, map_util_perf(sg_cpu->bw_dl),
> > +       freq_updated = cpufreq_driver_adjust_perf(sg_cpu->cpu,
> > map_util_perf(sg_cpu->bw_dl),
> >                                     map_util_perf(sg_cpu->util), max_cap);
> >
> > -       sg_cpu->sg_policy->last_freq_update_time = time;
> > +       if (freq_updated)
> > +               sg_cpu->sg_policy->last_freq_update_time = time;
> >   }
> >
>
> Hello Xuewen,
> FWIW, the patch and explanation for sugov_update_single_perf() seem sensible to
> me. Just a comment about cpufreq_driver_adjust_perf() and
> (struct cpufreq_driver)->adjust_perf(): wouldn't their prototype need to be
> updated (i.e. not return void) to do the change suggested above ?

Yes, their function type should be changed from void to bool or init.
For this patch, I just raise a question for everyone to discuss. If
this is a problem, the official patch needs to be revised later.

BR
xuewen

>
> Regards,
> Pierre
>
> >
> > BR
> > Thanks!
> >
> > ---
> > xuewen
> >>
> >> LGTM otherwise.
> >>
> >>
> >> Cheers
> >>
> >> --
> >> Qais Yousef
> >>
> >>>                next_f = sg_policy->next_freq;
> >>>
> >>>                /* Restore cached freq as next_freq has changed */
> >>> --
> >>> 2.25.1
> >>>
> >

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed
  2023-07-24 15:53     ` Qais Yousef
@ 2023-07-25  2:21       ` Xuewen Yan
  2023-07-25  8:50         ` Rafael J. Wysocki
  0 siblings, 1 reply; 14+ messages in thread
From: Xuewen Yan @ 2023-07-25  2:21 UTC (permalink / raw)
  To: Qais Yousef
  Cc: Xuewen Yan, rafael, viresh.kumar, mingo, peterz, vincent.guittot,
	dietmar.eggemann, rostedt, bsegall, mgorman, bristot, vschneid,
	guohua.yan, linux-pm, linux-kernel

On Mon, Jul 24, 2023 at 11:53 PM Qais Yousef <qyousef@layalina.io> wrote:
>
> On 07/24/23 11:36, Xuewen Yan wrote:
> > On Sat, Jul 22, 2023 at 7:02 AM Qais Yousef <qyousef@layalina.io> wrote:
> > >
> > > On 07/19/23 21:05, Xuewen Yan wrote:
> > > > When cpufreq's policy is single, there is a scenario that will
> > > > cause sg_policy's next_freq to be unable to update.
> > > >
> > > > When the cpu's util is always max, the cpufreq will be max,
> > > > and then if we change the policy's scaling_max_freq to be a
> > > > lower freq, indeed, the sg_policy's next_freq need change to
> > > > be the lower freq, however, because the cpu_is_busy, the next_freq
> > > > would keep the max_freq.
> > > >
> > > > For example:
> > > > The cpu7 is single cpu:
> > > >
> > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # while true;do done&
> > > > [1] 4737
> > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # taskset -p 80 4737
> > > > pid 4737's current affinity mask: ff
> > > > pid 4737's new affinity mask: 80
> > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > > > 2301000
> > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_cur_freq
> > > > 2301000
> > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # echo 2171000 > scaling_max_freq
> > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > > > 2171000
> > > >
> > > > At this time, the sg_policy's next_freq would keep 2301000.
> > > >
> > > > To prevent the case happen, add the judgment of the need_freq_update flag.
> > > >
> > > > Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com>
> > > > Co-developed-by: Guohua Yan <guohua.yan@unisoc.com>
> > > > Signed-off-by: Guohua Yan <guohua.yan@unisoc.com>
> > > > ---
> > > >  kernel/sched/cpufreq_schedutil.c | 3 ++-
> > > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > > >
> > > > diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> > > > index 4492608b7d7f..458d359f5991 100644
> > > > --- a/kernel/sched/cpufreq_schedutil.c
> > > > +++ b/kernel/sched/cpufreq_schedutil.c
> > > > @@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
> > > >        * Except when the rq is capped by uclamp_max.
> > > >        */
> > > >       if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) &&
> > > > -         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
> > > > +         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq &&
> > > > +         !sg_policy->need_freq_update) {
> > >
> > > What about sugov_update_single_perf()? It seems to have the same problem, no?
> >
> > There is no problem in sugov_update_single_perf, because the next_freq
> > is updated by drivers, maybe the next_freq is not used when using
> > sugov_update_single_perf..
>
> Ah I see; we just use prev_util but the request will go through and the driver
> should observe the new limit regardless of what util value we pass to it. Got
> ya.
>
> >
> > But  for the last_freq_update_time, I think there are some problems
> > when using sugov_update_single_perf:
> > Now, there is no judgment condition for the update of the
> > last_freq_update_time. That means the last_freq_update_time is always
> > updated in sugov_update_single_perf.
> > And in sugov_should_update_freq: it would judge the
> > freq_update_delay_ns. As a result, If we use the
> > sugov_update_single_perf, the cpu frequency would only be periodically
> > updated according to freq_update_delay_ns.
> > Maybe we should judge the cpufreq_driver_adjust_perf's return value,
> > if the freq is not updated, the last_freq_update_time also does not
> > have to update.
> >
> > Just like:
> > ---
> > diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> > index 458d359f5991..10f18b054f01 100644
> > --- a/kernel/sched/cpufreq_schedutil.c
> > +++ b/kernel/sched/cpufreq_schedutil.c
> > @@ -381,6 +381,7 @@ static void sugov_update_single_perf(struct
> > update_util_data *hook, u64 time,
> >         struct sugov_cpu *sg_cpu = container_of(hook, struct
> > sugov_cpu, update_util);
> >         unsigned long prev_util = sg_cpu->util;
> >         unsigned long max_cap;
> > +       bool freq_updated;
> >
> >         /*
> >          * Fall back to the "frequency" path if frequency invariance is not
> > @@ -407,10 +408,11 @@ static void sugov_update_single_perf(struct
> > update_util_data *hook, u64 time,
> >             sugov_cpu_is_busy(sg_cpu) && sg_cpu->util < prev_util)
> >                 sg_cpu->util = prev_util;
> >
> > -       cpufreq_driver_adjust_perf(sg_cpu->cpu, map_util_perf(sg_cpu->bw_dl),
> > +       freq_updated = cpufreq_driver_adjust_perf(sg_cpu->cpu,
> > map_util_perf(sg_cpu->bw_dl),
> >                                    map_util_perf(sg_cpu->util), max_cap);
> >
> > -       sg_cpu->sg_policy->last_freq_update_time = time;
> > +       if (freq_updated)
> > +               sg_cpu->sg_policy->last_freq_update_time = time;
> >  }
>
> Sound reasonable in principle, but it could lead to overhead; for example when
> the system is busy and maxed out, the last_freq_update_time will never be
> updated and will end up continuously calling to the driver to change frequency
> without any rate limit AFAICS. Which might not be an acceptable overhead,
> I don't know. Logically this is wasted cycles preventing the tasks from doing
> useful work. I think we need to look at such corner cases and treat them
> appropriately to not call the driver if we go with this approach.

Hi Qais,

I can understand what you mean, but I don't think this is a problem.
For the driver, the calculation of whether to update the frequency may
not be the main time-consuming, but the main time-consuming may be the
frequency conversion time of the hardware. If the hardware does not
need frequency conversion, the operation of calculating the frequency
takes a very short time.
If the operation of calling the driver frequently is unacceptable, can
prev_util be used?

---
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 4492608b7d7f..3febfd032eee 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -379,7 +379,9 @@ static void sugov_update_single_perf(struct
update_util_data *hook, u64 time,
 {
        struct sugov_cpu *sg_cpu = container_of(hook, struct
sugov_cpu, update_util);
        unsigned long prev_util = sg_cpu->util;
+       unsigned long prev_bw_dl = sg_cpu->bw_dl;
        unsigned long max_cap;
+       bool freq_updated;

        /*
         * Fall back to the "frequency" path if frequency invariance is not
@@ -406,10 +408,14 @@ static void sugov_update_single_perf(struct
update_util_data *hook, u64 time,
            sugov_cpu_is_busy(sg_cpu) && sg_cpu->util < prev_util)
                sg_cpu->util = prev_util;

-       cpufreq_driver_adjust_perf(sg_cpu->cpu, map_util_perf(sg_cpu->bw_dl),
+       if (prev_util == sg_cpu->util && prev_bw_dl == sg_cpu->bw_dl)
+               return;
+
+       freq_updated = cpufreq_driver_adjust_perf(sg_cpu->cpu,
map_util_perf(sg_cpu->bw_dl),
                                   map_util_perf(sg_cpu->util), max_cap);

-       sg_cpu->sg_policy->last_freq_update_time = time;
+       if (freq_updated)
+               sg_cpu->sg_policy->last_freq_update_time = time;
 }

 static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu, u64 time)


BR
---
xuewen
>
>
> Cheers
>
> --
> Qais Yousef
>
> >
> >
> > BR
> > Thanks!
> >
> > ---
> > xuewen
> > >
> > > LGTM otherwise.
> > >
> > >
> > > Cheers
> > >
> > > --
> > > Qais Yousef
> > >
> > > >               next_f = sg_policy->next_freq;
> > > >
> > > >               /* Restore cached freq as next_freq has changed */
> > > > --
> > > > 2.25.1
> > > >

^ permalink raw reply related	[flat|nested] 14+ messages in thread

* Re: [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed
  2023-07-25  2:21       ` Xuewen Yan
@ 2023-07-25  8:50         ` Rafael J. Wysocki
  2023-07-25 12:08           ` Xuewen Yan
  0 siblings, 1 reply; 14+ messages in thread
From: Rafael J. Wysocki @ 2023-07-25  8:50 UTC (permalink / raw)
  To: Xuewen Yan
  Cc: Qais Yousef, Xuewen Yan, rafael, viresh.kumar, mingo, peterz,
	vincent.guittot, dietmar.eggemann, rostedt, bsegall, mgorman,
	bristot, vschneid, guohua.yan, linux-pm, linux-kernel

On Tue, Jul 25, 2023 at 4:21 AM Xuewen Yan <xuewen.yan94@gmail.com> wrote:
>
> On Mon, Jul 24, 2023 at 11:53 PM Qais Yousef <qyousef@layalina.io> wrote:
> >
> > On 07/24/23 11:36, Xuewen Yan wrote:
> > > On Sat, Jul 22, 2023 at 7:02 AM Qais Yousef <qyousef@layalina.io> wrote:
> > > >
> > > > On 07/19/23 21:05, Xuewen Yan wrote:
> > > > > When cpufreq's policy is single, there is a scenario that will
> > > > > cause sg_policy's next_freq to be unable to update.
> > > > >
> > > > > When the cpu's util is always max, the cpufreq will be max,
> > > > > and then if we change the policy's scaling_max_freq to be a
> > > > > lower freq, indeed, the sg_policy's next_freq need change to
> > > > > be the lower freq, however, because the cpu_is_busy, the next_freq
> > > > > would keep the max_freq.
> > > > >
> > > > > For example:
> > > > > The cpu7 is single cpu:
> > > > >
> > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # while true;do done&
> > > > > [1] 4737
> > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # taskset -p 80 4737
> > > > > pid 4737's current affinity mask: ff
> > > > > pid 4737's new affinity mask: 80
> > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > > > > 2301000
> > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_cur_freq
> > > > > 2301000
> > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # echo 2171000 > scaling_max_freq
> > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > > > > 2171000
> > > > >
> > > > > At this time, the sg_policy's next_freq would keep 2301000.
> > > > >
> > > > > To prevent the case happen, add the judgment of the need_freq_update flag.
> > > > >
> > > > > Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com>
> > > > > Co-developed-by: Guohua Yan <guohua.yan@unisoc.com>
> > > > > Signed-off-by: Guohua Yan <guohua.yan@unisoc.com>
> > > > > ---
> > > > >  kernel/sched/cpufreq_schedutil.c | 3 ++-
> > > > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > > > >
> > > > > diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> > > > > index 4492608b7d7f..458d359f5991 100644
> > > > > --- a/kernel/sched/cpufreq_schedutil.c
> > > > > +++ b/kernel/sched/cpufreq_schedutil.c
> > > > > @@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
> > > > >        * Except when the rq is capped by uclamp_max.
> > > > >        */
> > > > >       if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) &&
> > > > > -         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
> > > > > +         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq &&
> > > > > +         !sg_policy->need_freq_update) {
> > > >
> > > > What about sugov_update_single_perf()? It seems to have the same problem, no?
> > >
> > > There is no problem in sugov_update_single_perf, because the next_freq
> > > is updated by drivers, maybe the next_freq is not used when using
> > > sugov_update_single_perf..
> >
> > Ah I see; we just use prev_util but the request will go through and the driver
> > should observe the new limit regardless of what util value we pass to it. Got
> > ya.
> >
> > >
> > > But  for the last_freq_update_time, I think there are some problems
> > > when using sugov_update_single_perf:
> > > Now, there is no judgment condition for the update of the
> > > last_freq_update_time. That means the last_freq_update_time is always
> > > updated in sugov_update_single_perf.
> > > And in sugov_should_update_freq: it would judge the
> > > freq_update_delay_ns. As a result, If we use the
> > > sugov_update_single_perf, the cpu frequency would only be periodically
> > > updated according to freq_update_delay_ns.
> > > Maybe we should judge the cpufreq_driver_adjust_perf's return value,
> > > if the freq is not updated, the last_freq_update_time also does not
> > > have to update.
> > >
> > > Just like:
> > > ---
> > > diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> > > index 458d359f5991..10f18b054f01 100644
> > > --- a/kernel/sched/cpufreq_schedutil.c
> > > +++ b/kernel/sched/cpufreq_schedutil.c
> > > @@ -381,6 +381,7 @@ static void sugov_update_single_perf(struct
> > > update_util_data *hook, u64 time,
> > >         struct sugov_cpu *sg_cpu = container_of(hook, struct
> > > sugov_cpu, update_util);
> > >         unsigned long prev_util = sg_cpu->util;
> > >         unsigned long max_cap;
> > > +       bool freq_updated;
> > >
> > >         /*
> > >          * Fall back to the "frequency" path if frequency invariance is not
> > > @@ -407,10 +408,11 @@ static void sugov_update_single_perf(struct
> > > update_util_data *hook, u64 time,
> > >             sugov_cpu_is_busy(sg_cpu) && sg_cpu->util < prev_util)
> > >                 sg_cpu->util = prev_util;
> > >
> > > -       cpufreq_driver_adjust_perf(sg_cpu->cpu, map_util_perf(sg_cpu->bw_dl),
> > > +       freq_updated = cpufreq_driver_adjust_perf(sg_cpu->cpu,
> > > map_util_perf(sg_cpu->bw_dl),
> > >                                    map_util_perf(sg_cpu->util), max_cap);
> > >
> > > -       sg_cpu->sg_policy->last_freq_update_time = time;
> > > +       if (freq_updated)
> > > +               sg_cpu->sg_policy->last_freq_update_time = time;
> > >  }
> >
> > Sound reasonable in principle, but it could lead to overhead; for example when
> > the system is busy and maxed out, the last_freq_update_time will never be
> > updated and will end up continuously calling to the driver to change frequency
> > without any rate limit AFAICS. Which might not be an acceptable overhead,
> > I don't know. Logically this is wasted cycles preventing the tasks from doing
> > useful work. I think we need to look at such corner cases and treat them
> > appropriately to not call the driver if we go with this approach.
>
> Hi Qais,
>
> I can understand what you mean, but I don't think this is a problem.
> For the driver, the calculation of whether to update the frequency may
> not be the main time-consuming, but the main time-consuming may be the
> frequency conversion time of the hardware. If the hardware does not
> need frequency conversion, the operation of calculating the frequency
> takes a very short time.
> If the operation of calling the driver frequently is unacceptable, can
> prev_util be used?

No, it's better to pass the data to the driver directly and let it
sort that out in this particular case.

> ---
> diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> index 4492608b7d7f..3febfd032eee 100644
> --- a/kernel/sched/cpufreq_schedutil.c
> +++ b/kernel/sched/cpufreq_schedutil.c
> @@ -379,7 +379,9 @@ static void sugov_update_single_perf(struct
> update_util_data *hook, u64 time,
>  {
>         struct sugov_cpu *sg_cpu = container_of(hook, struct
> sugov_cpu, update_util);
>         unsigned long prev_util = sg_cpu->util;
> +       unsigned long prev_bw_dl = sg_cpu->bw_dl;
>         unsigned long max_cap;
> +       bool freq_updated;
>
>         /*
>          * Fall back to the "frequency" path if frequency invariance is not
> @@ -406,10 +408,14 @@ static void sugov_update_single_perf(struct
> update_util_data *hook, u64 time,
>             sugov_cpu_is_busy(sg_cpu) && sg_cpu->util < prev_util)
>                 sg_cpu->util = prev_util;
>
> -       cpufreq_driver_adjust_perf(sg_cpu->cpu, map_util_perf(sg_cpu->bw_dl),
> +       if (prev_util == sg_cpu->util && prev_bw_dl == sg_cpu->bw_dl)
> +               return;
> +
> +       freq_updated = cpufreq_driver_adjust_perf(sg_cpu->cpu,
> map_util_perf(sg_cpu->bw_dl),
>                                    map_util_perf(sg_cpu->util), max_cap);
>
> -       sg_cpu->sg_policy->last_freq_update_time = time;
> +       if (freq_updated)
> +               sg_cpu->sg_policy->last_freq_update_time = time;
>  }
>
>  static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu, u64 time)
>
>
> BR
> ---
> xuewen
> >
> >
> > Cheers
> >
> > --
> > Qais Yousef
> >
> > >
> > >
> > > BR
> > > Thanks!
> > >
> > > ---
> > > xuewen
> > > >
> > > > LGTM otherwise.
> > > >
> > > >
> > > > Cheers
> > > >
> > > > --
> > > > Qais Yousef
> > > >
> > > > >               next_f = sg_policy->next_freq;
> > > > >
> > > > >               /* Restore cached freq as next_freq has changed */
> > > > > --
> > > > > 2.25.1
> > > > >

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed
  2023-07-25  8:50         ` Rafael J. Wysocki
@ 2023-07-25 12:08           ` Xuewen Yan
  2023-08-22 19:28             ` Rafael J. Wysocki
  0 siblings, 1 reply; 14+ messages in thread
From: Xuewen Yan @ 2023-07-25 12:08 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Qais Yousef, Xuewen Yan, viresh.kumar, mingo, peterz,
	vincent.guittot, dietmar.eggemann, rostedt, bsegall, mgorman,
	bristot, vschneid, guohua.yan, linux-pm, linux-kernel

Hi Rafael

On Tue, Jul 25, 2023 at 4:51 PM Rafael J. Wysocki <rafael@kernel.org> wrote:
>
> On Tue, Jul 25, 2023 at 4:21 AM Xuewen Yan <xuewen.yan94@gmail.com> wrote:
> >
> > On Mon, Jul 24, 2023 at 11:53 PM Qais Yousef <qyousef@layalina.io> wrote:
> > >
> > > On 07/24/23 11:36, Xuewen Yan wrote:
> > > > On Sat, Jul 22, 2023 at 7:02 AM Qais Yousef <qyousef@layalina.io> wrote:
> > > > >
> > > > > On 07/19/23 21:05, Xuewen Yan wrote:
> > > > > > When cpufreq's policy is single, there is a scenario that will
> > > > > > cause sg_policy's next_freq to be unable to update.
> > > > > >
> > > > > > When the cpu's util is always max, the cpufreq will be max,
> > > > > > and then if we change the policy's scaling_max_freq to be a
> > > > > > lower freq, indeed, the sg_policy's next_freq need change to
> > > > > > be the lower freq, however, because the cpu_is_busy, the next_freq
> > > > > > would keep the max_freq.
> > > > > >
> > > > > > For example:
> > > > > > The cpu7 is single cpu:
> > > > > >
> > > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # while true;do done&
> > > > > > [1] 4737
> > > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # taskset -p 80 4737
> > > > > > pid 4737's current affinity mask: ff
> > > > > > pid 4737's new affinity mask: 80
> > > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > > > > > 2301000
> > > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_cur_freq
> > > > > > 2301000
> > > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # echo 2171000 > scaling_max_freq
> > > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > > > > > 2171000
> > > > > >
> > > > > > At this time, the sg_policy's next_freq would keep 2301000.
> > > > > >
> > > > > > To prevent the case happen, add the judgment of the need_freq_update flag.
> > > > > >
> > > > > > Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com>
> > > > > > Co-developed-by: Guohua Yan <guohua.yan@unisoc.com>
> > > > > > Signed-off-by: Guohua Yan <guohua.yan@unisoc.com>
> > > > > > ---
> > > > > >  kernel/sched/cpufreq_schedutil.c | 3 ++-
> > > > > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > > > > >
> > > > > > diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> > > > > > index 4492608b7d7f..458d359f5991 100644
> > > > > > --- a/kernel/sched/cpufreq_schedutil.c
> > > > > > +++ b/kernel/sched/cpufreq_schedutil.c
> > > > > > @@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
> > > > > >        * Except when the rq is capped by uclamp_max.
> > > > > >        */
> > > > > >       if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) &&
> > > > > > -         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
> > > > > > +         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq &&
> > > > > > +         !sg_policy->need_freq_update) {
> > > > >
> > > > > What about sugov_update_single_perf()? It seems to have the same problem, no?
> > > >
> > > > There is no problem in sugov_update_single_perf, because the next_freq
> > > > is updated by drivers, maybe the next_freq is not used when using
> > > > sugov_update_single_perf..
> > >
> > > Ah I see; we just use prev_util but the request will go through and the driver
> > > should observe the new limit regardless of what util value we pass to it. Got
> > > ya.
> > >
> > > >
> > > > But  for the last_freq_update_time, I think there are some problems
> > > > when using sugov_update_single_perf:
> > > > Now, there is no judgment condition for the update of the
> > > > last_freq_update_time. That means the last_freq_update_time is always
> > > > updated in sugov_update_single_perf.
> > > > And in sugov_should_update_freq: it would judge the
> > > > freq_update_delay_ns. As a result, If we use the
> > > > sugov_update_single_perf, the cpu frequency would only be periodically
> > > > updated according to freq_update_delay_ns.
> > > > Maybe we should judge the cpufreq_driver_adjust_perf's return value,
> > > > if the freq is not updated, the last_freq_update_time also does not
> > > > have to update.
> > > >
> > > > Just like:
> > > > ---
> > > > diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> > > > index 458d359f5991..10f18b054f01 100644
> > > > --- a/kernel/sched/cpufreq_schedutil.c
> > > > +++ b/kernel/sched/cpufreq_schedutil.c
> > > > @@ -381,6 +381,7 @@ static void sugov_update_single_perf(struct
> > > > update_util_data *hook, u64 time,
> > > >         struct sugov_cpu *sg_cpu = container_of(hook, struct
> > > > sugov_cpu, update_util);
> > > >         unsigned long prev_util = sg_cpu->util;
> > > >         unsigned long max_cap;
> > > > +       bool freq_updated;
> > > >
> > > >         /*
> > > >          * Fall back to the "frequency" path if frequency invariance is not
> > > > @@ -407,10 +408,11 @@ static void sugov_update_single_perf(struct
> > > > update_util_data *hook, u64 time,
> > > >             sugov_cpu_is_busy(sg_cpu) && sg_cpu->util < prev_util)
> > > >                 sg_cpu->util = prev_util;
> > > >
> > > > -       cpufreq_driver_adjust_perf(sg_cpu->cpu, map_util_perf(sg_cpu->bw_dl),
> > > > +       freq_updated = cpufreq_driver_adjust_perf(sg_cpu->cpu,
> > > > map_util_perf(sg_cpu->bw_dl),
> > > >                                    map_util_perf(sg_cpu->util), max_cap);
> > > >
> > > > -       sg_cpu->sg_policy->last_freq_update_time = time;
> > > > +       if (freq_updated)
> > > > +               sg_cpu->sg_policy->last_freq_update_time = time;
> > > >  }
> > >
> > > Sound reasonable in principle, but it could lead to overhead; for example when
> > > the system is busy and maxed out, the last_freq_update_time will never be
> > > updated and will end up continuously calling to the driver to change frequency
> > > without any rate limit AFAICS. Which might not be an acceptable overhead,
> > > I don't know. Logically this is wasted cycles preventing the tasks from doing
> > > useful work. I think we need to look at such corner cases and treat them
> > > appropriately to not call the driver if we go with this approach.
> >
> > Hi Qais,
> >
> > I can understand what you mean, but I don't think this is a problem.
> > For the driver, the calculation of whether to update the frequency may
> > not be the main time-consuming, but the main time-consuming may be the
> > frequency conversion time of the hardware. If the hardware does not
> > need frequency conversion, the operation of calculating the frequency
> > takes a very short time.
> > If the operation of calling the driver frequently is unacceptable, can
> > prev_util be used?
>
> No, it's better to pass the data to the driver directly and let it
> sort that out in this particular case.

Yes, I know. we should not interfere with the driver's behavior.

By the way, What do you think of the patch fixing the sugov_update_single_freq?

Thanks!

---
xuewen

>
> > ---
> > diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> > index 4492608b7d7f..3febfd032eee 100644
> > --- a/kernel/sched/cpufreq_schedutil.c
> > +++ b/kernel/sched/cpufreq_schedutil.c
> > @@ -379,7 +379,9 @@ static void sugov_update_single_perf(struct
> > update_util_data *hook, u64 time,
> >  {
> >         struct sugov_cpu *sg_cpu = container_of(hook, struct
> > sugov_cpu, update_util);
> >         unsigned long prev_util = sg_cpu->util;
> > +       unsigned long prev_bw_dl = sg_cpu->bw_dl;
> >         unsigned long max_cap;
> > +       bool freq_updated;
> >
> >         /*
> >          * Fall back to the "frequency" path if frequency invariance is not
> > @@ -406,10 +408,14 @@ static void sugov_update_single_perf(struct
> > update_util_data *hook, u64 time,
> >             sugov_cpu_is_busy(sg_cpu) && sg_cpu->util < prev_util)
> >                 sg_cpu->util = prev_util;
> >
> > -       cpufreq_driver_adjust_perf(sg_cpu->cpu, map_util_perf(sg_cpu->bw_dl),
> > +       if (prev_util == sg_cpu->util && prev_bw_dl == sg_cpu->bw_dl)
> > +               return;
> > +
> > +       freq_updated = cpufreq_driver_adjust_perf(sg_cpu->cpu,
> > map_util_perf(sg_cpu->bw_dl),
> >                                    map_util_perf(sg_cpu->util), max_cap);
> >
> > -       sg_cpu->sg_policy->last_freq_update_time = time;
> > +       if (freq_updated)
> > +               sg_cpu->sg_policy->last_freq_update_time = time;
> >  }
> >
> >  static unsigned int sugov_next_freq_shared(struct sugov_cpu *sg_cpu, u64 time)
> >
> >
> > BR
> > ---
> > xuewen
> > >
> > >
> > > Cheers
> > >
> > > --
> > > Qais Yousef
> > >
> > > >
> > > >
> > > > BR
> > > > Thanks!
> > > >
> > > > ---
> > > > xuewen
> > > > >
> > > > > LGTM otherwise.
> > > > >
> > > > >
> > > > > Cheers
> > > > >
> > > > > --
> > > > > Qais Yousef
> > > > >
> > > > > >               next_f = sg_policy->next_freq;
> > > > > >
> > > > > >               /* Restore cached freq as next_freq has changed */
> > > > > > --
> > > > > > 2.25.1
> > > > > >

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed
  2023-07-25 12:08           ` Xuewen Yan
@ 2023-08-22 19:28             ` Rafael J. Wysocki
  0 siblings, 0 replies; 14+ messages in thread
From: Rafael J. Wysocki @ 2023-08-22 19:28 UTC (permalink / raw)
  To: Xuewen Yan
  Cc: Rafael J. Wysocki, Qais Yousef, Xuewen Yan, viresh.kumar, mingo,
	peterz, vincent.guittot, dietmar.eggemann, rostedt, bsegall,
	mgorman, bristot, vschneid, guohua.yan, linux-pm, linux-kernel

On Tue, Jul 25, 2023 at 2:09 PM Xuewen Yan <xuewen.yan94@gmail.com> wrote:
>
> Hi Rafael
>
> On Tue, Jul 25, 2023 at 4:51 PM Rafael J. Wysocki <rafael@kernel.org> wrote:
> >
> > On Tue, Jul 25, 2023 at 4:21 AM Xuewen Yan <xuewen.yan94@gmail.com> wrote:
> > >
> > > On Mon, Jul 24, 2023 at 11:53 PM Qais Yousef <qyousef@layalina.io> wrote:
> > > >
> > > > On 07/24/23 11:36, Xuewen Yan wrote:
> > > > > On Sat, Jul 22, 2023 at 7:02 AM Qais Yousef <qyousef@layalina.io> wrote:
> > > > > >
> > > > > > On 07/19/23 21:05, Xuewen Yan wrote:
> > > > > > > When cpufreq's policy is single, there is a scenario that will
> > > > > > > cause sg_policy's next_freq to be unable to update.
> > > > > > >
> > > > > > > When the cpu's util is always max, the cpufreq will be max,
> > > > > > > and then if we change the policy's scaling_max_freq to be a
> > > > > > > lower freq, indeed, the sg_policy's next_freq need change to
> > > > > > > be the lower freq, however, because the cpu_is_busy, the next_freq
> > > > > > > would keep the max_freq.
> > > > > > >
> > > > > > > For example:
> > > > > > > The cpu7 is single cpu:
> > > > > > >
> > > > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # while true;do done&
> > > > > > > [1] 4737
> > > > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # taskset -p 80 4737
> > > > > > > pid 4737's current affinity mask: ff
> > > > > > > pid 4737's new affinity mask: 80
> > > > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > > > > > > 2301000
> > > > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_cur_freq
> > > > > > > 2301000
> > > > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # echo 2171000 > scaling_max_freq
> > > > > > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > > > > > > 2171000
> > > > > > >
> > > > > > > At this time, the sg_policy's next_freq would keep 2301000.
> > > > > > >
> > > > > > > To prevent the case happen, add the judgment of the need_freq_update flag.
> > > > > > >
> > > > > > > Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com>
> > > > > > > Co-developed-by: Guohua Yan <guohua.yan@unisoc.com>
> > > > > > > Signed-off-by: Guohua Yan <guohua.yan@unisoc.com>
> > > > > > > ---
> > > > > > >  kernel/sched/cpufreq_schedutil.c | 3 ++-
> > > > > > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > > > > > >
> > > > > > > diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> > > > > > > index 4492608b7d7f..458d359f5991 100644
> > > > > > > --- a/kernel/sched/cpufreq_schedutil.c
> > > > > > > +++ b/kernel/sched/cpufreq_schedutil.c
> > > > > > > @@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
> > > > > > >        * Except when the rq is capped by uclamp_max.
> > > > > > >        */
> > > > > > >       if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) &&
> > > > > > > -         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
> > > > > > > +         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq &&
> > > > > > > +         !sg_policy->need_freq_update) {
> > > > > >
> > > > > > What about sugov_update_single_perf()? It seems to have the same problem, no?
> > > > >
> > > > > There is no problem in sugov_update_single_perf, because the next_freq
> > > > > is updated by drivers, maybe the next_freq is not used when using
> > > > > sugov_update_single_perf..
> > > >
> > > > Ah I see; we just use prev_util but the request will go through and the driver
> > > > should observe the new limit regardless of what util value we pass to it. Got
> > > > ya.
> > > >
> > > > >
> > > > > But  for the last_freq_update_time, I think there are some problems
> > > > > when using sugov_update_single_perf:
> > > > > Now, there is no judgment condition for the update of the
> > > > > last_freq_update_time. That means the last_freq_update_time is always
> > > > > updated in sugov_update_single_perf.
> > > > > And in sugov_should_update_freq: it would judge the
> > > > > freq_update_delay_ns. As a result, If we use the
> > > > > sugov_update_single_perf, the cpu frequency would only be periodically
> > > > > updated according to freq_update_delay_ns.
> > > > > Maybe we should judge the cpufreq_driver_adjust_perf's return value,
> > > > > if the freq is not updated, the last_freq_update_time also does not
> > > > > have to update.
> > > > >
> > > > > Just like:
> > > > > ---
> > > > > diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> > > > > index 458d359f5991..10f18b054f01 100644
> > > > > --- a/kernel/sched/cpufreq_schedutil.c
> > > > > +++ b/kernel/sched/cpufreq_schedutil.c
> > > > > @@ -381,6 +381,7 @@ static void sugov_update_single_perf(struct
> > > > > update_util_data *hook, u64 time,
> > > > >         struct sugov_cpu *sg_cpu = container_of(hook, struct
> > > > > sugov_cpu, update_util);
> > > > >         unsigned long prev_util = sg_cpu->util;
> > > > >         unsigned long max_cap;
> > > > > +       bool freq_updated;
> > > > >
> > > > >         /*
> > > > >          * Fall back to the "frequency" path if frequency invariance is not
> > > > > @@ -407,10 +408,11 @@ static void sugov_update_single_perf(struct
> > > > > update_util_data *hook, u64 time,
> > > > >             sugov_cpu_is_busy(sg_cpu) && sg_cpu->util < prev_util)
> > > > >                 sg_cpu->util = prev_util;
> > > > >
> > > > > -       cpufreq_driver_adjust_perf(sg_cpu->cpu, map_util_perf(sg_cpu->bw_dl),
> > > > > +       freq_updated = cpufreq_driver_adjust_perf(sg_cpu->cpu,
> > > > > map_util_perf(sg_cpu->bw_dl),
> > > > >                                    map_util_perf(sg_cpu->util), max_cap);
> > > > >
> > > > > -       sg_cpu->sg_policy->last_freq_update_time = time;
> > > > > +       if (freq_updated)
> > > > > +               sg_cpu->sg_policy->last_freq_update_time = time;
> > > > >  }
> > > >
> > > > Sound reasonable in principle, but it could lead to overhead; for example when
> > > > the system is busy and maxed out, the last_freq_update_time will never be
> > > > updated and will end up continuously calling to the driver to change frequency
> > > > without any rate limit AFAICS. Which might not be an acceptable overhead,
> > > > I don't know. Logically this is wasted cycles preventing the tasks from doing
> > > > useful work. I think we need to look at such corner cases and treat them
> > > > appropriately to not call the driver if we go with this approach.
> > >
> > > Hi Qais,
> > >
> > > I can understand what you mean, but I don't think this is a problem.
> > > For the driver, the calculation of whether to update the frequency may
> > > not be the main time-consuming, but the main time-consuming may be the
> > > frequency conversion time of the hardware. If the hardware does not
> > > need frequency conversion, the operation of calculating the frequency
> > > takes a very short time.
> > > If the operation of calling the driver frequently is unacceptable, can
> > > prev_util be used?
> >
> > No, it's better to pass the data to the driver directly and let it
> > sort that out in this particular case.
>
> Yes, I know. we should not interfere with the driver's behavior.
>
> By the way, What do you think of the patch fixing the sugov_update_single_freq?

IIUC, you have found a genuine issue and the patch should address it.

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed
  2023-07-19 13:05 [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed Xuewen Yan
  2023-07-21 22:19 ` Qais Yousef
@ 2023-10-05 11:26 ` Ingo Molnar
  2023-10-05 11:35   ` Rafael J. Wysocki
  2023-10-05 20:23 ` [tip: sched/urgent] cpufreq: schedutil: Update next_freq when cpufreq_limits change tip-bot2 for Xuewen Yan
  2 siblings, 1 reply; 14+ messages in thread
From: Ingo Molnar @ 2023-10-05 11:26 UTC (permalink / raw)
  To: Xuewen Yan
  Cc: rafael, viresh.kumar, mingo, peterz, vincent.guittot,
	dietmar.eggemann, rostedt, bsegall, mgorman, bristot, vschneid,
	guohua.yan, qyousef, linux-pm, linux-kernel


* Xuewen Yan <xuewen.yan@unisoc.com> wrote:

> When cpufreq's policy is single, there is a scenario that will
> cause sg_policy's next_freq to be unable to update.
> 
> When the cpu's util is always max, the cpufreq will be max,
> and then if we change the policy's scaling_max_freq to be a
> lower freq, indeed, the sg_policy's next_freq need change to
> be the lower freq, however, because the cpu_is_busy, the next_freq
> would keep the max_freq.
> 
> For example:
> The cpu7 is single cpu:
> 
> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # while true;do done&
> [1] 4737
> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # taskset -p 80 4737
> pid 4737's current affinity mask: ff
> pid 4737's new affinity mask: 80
> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> 2301000
> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_cur_freq
> 2301000
> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # echo 2171000 > scaling_max_freq
> unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> 2171000
> 
> At this time, the sg_policy's next_freq would keep 2301000.
> 
> To prevent the case happen, add the judgment of the need_freq_update flag.
> 
> Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com>
> Co-developed-by: Guohua Yan <guohua.yan@unisoc.com>
> Signed-off-by: Guohua Yan <guohua.yan@unisoc.com>
> ---
>  kernel/sched/cpufreq_schedutil.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
> 
> diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> index 4492608b7d7f..458d359f5991 100644
> --- a/kernel/sched/cpufreq_schedutil.c
> +++ b/kernel/sched/cpufreq_schedutil.c
> @@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
>  	 * Except when the rq is capped by uclamp_max.
>  	 */
>  	if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) &&
> -	    sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
> +	    sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq &&
> +	    !sg_policy->need_freq_update) {
>  		next_f = sg_policy->next_freq;
>  
>  		/* Restore cached freq as next_freq has changed */

Just wondering about the status of this fix - is it pending in
some tree, or should we apply it to the scheduler tree?

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed
  2023-10-05 11:26 ` Ingo Molnar
@ 2023-10-05 11:35   ` Rafael J. Wysocki
  2023-10-05 20:09     ` Ingo Molnar
  0 siblings, 1 reply; 14+ messages in thread
From: Rafael J. Wysocki @ 2023-10-05 11:35 UTC (permalink / raw)
  To: Ingo Molnar
  Cc: Xuewen Yan, rafael, viresh.kumar, mingo, peterz, vincent.guittot,
	dietmar.eggemann, rostedt, bsegall, mgorman, bristot, vschneid,
	guohua.yan, qyousef, linux-pm, linux-kernel

On Thu, Oct 5, 2023 at 1:26 PM Ingo Molnar <mingo@kernel.org> wrote:
>
>
> * Xuewen Yan <xuewen.yan@unisoc.com> wrote:
>
> > When cpufreq's policy is single, there is a scenario that will
> > cause sg_policy's next_freq to be unable to update.
> >
> > When the cpu's util is always max, the cpufreq will be max,
> > and then if we change the policy's scaling_max_freq to be a
> > lower freq, indeed, the sg_policy's next_freq need change to
> > be the lower freq, however, because the cpu_is_busy, the next_freq
> > would keep the max_freq.
> >
> > For example:
> > The cpu7 is single cpu:
> >
> > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # while true;do done&
> > [1] 4737
> > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # taskset -p 80 4737
> > pid 4737's current affinity mask: ff
> > pid 4737's new affinity mask: 80
> > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > 2301000
> > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_cur_freq
> > 2301000
> > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # echo 2171000 > scaling_max_freq
> > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > 2171000
> >
> > At this time, the sg_policy's next_freq would keep 2301000.
> >
> > To prevent the case happen, add the judgment of the need_freq_update flag.
> >
> > Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com>
> > Co-developed-by: Guohua Yan <guohua.yan@unisoc.com>
> > Signed-off-by: Guohua Yan <guohua.yan@unisoc.com>
> > ---
> >  kernel/sched/cpufreq_schedutil.c | 3 ++-
> >  1 file changed, 2 insertions(+), 1 deletion(-)
> >
> > diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> > index 4492608b7d7f..458d359f5991 100644
> > --- a/kernel/sched/cpufreq_schedutil.c
> > +++ b/kernel/sched/cpufreq_schedutil.c
> > @@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
> >        * Except when the rq is capped by uclamp_max.
> >        */
> >       if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) &&
> > -         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
> > +         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq &&
> > +         !sg_policy->need_freq_update) {
> >               next_f = sg_policy->next_freq;
> >
> >               /* Restore cached freq as next_freq has changed */
>
> Just wondering about the status of this fix - is it pending in
> some tree, or should we apply it to the scheduler tree?

I have not queued it up yet, so it can be applied to the scheduler tree.

Thanks!

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed
  2023-10-05 11:35   ` Rafael J. Wysocki
@ 2023-10-05 20:09     ` Ingo Molnar
  0 siblings, 0 replies; 14+ messages in thread
From: Ingo Molnar @ 2023-10-05 20:09 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Xuewen Yan, viresh.kumar, mingo, peterz, vincent.guittot,
	dietmar.eggemann, rostedt, bsegall, mgorman, bristot, vschneid,
	guohua.yan, qyousef, linux-pm, linux-kernel


* Rafael J. Wysocki <rafael@kernel.org> wrote:

> On Thu, Oct 5, 2023 at 1:26 PM Ingo Molnar <mingo@kernel.org> wrote:
> >
> >
> > * Xuewen Yan <xuewen.yan@unisoc.com> wrote:
> >
> > > When cpufreq's policy is single, there is a scenario that will
> > > cause sg_policy's next_freq to be unable to update.
> > >
> > > When the cpu's util is always max, the cpufreq will be max,
> > > and then if we change the policy's scaling_max_freq to be a
> > > lower freq, indeed, the sg_policy's next_freq need change to
> > > be the lower freq, however, because the cpu_is_busy, the next_freq
> > > would keep the max_freq.
> > >
> > > For example:
> > > The cpu7 is single cpu:
> > >
> > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # while true;do done&
> > > [1] 4737
> > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # taskset -p 80 4737
> > > pid 4737's current affinity mask: ff
> > > pid 4737's new affinity mask: 80
> > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > > 2301000
> > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_cur_freq
> > > 2301000
> > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # echo 2171000 > scaling_max_freq
> > > unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
> > > 2171000
> > >
> > > At this time, the sg_policy's next_freq would keep 2301000.
> > >
> > > To prevent the case happen, add the judgment of the need_freq_update flag.
> > >
> > > Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com>
> > > Co-developed-by: Guohua Yan <guohua.yan@unisoc.com>
> > > Signed-off-by: Guohua Yan <guohua.yan@unisoc.com>
> > > ---
> > >  kernel/sched/cpufreq_schedutil.c | 3 ++-
> > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> > > index 4492608b7d7f..458d359f5991 100644
> > > --- a/kernel/sched/cpufreq_schedutil.c
> > > +++ b/kernel/sched/cpufreq_schedutil.c
> > > @@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
> > >        * Except when the rq is capped by uclamp_max.
> > >        */
> > >       if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) &&
> > > -         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
> > > +         sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq &&
> > > +         !sg_policy->need_freq_update) {
> > >               next_f = sg_policy->next_freq;
> > >
> > >               /* Restore cached freq as next_freq has changed */
> >
> > Just wondering about the status of this fix - is it pending in
> > some tree, or should we apply it to the scheduler tree?
> 
> I have not queued it up yet, so it can be applied to the scheduler tree.

Ok, I've applied it - and I've added your Acked-by.

Thanks,

	Ingo

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [tip: sched/urgent] cpufreq: schedutil: Update next_freq when cpufreq_limits change
  2023-07-19 13:05 [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed Xuewen Yan
  2023-07-21 22:19 ` Qais Yousef
  2023-10-05 11:26 ` Ingo Molnar
@ 2023-10-05 20:23 ` tip-bot2 for Xuewen Yan
  2 siblings, 0 replies; 14+ messages in thread
From: tip-bot2 for Xuewen Yan @ 2023-10-05 20:23 UTC (permalink / raw)
  To: linux-tip-commits
  Cc: Xuewen Yan, Guohua Yan, Ingo Molnar, Rafael J. Wysocki, x86,
	linux-kernel

The following commit has been merged into the sched/urgent branch of tip:

Commit-ID:     9e0bc36ab07c550d791bf17feeb479f1dfc42d89
Gitweb:        https://git.kernel.org/tip/9e0bc36ab07c550d791bf17feeb479f1dfc42d89
Author:        Xuewen Yan <xuewen.yan@unisoc.com>
AuthorDate:    Wed, 19 Jul 2023 21:05:27 +08:00
Committer:     Ingo Molnar <mingo@kernel.org>
CommitterDate: Thu, 05 Oct 2023 22:09:50 +02:00

cpufreq: schedutil: Update next_freq when cpufreq_limits change

When cpufreq's policy is 'single', there is a scenario that will
cause sg_policy's next_freq to be unable to update.

When the CPU's util is always max, the cpufreq will be max,
and then if we change the policy's scaling_max_freq to be a
lower freq, indeed, the sg_policy's next_freq need change to
be the lower freq, however, because the cpu_is_busy, the next_freq
would keep the max_freq.

For example:

The cpu7 is a single CPU:

  unisoc:/sys/devices/system/cpu/cpufreq/policy7 # while true;do done& [1] 4737
  unisoc:/sys/devices/system/cpu/cpufreq/policy7 # taskset -p 80 4737
  pid 4737's current affinity mask: ff
  pid 4737's new affinity mask: 80
  unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
  2301000
  unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_cur_freq
  2301000
  unisoc:/sys/devices/system/cpu/cpufreq/policy7 # echo 2171000 > scaling_max_freq
  unisoc:/sys/devices/system/cpu/cpufreq/policy7 # cat scaling_max_freq
  2171000

At this time, the sg_policy's next_freq would stay at 2301000, which
is wrong.

To fix this, add a check for the ->need_freq_update flag.

[ mingo: Clarified the changelog. ]

Co-developed-by: Guohua Yan <guohua.yan@unisoc.com>
Signed-off-by: Xuewen Yan <xuewen.yan@unisoc.com>
Signed-off-by: Guohua Yan <guohua.yan@unisoc.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Acked-by: "Rafael J. Wysocki" <rafael@kernel.org>
Link: https://lore.kernel.org/r/20230719130527.8074-1-xuewen.yan@unisoc.com
---
 kernel/sched/cpufreq_schedutil.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 4492608..458d359 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -350,7 +350,8 @@ static void sugov_update_single_freq(struct update_util_data *hook, u64 time,
 	 * Except when the rq is capped by uclamp_max.
 	 */
 	if (!uclamp_rq_is_capped(cpu_rq(sg_cpu->cpu)) &&
-	    sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq) {
+	    sugov_cpu_is_busy(sg_cpu) && next_f < sg_policy->next_freq &&
+	    !sg_policy->need_freq_update) {
 		next_f = sg_policy->next_freq;
 
 		/* Restore cached freq as next_freq has changed */

^ permalink raw reply related	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2023-10-05 20:23 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-07-19 13:05 [PATCH] cpufreq: schedutil: next_freq need update when cpufreq_limits changed Xuewen Yan
2023-07-21 22:19 ` Qais Yousef
2023-07-24  3:36   ` Xuewen Yan
2023-07-24 15:33     ` Pierre Gondois
2023-07-25  2:01       ` Xuewen Yan
2023-07-24 15:53     ` Qais Yousef
2023-07-25  2:21       ` Xuewen Yan
2023-07-25  8:50         ` Rafael J. Wysocki
2023-07-25 12:08           ` Xuewen Yan
2023-08-22 19:28             ` Rafael J. Wysocki
2023-10-05 11:26 ` Ingo Molnar
2023-10-05 11:35   ` Rafael J. Wysocki
2023-10-05 20:09     ` Ingo Molnar
2023-10-05 20:23 ` [tip: sched/urgent] cpufreq: schedutil: Update next_freq when cpufreq_limits change tip-bot2 for Xuewen Yan

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.