* Re: [PATCH v2] schedutil: Allow cpufreq requests to be made even when kthread kicked
From: Rafael J. Wysocki @ 2018-05-22 10:02 UTC (permalink / raw)
To: Joel Fernandes
Cc: Rafael J. Wysocki, Viresh Kumar, Joel Fernandes (Google.),
Linux Kernel Mailing List, Rafael J . Wysocki, Peter Zijlstra,
Ingo Molnar, Patrick Bellasi, Juri Lelli, Luca Abeni, Todd Kjos,
Claudio Scordino, kernel-team, Linux PM
In-Reply-To: <20180521161346.GB14065@joelaf.mtv.corp.google.com>
On Mon, May 21, 2018 at 6:13 PM, Joel Fernandes <joel@joelfernandes.org> wrote:
> On Mon, May 21, 2018 at 10:29:52AM +0200, Rafael J. Wysocki wrote:
>> On Mon, May 21, 2018 at 7:14 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
>> > On 18-05-18, 11:55, Joel Fernandes (Google.) wrote:
>> >> From: "Joel Fernandes (Google)" <joel@joelfernandes.org>
>> >>
>> >> Currently there is a chance of a schedutil cpufreq update request to be
>> >> dropped if there is a pending update request. This pending request can
>> >> be delayed if there is a scheduling delay of the irq_work and the wake
>> >> up of the schedutil governor kthread.
>> >>
>> >> A very bad scenario is when a schedutil request was already just made,
>> >> such as to reduce the CPU frequency, then a newer request to increase
>> >> CPU frequency (even sched deadline urgent frequency increase requests)
>> >> can be dropped, even though the rate limits suggest that its Ok to
>> >> process a request. This is because of the way the work_in_progress flag
>> >> is used.
>> >>
>> >> This patch improves the situation by allowing new requests to happen
>> >> even though the old one is still being processed. Note that in this
>> >> approach, if an irq_work was already issued, we just update next_freq
>> >> and don't bother to queue another request so there's no extra work being
>> >> done to make this happen.
>> >
>> > Now that this isn't an RFC anymore, you shouldn't have added below
>> > paragraph here. It could go to the comments section though.
>> >
>> >> I had brought up this issue at the OSPM conference and Claudio had a
>> >> discussion RFC with an alternate approach [1]. I prefer the approach as
>> >> done in the patch below since it doesn't need any new flags and doesn't
>> >> cause any other extra overhead.
>> >>
>> >> [1] https://patchwork.kernel.org/patch/10384261/
>> >>
>> >> LGTMed-by: Viresh Kumar <viresh.kumar@linaro.org>
>> >> LGTMed-by: Juri Lelli <juri.lelli@redhat.com>
>> >
>> > Looks like a Tag you just invented ? :)
>>
>> Yeah.
>>
>> The LGTM from Juri can be converned into an ACK silently IMO. That
>> said I have added Looks-good-to: tags to a couple of commits. :-)
>
> Cool, I'll covert them to Acks :-)
So it looks like I should expect an update of this patch, right?
Or do you prefer the current one to be applied and work on top of it?
> [..]
>> >> v1 -> v2: Minor style related changes.
>> >>
>> >> kernel/sched/cpufreq_schedutil.c | 34 ++++++++++++++++++++++++--------
>> >> 1 file changed, 26 insertions(+), 8 deletions(-)
>> >>
>> >> diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
>> >> index e13df951aca7..5c482ec38610 100644
>> >> --- a/kernel/sched/cpufreq_schedutil.c
>> >> +++ b/kernel/sched/cpufreq_schedutil.c
>> >> @@ -92,9 +92,6 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
>> >> !cpufreq_can_do_remote_dvfs(sg_policy->policy))
>> >> return false;
>> >>
>> >> - if (sg_policy->work_in_progress)
>> >> - return false;
>> >> -
>> >> if (unlikely(sg_policy->need_freq_update)) {
>> >> sg_policy->need_freq_update = false;
>> >> /*
>> >> @@ -128,7 +125,7 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time,
>> >>
>> >> policy->cur = next_freq;
>> >> trace_cpu_frequency(next_freq, smp_processor_id());
>> >> - } else {
>> >> + } else if (!sg_policy->work_in_progress) {
>> >> sg_policy->work_in_progress = true;
>> >> irq_work_queue(&sg_policy->irq_work);
>> >> }
>> >> @@ -291,6 +288,13 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
>> >>
>> >> ignore_dl_rate_limit(sg_cpu, sg_policy);
>> >>
>> >> + /*
>> >> + * For slow-switch systems, single policy requests can't run at the
>> >> + * moment if update is in progress, unless we acquire update_lock.
>> >> + */
>> >> + if (sg_policy->work_in_progress)
>> >> + return;
>> >> +
>> >
>> > I would still want this to go away :)
>> >
>> > @Rafael, will it be fine to get locking in place for unshared policy
>> > platforms ?
>>
>> As long as it doesn't affect the fast switch path in any way.
>
> I just realized that on a single policy switch that uses the governor thread,
> there will be 1 thread per-CPU. The sugov_update_single will be called on the
> same CPU with interrupts disabled.
sugov_update_single() doesn't have to run on the target CPU.
> In sugov_work, we are doing a
> raw_spin_lock_irqsave which also disables interrupts. So I don't think
> there's any possibility of a race happening on the same CPU between the
> frequency update request and the sugov_work executing. In other words, I feel
> we can drop the above if (..) statement for single policies completely and
> only keep the changes for the shared policy. Viresh since you brought up the
> single policy issue initially which made me add this if statememnt, could you
> let me know if you agree with what I just said?
Which is why you need the spinlock too.
^ permalink raw reply
* [PATCH] cpufreq: Rename cpufreq_can_do_remote_dvfs()
From: Viresh Kumar @ 2018-05-22 10:01 UTC (permalink / raw)
To: Rafael Wysocki, Ingo Molnar, Peter Zijlstra
Cc: Viresh Kumar, linux-pm, Vincent Guittot, Rafael J. Wysocki,
linux-kernel
This routine checks if the CPU running this code belongs to the policy
of the target CPU or if not, can it do remote DVFS for it remotely. But
the current name of it implies as if it is only about doing remote
updates.
Rename it to make it more relevant.
Reported-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/cpufreq/cpufreq_governor.c | 2 +-
include/linux/cpufreq.h | 2 +-
kernel/sched/cpufreq_schedutil.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c
index ca38229b045a..871bf9cf55cf 100644
--- a/drivers/cpufreq/cpufreq_governor.c
+++ b/drivers/cpufreq/cpufreq_governor.c
@@ -278,7 +278,7 @@ static void dbs_update_util_handler(struct update_util_data *data, u64 time,
struct policy_dbs_info *policy_dbs = cdbs->policy_dbs;
u64 delta_ns, lst;
- if (!cpufreq_can_do_remote_dvfs(policy_dbs->policy))
+ if (!cpufreq_this_cpu_can_update(policy_dbs->policy))
return;
/*
diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
index 87f48dd932eb..882a9b9e34bc 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -571,7 +571,7 @@ struct governor_attr {
size_t count);
};
-static inline bool cpufreq_can_do_remote_dvfs(struct cpufreq_policy *policy)
+static inline bool cpufreq_this_cpu_can_update(struct cpufreq_policy *policy)
{
/*
* Allow remote callbacks if:
diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
index 2442decbfec7..2145655dbd9e 100644
--- a/kernel/sched/cpufreq_schedutil.c
+++ b/kernel/sched/cpufreq_schedutil.c
@@ -89,7 +89,7 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
* schedule the kthread.
*/
if (sg_policy->policy->fast_switch_enabled &&
- !cpufreq_can_do_remote_dvfs(sg_policy->policy))
+ !cpufreq_this_cpu_can_update(sg_policy->policy))
return false;
if (sg_policy->work_in_progress)
--
2.15.0.194.g9af6a3dea062
^ permalink raw reply related
* Re: [PATCH v3 0/2] Fix and cleanup iowait boost
From: Peter Zijlstra @ 2018-05-22 9:51 UTC (permalink / raw)
To: Patrick Bellasi
Cc: linux-kernel, linux-pm, Ingo Molnar, Rafael J . Wysocki,
Viresh Kumar, Vincent Guittot, Dietmar Eggemann, Juri Lelli,
Joel Fernandes
In-Reply-To: <20180521085120.7902-1-patrick.bellasi@arm.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
^ permalink raw reply
* Re: [PATCH] cpufreq: Add Kryo CPU scaling driver
From: Viresh Kumar @ 2018-05-22 9:38 UTC (permalink / raw)
To: ilialin
Cc: 'Sudeep Holla', mturquette, sboyd, robh, mark.rutland, nm,
lgirdwood, broonie, andy.gross, david.brown, catalin.marinas,
will.deacon, rjw, linux-clk, devicetree, linux-kernel, linux-pm,
linux-arm-msm, linux-soc, linux-arm-kernel, rnayak, amit.kucheria,
nicolas.dechesne, celster, tfinkel
In-Reply-To: <001401d3f1a2$c7328850$559798f0$@codeaurora.org>
On 22-05-18, 10:59, ilialin@codeaurora.org wrote:
> OK, I think I found out the way. Would this be correct?
> -----------------------------------------------------------------------------------------------
> extern struct cpu_topology cpu_topology[NR_CPUS];
>
> static struct device *qcom_cpufreq_kryo_get_cluster_lead(int cluster)
> {
> unsigned cpu;
>
> for_each_possible_cpu(cpu) {
> if ((cluster == cpu_topology[cpu].cluster_id) &&
> (0 == cpu_topology[cpu].core_id))
> return get_cpu_device(cpu);
> }
>
> return NULL;
> }
Okay, this is what you should do IMHO.
for_each_possible_cpu(cpu) {
cpu_dev = xxx..
ret = dev_pm_opp_set_supported_hw(cpu_dev, xxx, xxx);
if (ret && ret != -EBUSY)
error-out.
}
This would require a trivial patch for the OPP core to not throw an
error message with -EBUSY. I can do that separately.
--
viresh
^ permalink raw reply
* Re: [PATCH] cpufreq: Add Kryo CPU scaling driver
From: Sudeep Holla @ 2018-05-22 9:18 UTC (permalink / raw)
To: ilialin, mturquette, sboyd, robh, mark.rutland, viresh.kumar, nm,
lgirdwood, broonie, andy.gross, david.brown, catalin.marinas,
will.deacon, rjw, linux-clk
Cc: Sudeep Holla, devicetree, linux-kernel, linux-pm, linux-arm-msm,
linux-soc, linux-arm-kernel, rnayak, amit.kucheria,
nicolas.dechesne, celster, tfinkel
In-Reply-To: <001401d3f1a2$c7328850$559798f0$@codeaurora.org>
On 22/05/18 08:59, ilialin@codeaurora.org wrote:
> OK, I think I found out the way. Would this be correct?
No.
> -----------------------------------------------------------------------------------------------
> extern struct cpu_topology cpu_topology[NR_CPUS];
>
> static struct device *qcom_cpufreq_kryo_get_cluster_lead(int cluster)
> {
> unsigned cpu;
>
> for_each_possible_cpu(cpu) {
> if ((cluster == cpu_topology[cpu].cluster_id) &&
cluster_id is going away soon, so avoid relying on that. IIUC there's a
way already something like opp_of_get_shared_cpus.
--
Regards,
Sudeep
^ permalink raw reply
* Re: [PATCH] cpufreq: Add Kryo CPU scaling driver
From: Sudeep Holla @ 2018-05-22 9:12 UTC (permalink / raw)
To: ilialin, mturquette, sboyd, robh, mark.rutland, viresh.kumar, nm,
lgirdwood, broonie, andy.gross, david.brown, catalin.marinas,
will.deacon, rjw, linux-clk
Cc: Sudeep Holla, devicetree, linux-kernel, linux-pm, linux-arm-msm,
linux-soc, linux-arm-kernel, rnayak, amit.kucheria,
nicolas.dechesne, celster, tfinkel
In-Reply-To: <001201d3f19a$0130a860$0391f920$@codeaurora.org>
On 22/05/18 07:56, ilialin@codeaurora.org wrote:
>
>
>> -----Original Message-----
>> From: Sudeep Holla <sudeep.holla@arm.com>
>> Sent: Monday, May 21, 2018 16:05
[...]
>>
>>
>> That may be true and I am not that bothered about it. But assuming physical
>> ordering from the logical cpu number is *incorrect* and will break if kernel
>> decides to change the allocation algorithm. Kernel provides no guarantee on
>> that, so you need to depend on some physical ID or may be DT to achieve
>> what your want. But the current code as it stands is wrong.
>
> Got your point. In fact CPUs are numbered 0-3 and ordered into 2 clusters in the DT:
>
> cpus {
> #address-cells = <2>;
> #size-cells = <0>;
>
> CPU0: cpu@0 {
> ...
> reg = <0x0 0x0>;
> ...
> };
>
> CPU1: cpu@1 {
> ...
> reg = <0x0 0x1>;
> ...
> };
>
> CPU2: cpu@100 {
> ...
> reg = <0x0 0x100>;
> ...
> };
>
> CPU3: cpu@101 {
> ...
> reg = <0x0 0x101>;
> ...
> };
>
> cpu-map {
> cluster0 {
> core0 {
> cpu = <&CPU0>;
> };
>
> core1 {
> cpu = <&CPU1>;
> };
> };
>
> cluster1 {
> core0 {
> cpu = <&CPU2>;
> };
>
> core1 {
> cpu = <&CPU3>;
> };
> };
> };
> };
>
> As far, as I understand, they are probed in the same order.
Yes that's correct today, will that have to remain same for ever ?
No it's not user ABI and kernel can decide to change the allocation
order. What if for some reason one/more CPUs fails to boot or even
configured not to boot ?
> However, to be certain that the physical CPU is the one I intend to
> configure, I have to fetch the device structure pointer for the cpu-map ->
> clusterX -> core0 -> cpu path. Could you suggest a kernel API to do
> that?
>
Let's rewind a bit. Do you supply OPPs only on CPU0 and CPU2 ?
If yes, that's again wrong. Simple solution is to parse all logical
CPUs and skip if the share OPPs with some other CPUs. I think that
logic already exists in OPP library IIRC.
--
Regards,
Sudeep
^ permalink raw reply
* RE: [PATCH] cpufreq: Add Kryo CPU scaling driver
From: ilialin @ 2018-05-22 7:59 UTC (permalink / raw)
To: 'Sudeep Holla', mturquette, sboyd, robh, mark.rutland,
viresh.kumar, nm, lgirdwood, broonie, andy.gross, david.brown,
catalin.marinas, will.deacon, rjw, linux-clk
Cc: devicetree, linux-kernel, linux-pm, linux-arm-msm, linux-soc,
linux-arm-kernel, rnayak, amit.kucheria, nicolas.dechesne,
celster, tfinkel
In-Reply-To: <2ace10bc-e1c4-2060-94d3-eb71e966ffbe@arm.com>
OK, I think I found out the way. Would this be correct?
-----------------------------------------------------------------------------------------------
extern struct cpu_topology cpu_topology[NR_CPUS];
static struct device *qcom_cpufreq_kryo_get_cluster_lead(int cluster)
{
unsigned cpu;
for_each_possible_cpu(cpu) {
if ((cluster == cpu_topology[cpu].cluster_id) &&
(0 == cpu_topology[cpu].core_id))
return get_cpu_device(cpu);
}
return NULL;
}
-----------------------------------------------------------------------------------------------
> -----Original Message-----
> From: ilialin@codeaurora.org <ilialin@codeaurora.org>
> Sent: Tuesday, May 22, 2018 09:56
> To: 'Sudeep Holla' <sudeep.holla@arm.com>; 'mturquette@baylibre.com'
> <mturquette@baylibre.com>; 'sboyd@kernel.org' <sboyd@kernel.org>;
> 'robh@kernel.org' <robh@kernel.org>; 'mark.rutland@arm.com'
> <mark.rutland@arm.com>; 'viresh.kumar@linaro.org'
> <viresh.kumar@linaro.org>; 'nm@ti.com' <nm@ti.com>;
> 'lgirdwood@gmail.com' <lgirdwood@gmail.com>; 'broonie@kernel.org'
> <broonie@kernel.org>; 'andy.gross@linaro.org' <andy.gross@linaro.org>;
> 'david.brown@linaro.org' <david.brown@linaro.org>;
> 'catalin.marinas@arm.com' <catalin.marinas@arm.com>;
> 'will.deacon@arm.com' <will.deacon@arm.com>; 'rjw@rjwysocki.net'
> <rjw@rjwysocki.net>; 'linux-clk@vger.kernel.org' <linux-
> clk@vger.kernel.org>
> Cc: 'devicetree@vger.kernel.org' <devicetree@vger.kernel.org>; 'linux-
> kernel@vger.kernel.org' <linux-kernel@vger.kernel.org>; 'linux-
> pm@vger.kernel.org' <linux-pm@vger.kernel.org>; 'linux-arm-
> msm@vger.kernel.org' <linux-arm-msm@vger.kernel.org>; 'linux-
> soc@vger.kernel.org' <linux-soc@vger.kernel.org>; 'linux-arm-
> kernel@lists.infradead.org' <linux-arm-kernel@lists.infradead.org>;
> 'rnayak@codeaurora.org' <rnayak@codeaurora.org>;
> 'amit.kucheria@linaro.org' <amit.kucheria@linaro.org>;
> 'nicolas.dechesne@linaro.org' <nicolas.dechesne@linaro.org>;
> 'celster@codeaurora.org' <celster@codeaurora.org>;
> 'tfinkel@codeaurora.org' <tfinkel@codeaurora.org>
> Subject: RE: [PATCH] cpufreq: Add Kryo CPU scaling driver
>
>
>
> > -----Original Message-----
> > From: Sudeep Holla <sudeep.holla@arm.com>
> > Sent: Monday, May 21, 2018 16:05
> > To: ilialin@codeaurora.org; mturquette@baylibre.com; sboyd@kernel.org;
> > robh@kernel.org; mark.rutland@arm.com; viresh.kumar@linaro.org;
> > nm@ti.com; lgirdwood@gmail.com; broonie@kernel.org;
> > andy.gross@linaro.org; david.brown@linaro.org;
> > catalin.marinas@arm.com; will.deacon@arm.com; rjw@rjwysocki.net;
> > linux-clk@vger.kernel.org
> > Cc: Sudeep Holla <sudeep.holla@arm.com>; devicetree@vger.kernel.org;
> > linux-kernel@vger.kernel.org; linux-pm@vger.kernel.org; linux-arm-
> > msm@vger.kernel.org; linux-soc@vger.kernel.org; linux-arm-
> > kernel@lists.infradead.org; rnayak@codeaurora.org;
> > amit.kucheria@linaro.org; nicolas.dechesne@linaro.org;
> > celster@codeaurora.org; tfinkel@codeaurora.org
> > Subject: Re: [PATCH] cpufreq: Add Kryo CPU scaling driver
> >
> >
> >
> > On 21/05/18 13:57, ilialin@codeaurora.org wrote:
> > >
> > [...]
> >
> > >>> +#include <linux/cpu.h>
> > >>> +#include <linux/err.h>
> > >>> +#include <linux/init.h>
> > >>> +#include <linux/kernel.h>
> > >>> +#include <linux/module.h>
> > >>> +#include <linux/nvmem-consumer.h> #include <linux/of.h> #include
> > >>> +<linux/platform_device.h> #include <linux/pm_opp.h> #include
> > >>> +<linux/slab.h> #include <linux/soc/qcom/smem.h>
> > >>> +
> > >>> +#define MSM_ID_SMEM 137
> > >>> +#define SILVER_LEAD 0
> > >>> +#define GOLD_LEAD 2
> > >>> +
> > >>
> > >> So I gather form other emails, that these are physical cpu
> > >> number(not even unique identifier like MPIDR). Will this work on
> > >> parts or platforms that need to boot in GOLD LEAD cpus.
> > >
> > > The driver is for Kryo CPU, which (and AFAIK all multicore MSMs)
> > > always boots on the CPU0.
> >
> >
> > That may be true and I am not that bothered about it. But assuming
> > physical ordering from the logical cpu number is *incorrect* and will
> > break if kernel decides to change the allocation algorithm. Kernel
> > provides no guarantee on that, so you need to depend on some physical
> > ID or may be DT to achieve what your want. But the current code as it
> stands is wrong.
>
> Got your point. In fact CPUs are numbered 0-3 and ordered into 2 clusters in
> the DT:
>
> cpus {
> #address-cells = <2>;
> #size-cells = <0>;
>
> CPU0: cpu@0 {
> ...
> reg = <0x0 0x0>;
> ...
> };
>
> CPU1: cpu@1 {
> ...
> reg = <0x0 0x1>;
> ...
> };
>
> CPU2: cpu@100 {
> ...
> reg = <0x0 0x100>;
> ...
> };
>
> CPU3: cpu@101 {
> ...
> reg = <0x0 0x101>;
> ...
> };
>
> cpu-map {
> cluster0 {
> core0 {
> cpu = <&CPU0>;
> };
>
> core1 {
> cpu = <&CPU1>;
> };
> };
>
> cluster1 {
> core0 {
> cpu = <&CPU2>;
> };
>
> core1 {
> cpu = <&CPU3>;
> };
> };
> };
> };
>
> As far, as I understand, they are probed in the same order. However, to be
> certain that the physical CPU is the one I intend to configure, I have to fetch
> the device structure pointer for the cpu-map -> clusterX -> core0 -> cpu path.
> Could you suggest a kernel API to do that?
>
>
>
> >
> > --
> > Regards,
> > Sudeep
^ permalink raw reply
* RE: [PATCH] cpufreq: Add Kryo CPU scaling driver
From: ilialin @ 2018-05-22 6:56 UTC (permalink / raw)
To: 'Sudeep Holla', mturquette, sboyd, robh, mark.rutland,
viresh.kumar, nm, lgirdwood, broonie, andy.gross, david.brown,
catalin.marinas, will.deacon, rjw, linux-clk
Cc: devicetree, linux-kernel, linux-pm, linux-arm-msm, linux-soc,
linux-arm-kernel, rnayak, amit.kucheria, nicolas.dechesne,
celster, tfinkel
In-Reply-To: <2ace10bc-e1c4-2060-94d3-eb71e966ffbe@arm.com>
> -----Original Message-----
> From: Sudeep Holla <sudeep.holla@arm.com>
> Sent: Monday, May 21, 2018 16:05
> To: ilialin@codeaurora.org; mturquette@baylibre.com; sboyd@kernel.org;
> robh@kernel.org; mark.rutland@arm.com; viresh.kumar@linaro.org;
> nm@ti.com; lgirdwood@gmail.com; broonie@kernel.org;
> andy.gross@linaro.org; david.brown@linaro.org; catalin.marinas@arm.com;
> will.deacon@arm.com; rjw@rjwysocki.net; linux-clk@vger.kernel.org
> Cc: Sudeep Holla <sudeep.holla@arm.com>; devicetree@vger.kernel.org;
> linux-kernel@vger.kernel.org; linux-pm@vger.kernel.org; linux-arm-
> msm@vger.kernel.org; linux-soc@vger.kernel.org; linux-arm-
> kernel@lists.infradead.org; rnayak@codeaurora.org;
> amit.kucheria@linaro.org; nicolas.dechesne@linaro.org;
> celster@codeaurora.org; tfinkel@codeaurora.org
> Subject: Re: [PATCH] cpufreq: Add Kryo CPU scaling driver
>
>
>
> On 21/05/18 13:57, ilialin@codeaurora.org wrote:
> >
> [...]
>
> >>> +#include <linux/cpu.h>
> >>> +#include <linux/err.h>
> >>> +#include <linux/init.h>
> >>> +#include <linux/kernel.h>
> >>> +#include <linux/module.h>
> >>> +#include <linux/nvmem-consumer.h>
> >>> +#include <linux/of.h>
> >>> +#include <linux/platform_device.h>
> >>> +#include <linux/pm_opp.h>
> >>> +#include <linux/slab.h>
> >>> +#include <linux/soc/qcom/smem.h>
> >>> +
> >>> +#define MSM_ID_SMEM 137
> >>> +#define SILVER_LEAD 0
> >>> +#define GOLD_LEAD 2
> >>> +
> >>
> >> So I gather form other emails, that these are physical cpu number(not
> >> even unique identifier like MPIDR). Will this work on parts or
> >> platforms that need to boot in GOLD LEAD cpus.
> >
> > The driver is for Kryo CPU, which (and AFAIK all multicore MSMs)
> > always boots on the CPU0.
>
>
> That may be true and I am not that bothered about it. But assuming physical
> ordering from the logical cpu number is *incorrect* and will break if kernel
> decides to change the allocation algorithm. Kernel provides no guarantee on
> that, so you need to depend on some physical ID or may be DT to achieve
> what your want. But the current code as it stands is wrong.
Got your point. In fact CPUs are numbered 0-3 and ordered into 2 clusters in the DT:
cpus {
#address-cells = <2>;
#size-cells = <0>;
CPU0: cpu@0 {
...
reg = <0x0 0x0>;
...
};
CPU1: cpu@1 {
...
reg = <0x0 0x1>;
...
};
CPU2: cpu@100 {
...
reg = <0x0 0x100>;
...
};
CPU3: cpu@101 {
...
reg = <0x0 0x101>;
...
};
cpu-map {
cluster0 {
core0 {
cpu = <&CPU0>;
};
core1 {
cpu = <&CPU1>;
};
};
cluster1 {
core0 {
cpu = <&CPU2>;
};
core1 {
cpu = <&CPU3>;
};
};
};
};
As far, as I understand, they are probed in the same order. However, to be certain that the physical CPU is the one I intend to configure, I have to fetch the device structure pointer for the cpu-map -> clusterX -> core0 -> cpu path. Could you suggest a kernel API to do that?
>
> --
> Regards,
> Sudeep
^ permalink raw reply
* [PATCH v3 3/3] ARM: dts: imx6ull-colibri-wifi: remove operating points
From: Sébastien Szymanski @ 2018-05-22 6:28 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Mark Rutland, devicetree, linux-pm, Viresh Kumar,
Rafael J . Wysocki, linux-kernel, Stefan Agner, Rob Herring,
Sascha Hauer, Fabio Estevam, Shawn Guo
In-Reply-To: <20180522062853.24799-1-sebastien.szymanski@armadeus.com>
Operating points are now defined in the imx6ull.dtsi file so remove
them from board device trees.
Signed-off-by: Sébastien Szymanski <sebastien.szymanski@armadeus.com>
---
arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi | 14 --------------
1 file changed, 14 deletions(-)
diff --git a/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi b/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
index 3dffbcd50bf6..183193e8580d 100644
--- a/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
+++ b/arch/arm/boot/dts/imx6ull-colibri-wifi.dtsi
@@ -20,20 +20,6 @@
&cpu0 {
clock-frequency = <792000000>;
- operating-points = <
- /* kHz uV */
- 792000 1225000
- 528000 1175000
- 396000 1025000
- 198000 950000
- >;
- fsl,soc-operating-points = <
- /* KHz uV */
- 792000 1175000
- 528000 1175000
- 396000 1175000
- 198000 1175000
- >;
};
&iomuxc {
--
2.16.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 2/3] ARM: dts: imx6ull: add operating points
From: Sébastien Szymanski @ 2018-05-22 6:28 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Mark Rutland, devicetree, linux-pm, Viresh Kumar,
Rafael J . Wysocki, linux-kernel, Stefan Agner, Rob Herring,
Sascha Hauer, Fabio Estevam, Shawn Guo
In-Reply-To: <20180522062853.24799-1-sebastien.szymanski@armadeus.com>
i.MX6ULL has different operating ranges than i.MX6UL so add the
operating points for the i.MX6ULL. A 25mV offset is added to the minimum
allowed values like for the i.MX6UL.
Signed-off-by: Sébastien Szymanski <sebastien.szymanski@armadeus.com>
---
Changes for v3:
- none
Changes for v2:
- Fix soc-operating-points voltage for 792MHz and 900MHz
arch/arm/boot/dts/imx6ull.dtsi | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/arch/arm/boot/dts/imx6ull.dtsi b/arch/arm/boot/dts/imx6ull.dtsi
index 571ddd71cdba..530d5526b890 100644
--- a/arch/arm/boot/dts/imx6ull.dtsi
+++ b/arch/arm/boot/dts/imx6ull.dtsi
@@ -46,6 +46,25 @@
/* Delete UART8 in AIPS-1 (i.MX6UL specific) */
/delete-node/ &uart8;
+&cpu0 {
+ operating-points = <
+ /* kHz uV */
+ 900000 1275000
+ 792000 1225000
+ 528000 1175000
+ 396000 1025000
+ 198000 950000
+ >;
+ fsl,soc-operating-points = <
+ /* KHz uV */
+ 900000 1175000
+ 792000 1175000
+ 528000 1175000
+ 396000 1175000
+ 198000 1175000
+ >;
+};
+
/ {
soc {
aips3: aips-bus@2200000 {
--
2.16.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* [PATCH v3 1/3] cpufreq: imx6q: check speed grades for i.MX6ULL
From: Sébastien Szymanski @ 2018-05-22 6:28 UTC (permalink / raw)
To: linux-arm-kernel
Cc: Mark Rutland, devicetree, linux-pm, Viresh Kumar,
Rafael J . Wysocki, linux-kernel, Stefan Agner, Rob Herring,
Sascha Hauer, Fabio Estevam, Shawn Guo
Check the max speed supported from the fuses for i.MX6ULL and update the
operating points table accordingly.
Signed-off-by: Sébastien Szymanski <sebastien.szymanski@armadeus.com>
---
Changes for v3:
- none
Changes for v2:
- none
drivers/cpufreq/imx6q-cpufreq.c | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index 83cf631fc9bc..f094687cae52 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -266,6 +266,8 @@ static void imx6q_opp_check_speed_grading(struct device *dev)
}
#define OCOTP_CFG3_6UL_SPEED_696MHZ 0x2
+#define OCOTP_CFG3_6ULL_SPEED_792MHZ 0x2
+#define OCOTP_CFG3_6ULL_SPEED_900MHZ 0x3
static void imx6ul_opp_check_speed_grading(struct device *dev)
{
@@ -287,16 +289,30 @@ static void imx6ul_opp_check_speed_grading(struct device *dev)
* Speed GRADING[1:0] defines the max speed of ARM:
* 2b'00: Reserved;
* 2b'01: 528000000Hz;
- * 2b'10: 696000000Hz;
- * 2b'11: Reserved;
+ * 2b'10: 696000000Hz on i.MX6UL, 792000000Hz on i.MX6ULL;
+ * 2b'11: 900000000Hz on i.MX6ULL only;
* We need to set the max speed of ARM according to fuse map.
*/
val = readl_relaxed(base + OCOTP_CFG3);
val >>= OCOTP_CFG3_SPEED_SHIFT;
val &= 0x3;
- if (val != OCOTP_CFG3_6UL_SPEED_696MHZ)
- if (dev_pm_opp_disable(dev, 696000000))
- dev_warn(dev, "failed to disable 696MHz OPP\n");
+
+ if (of_machine_is_compatible("fsl,imx6ul")) {
+ if (val != OCOTP_CFG3_6UL_SPEED_696MHZ)
+ if (dev_pm_opp_disable(dev, 696000000))
+ dev_warn(dev, "failed to disable 696MHz OPP\n");
+ }
+
+ if (of_machine_is_compatible("fsl,imx6ull")) {
+ if (val != OCOTP_CFG3_6ULL_SPEED_792MHZ)
+ if (dev_pm_opp_disable(dev, 792000000))
+ dev_warn(dev, "failed to disable 792MHz OPP\n");
+
+ if (val != OCOTP_CFG3_6ULL_SPEED_900MHZ)
+ if (dev_pm_opp_disable(dev, 900000000))
+ dev_warn(dev, "failed to disable 900MHz OPP\n");
+ }
+
iounmap(base);
put_node:
of_node_put(np);
@@ -356,7 +372,8 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
goto put_reg;
}
- if (of_machine_is_compatible("fsl,imx6ul"))
+ if (of_machine_is_compatible("fsl,imx6ul") ||
+ of_machine_is_compatible("fsl,imx6ull"))
imx6ul_opp_check_speed_grading(cpu_dev);
else
imx6q_opp_check_speed_grading(cpu_dev);
--
2.16.1
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply related
* Re: [PATCH v2 1/2] cpufreq: imx6q: check speed grades for i.MX6ULL
From: Sébastien Szymanski @ 2018-05-22 6:13 UTC (permalink / raw)
To: Viresh Kumar
Cc: Linux PM list, Rafael J . Wysocki, Stefan Agner, Fabio Estevam,
Shawn Guo, Linux ARM
In-Reply-To: <CAOh2x==MCPnANhww2JYhGkaALcAPZe_qAUcbZmhyCDwPjOjT2Q@mail.gmail.com>
On 04/19/2018 11:09 AM, Viresh Kumar wrote:
> On Thu, Apr 19, 2018 at 12:49 PM, Sébastien Szymanski
> <sebastien.szymanski@armadeus.com> wrote:
>> Check the max speed supported from the fuses for i.MX6ULL and update the
>> operating points table accordingly.
>>
>> Signed-off-by: Sébastien Szymanski <sebastien.szymanski@armadeus.com>
>> ---
>>
>> Changes for v2:
>> - none
>
> Please cc all the maintainers present in MAINTAINERS file. You missed cc'ing me
> and I missed V1 earlier.
Ok.
>
>> drivers/cpufreq/imx6q-cpufreq.c | 29 +++++++++++++++++++++++------
>> 1 file changed, 23 insertions(+), 6 deletions(-)
>>
>> diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
>> index 83cf631fc9bc..f094687cae52 100644
>> --- a/drivers/cpufreq/imx6q-cpufreq.c
>> +++ b/drivers/cpufreq/imx6q-cpufreq.c
>> @@ -266,6 +266,8 @@ static void imx6q_opp_check_speed_grading(struct device *dev)
>> }
>>
>> #define OCOTP_CFG3_6UL_SPEED_696MHZ 0x2
>> +#define OCOTP_CFG3_6ULL_SPEED_792MHZ 0x2
>> +#define OCOTP_CFG3_6ULL_SPEED_900MHZ 0x3
>
> Looking at the wording everywhere, this represents the maximum
> supported frequency ?
Yes.
> In that case ...
>
>>
>> static void imx6ul_opp_check_speed_grading(struct device *dev)
>> {
>> @@ -287,16 +289,30 @@ static void imx6ul_opp_check_speed_grading(struct device *dev)
>> * Speed GRADING[1:0] defines the max speed of ARM:
>> * 2b'00: Reserved;
>> * 2b'01: 528000000Hz;
>> - * 2b'10: 696000000Hz;
>> - * 2b'11: Reserved;
>> + * 2b'10: 696000000Hz on i.MX6UL, 792000000Hz on i.MX6ULL;
>> + * 2b'11: 900000000Hz on i.MX6ULL only;
>> * We need to set the max speed of ARM according to fuse map.
>> */
>> val = readl_relaxed(base + OCOTP_CFG3);
>> val >>= OCOTP_CFG3_SPEED_SHIFT;
>> val &= 0x3;
>> - if (val != OCOTP_CFG3_6UL_SPEED_696MHZ)
>> - if (dev_pm_opp_disable(dev, 696000000))
>> - dev_warn(dev, "failed to disable 696MHz OPP\n");
>> +
>> + if (of_machine_is_compatible("fsl,imx6ul")) {
>> + if (val != OCOTP_CFG3_6UL_SPEED_696MHZ)
>> + if (dev_pm_opp_disable(dev, 696000000))
>> + dev_warn(dev, "failed to disable 696MHz OPP\n");
>> + }
>> +
>> + if (of_machine_is_compatible("fsl,imx6ull")) {
>> + if (val != OCOTP_CFG3_6ULL_SPEED_792MHZ)
>> + if (dev_pm_opp_disable(dev, 792000000))
>> + dev_warn(dev, "failed to disable 792MHz OPP\n");
>> +
>> + if (val != OCOTP_CFG3_6ULL_SPEED_900MHZ)
>> + if (dev_pm_opp_disable(dev, 900000000))
>> + dev_warn(dev, "failed to disable 900MHz OPP\n");
>
> ... this looks wrong to me as you will end up disabling 792 MHz if max speed is
> 900 MHz.
The datasheet of the 900 MHz i.MX6ULL version [1] does not list 792 MHz
as an operating range, that's why 792 MHz is disabled when max speed is
900 MHz.
[1] https://www.nxp.com/docs/en/data-sheet/IMX6ULLCEC.pdf (page 24,
table 10. "Operating Ranges")
Regards,
>
>> + }
>> +
>> iounmap(base);
>> put_node:
>> of_node_put(np);
>> @@ -356,7 +372,8 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev)
>> goto put_reg;
>> }
>>
>> - if (of_machine_is_compatible("fsl,imx6ul"))
>> + if (of_machine_is_compatible("fsl,imx6ul") ||
>> + of_machine_is_compatible("fsl,imx6ull"))
>> imx6ul_opp_check_speed_grading(cpu_dev);
>> else
>> imx6q_opp_check_speed_grading(cpu_dev);
>> --
>> 2.16.1
>>
--
Sébastien Szymanski
Software engineer, Armadeus Systems
Tel: +33 (0)9 72 29 41 44
Fax: +33 (0)9 72 28 79 26
_______________________________________________
linux-arm-kernel mailing list
linux-arm-kernel@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/linux-arm-kernel
^ permalink raw reply
* Re: [PATCH 19/33] thermal: db8500: use match_string() helper
From: Andy Shevchenko @ 2018-05-21 22:00 UTC (permalink / raw)
To: Yisheng Xie
Cc: Linux Kernel Mailing List, Zhang Rui, Eduardo Valentin, Linux PM
In-Reply-To: <1526903890-35761-20-git-send-email-xieyisheng1@huawei.com>
On Mon, May 21, 2018 at 2:57 PM, Yisheng Xie <xieyisheng1@huawei.com> wrote:
> match_string() returns the index of an array for a matching string,
> which can be used intead of open coded variant.
> + i = match_string((const char **)trip_point->cdev_name,
Casting looks ugly. You need to constify the variable itself.
> + COOLING_DEV_MAX, cdev->type);
>
> - return -ENODEV;
> + return (i < 0) ? -ENODEV : 0;
I would rather go with
if (ret < 0)
return -ENODEV;
return 0;
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH 18/33] power: supply: use match_string() helper
From: Andy Shevchenko @ 2018-05-21 21:58 UTC (permalink / raw)
To: Yisheng Xie; +Cc: Linux Kernel Mailing List, Sebastian Reichel, Linux PM
In-Reply-To: <1526903890-35761-19-git-send-email-xieyisheng1@huawei.com>
On Mon, May 21, 2018 at 2:57 PM, Yisheng Xie <xieyisheng1@huawei.com> wrote:
> match_string() returns the index of an array for a matching string,
> which can be used intead of open coded variant.
>
This doesn't make code looks better anyhow. I even think it makes it
worse to read.
That's why I dropped my version of the change (and yes, I missed the
type conversion which looks here just ugly).
Sebastian, if my opinion makes any difference here, I would say NAK to this one.
> Cc: Sebastian Reichel <sre@kernel.org>
> Cc: linux-pm@vger.kernel.org
> Signed-off-by: Yisheng Xie <xieyisheng1@huawei.com>
> ---
> drivers/power/supply/power_supply_core.c | 16 ++++++----------
> 1 file changed, 6 insertions(+), 10 deletions(-)
>
> diff --git a/drivers/power/supply/power_supply_core.c b/drivers/power/supply/power_supply_core.c
> index feac7b0..84da3a2 100644
> --- a/drivers/power/supply/power_supply_core.c
> +++ b/drivers/power/supply/power_supply_core.c
> @@ -36,8 +36,6 @@
> static bool __power_supply_is_supplied_by(struct power_supply *supplier,
> struct power_supply *supply)
> {
> - int i;
> -
> if (!supply->supplied_from && !supplier->supplied_to)
> return false;
>
> @@ -45,18 +43,16 @@ static bool __power_supply_is_supplied_by(struct power_supply *supplier,
> if (supply->supplied_from) {
> if (!supplier->desc->name)
> return false;
> - for (i = 0; i < supply->num_supplies; i++)
> - if (!strcmp(supplier->desc->name, supply->supplied_from[i]))
> - return true;
> + return match_string((const char **)supply->supplied_from,
> + supply->num_supplies,
> + supplier->desc->name) >= 0;
> } else {
> if (!supply->desc->name)
> return false;
> - for (i = 0; i < supplier->num_supplicants; i++)
> - if (!strcmp(supplier->supplied_to[i], supply->desc->name))
> - return true;
> + return match_string((const char **)supplier->supplied_to,
> + supplier->num_supplicants,
> + supply->desc->name) >= 0;
> }
> -
> - return false;
> }
>
> static int __power_supply_changed_work(struct device *dev, void *data)
> --
> 1.7.12.4
>
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* Re: [PATCH v2 2/2] cpufreq: qcom-fw: Add support for QCOM cpufreq FW driver
From: skannan @ 2018-05-21 19:06 UTC (permalink / raw)
To: Viresh Kumar
Cc: Taniya Das, Rafael J. Wysocki, linux-kernel, linux-pm,
Stephen Boyd, robh, Rajendra Nayak, Amit Nischal, devicetree,
amit.kucheria
In-Reply-To: <20180521090113.qo2lrafjrh2xi6va@vireshk-i7>
On 2018-05-21 02:01, Viresh Kumar wrote:
> On 19-05-18, 23:04, Taniya Das wrote:
>> The CPUfreq FW present in some QCOM chipsets offloads the steps
>> necessary
>> for changing the frequency of CPUs. The driver implements the cpufreq
>> driver interface for this firmware.
>>
>> Signed-off-by: Saravana Kannan <skannan@codeaurora.org>
>> Signed-off-by: Taniya Das <tdas@codeaurora.org>
>> ---
>> drivers/cpufreq/Kconfig.arm | 9 ++
>> drivers/cpufreq/Makefile | 1 +
>> drivers/cpufreq/qcom-cpufreq-fw.c | 317
>> ++++++++++++++++++++++++++++++++++++++
>> 3 files changed, 327 insertions(+)
>> create mode 100644 drivers/cpufreq/qcom-cpufreq-fw.c
>>
>> diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
>> index 96b35b8..571f6b4 100644
>> --- a/drivers/cpufreq/Kconfig.arm
>> +++ b/drivers/cpufreq/Kconfig.arm
>> @@ -301,3 +301,12 @@ config ARM_PXA2xx_CPUFREQ
>> This add the CPUFreq driver support for Intel PXA2xx SOCs.
>>
>> If in doubt, say N.
>> +
>> +config ARM_QCOM_CPUFREQ_FW
>> + bool "QCOM CPUFreq FW driver"
>
> During last review I didn't say that this driver shouldn't be a
> module, but that you need to fix things to make it a module. I am fine
> though if you don't want this to be a module ever.
>
>> + help
>> + Support for the CPUFreq FW driver.
>> + The CPUfreq FW preset in some QCOM chipsets offloads the steps
>> + necessary for changing the frequency of CPUs. The driver
>> + implements the cpufreq driver interface for this firmware.
>> + Say Y if you want to support CPUFreq FW.
>> diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
>> index 8d24ade..a3edbce 100644
>> --- a/drivers/cpufreq/Makefile
>> +++ b/drivers/cpufreq/Makefile
>> @@ -85,6 +85,7 @@ obj-$(CONFIG_ARM_TEGRA124_CPUFREQ) +=
>> tegra124-cpufreq.o
>> obj-$(CONFIG_ARM_TEGRA186_CPUFREQ) += tegra186-cpufreq.o
>> obj-$(CONFIG_ARM_TI_CPUFREQ) += ti-cpufreq.o
>> obj-$(CONFIG_ARM_VEXPRESS_SPC_CPUFREQ) += vexpress-spc-cpufreq.o
>> +obj-$(CONFIG_ARM_QCOM_CPUFREQ_FW) += qcom-cpufreq-fw.o
>>
>>
>>
>> ##################################################################################
>> diff --git a/drivers/cpufreq/qcom-cpufreq-fw.c
>> b/drivers/cpufreq/qcom-cpufreq-fw.c
>> new file mode 100644
>> index 0000000..0e66de0
>> --- /dev/null
>> +++ b/drivers/cpufreq/qcom-cpufreq-fw.c
>> @@ -0,0 +1,317 @@
>> +// SPDX-License-Identifier: GPL-2.0
>> +/*
>> + * Copyright (c) 2018, The Linux Foundation. All rights reserved.
>> + */
>> +
>> +#include <linux/cpufreq.h>
>> +#include <linux/init.h>
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/of_address.h>
>> +#include <linux/of_platform.h>
>> +
>> +#define INIT_RATE 300000000UL
>> +#define XO_RATE 19200000UL
>> +#define LUT_MAX_ENTRIES 40U
>> +#define CORE_COUNT_VAL(val) ((val & GENMASK(18, 16)) >> 16)
>> +#define LUT_ROW_SIZE 32
>> +
>> +struct cpufreq_qcom {
>> + struct cpufreq_frequency_table *table;
>> + struct device *dev;
>> + void __iomem *perf_base;
>> + void __iomem *lut_base;
>> + cpumask_t related_cpus;
>> + unsigned int max_cores;
>> +};
>> +
>> +static struct cpufreq_qcom *qcom_freq_domain_map[NR_CPUS];
>> +
>> +static int
>> +qcom_cpufreq_fw_target_index(struct cpufreq_policy *policy, unsigned
>> int index)
>> +{
>> + struct cpufreq_qcom *c = policy->driver_data;
>> +
>> + if (index >= LUT_MAX_ENTRIES) {
>> + dev_err(c->dev,
>> + "Passing an index (%u) that's greater than max (%d)\n",
>> + index, LUT_MAX_ENTRIES - 1);
>> + return -EINVAL;
>> + }
>
> This is never going to happen unless there is a bug in cpufreq core.
> You are allocating only 40 entries for the cpufreq table and this will
> always be 0-39. None of the other drivers is checking this I believe
> and neither should you. This is the only routine which will get call
> very frequently and we better not add unnecessary stuff here.
>
>> + writel_relaxed(index, c->perf_base);
>> +
>> + /* Make sure the write goes through before proceeding */
>> + mb();
>
> Btw what happens right after this is done ? Are we guaranteed that the
> frequency is updated in the hardware after this ? What about enabling
> fast-switch for your platform ? Look at drivers/cpufreq/scmi-cpufreq.c
> to see how that is done.
Yeah, I don't think this is needed really.
>
>> + return 0;
>> +}
>> +
>> +static unsigned int qcom_cpufreq_fw_get(unsigned int cpu)
>> +{
>> + struct cpufreq_qcom *c;
>> + unsigned int index;
>> +
>> + c = qcom_freq_domain_map[cpu];
>> + if (!c)
>> + return -ENODEV;
>
> Return 0 on error here.
>
>> +
>> + index = readl_relaxed(c->perf_base);
>> + index = min(index, LUT_MAX_ENTRIES - 1);
>
> Will the hardware ever read a value over 39 here ?
The register could be initialized to whatever before the kernel is
brought up. Don't want to depend on it being correct to avoid out of
bounds access that could leak data.
>> +
>> + return c->table[index].frequency;
>> +}
>> +
>> +static int qcom_cpufreq_fw_cpu_init(struct cpufreq_policy *policy)
>> +{
>> + struct cpufreq_qcom *c;
>> +
>> + c = qcom_freq_domain_map[policy->cpu];
>> + if (!c) {
>> + pr_err("No scaling support for CPU%d\n", policy->cpu);
>> + return -ENODEV;
>> + }
>> +
>> + cpumask_copy(policy->cpus, &c->related_cpus);
>> + policy->freq_table = c->table;
>> + policy->driver_data = c;
>> +
>> + return 0;
>> +}
>> +
>> +static struct freq_attr *qcom_cpufreq_fw_attr[] = {
>> + &cpufreq_freq_attr_scaling_available_freqs,
>> + &cpufreq_freq_attr_scaling_boost_freqs,
>> + NULL
>> +};
>> +
>> +static struct cpufreq_driver cpufreq_qcom_fw_driver = {
>> + .flags = CPUFREQ_STICKY | CPUFREQ_NEED_INITIAL_FREQ_CHECK |
>> + CPUFREQ_HAVE_GOVERNOR_PER_POLICY,
>> + .verify = cpufreq_generic_frequency_table_verify,
>> + .target_index = qcom_cpufreq_fw_target_index,
>> + .get = qcom_cpufreq_fw_get,
>> + .init = qcom_cpufreq_fw_cpu_init,
>> + .name = "qcom-cpufreq-fw",
>> + .attr = qcom_cpufreq_fw_attr,
>> + .boost_enabled = true,
>> +};
>> +
>> +static int qcom_read_lut(struct platform_device *pdev,
>> + struct cpufreq_qcom *c)
>> +{
>> + struct device *dev = &pdev->dev;
>> + u32 data, src, lval, i, core_count, prev_cc;
>> +
>> + c->table = devm_kcalloc(dev, LUT_MAX_ENTRIES + 1,
>> + sizeof(*c->table), GFP_KERNEL);
>> + if (!c->table)
>> + return -ENOMEM;
>> +
>> + for (i = 0; i < LUT_MAX_ENTRIES; i++) {
>> + data = readl_relaxed(c->lut_base + i * LUT_ROW_SIZE);
>> + src = ((data & GENMASK(31, 30)) >> 30);
>> + lval = (data & GENMASK(7, 0));
>> + core_count = CORE_COUNT_VAL(data);
>> +
>> + if (!src)
>> + c->table[i].frequency = INIT_RATE / 1000;
>> + else
>> + c->table[i].frequency = XO_RATE * lval / 1000;
>> +
>> + c->table[i].driver_data = c->table[i].frequency;
>
> Why do you need to use driver_data here? Why can't you simple use
> frequency field in the below conditional expressions ?
>
>> +
>> + dev_dbg(dev, "index=%d freq=%d, core_count %d\n",
>> + i, c->table[i].frequency, core_count);
>> +
>> + if (core_count != c->max_cores)
>> + c->table[i].frequency = CPUFREQ_ENTRY_INVALID;
>> +
>> + /*
>> + * Two of the same frequencies with the same core counts means
>> + * end of table.
>> + */
>> + if (i > 0 && c->table[i - 1].driver_data ==
>> + c->table[i].driver_data && prev_cc == core_count) {
>> + struct cpufreq_frequency_table *prev = &c->table[i - 1];
>> +
>> + if (prev->frequency == CPUFREQ_ENTRY_INVALID) {
>
> There can only be a single boost frequency at max ?
As of now, yes. If that changes, we'll change this code later.
>> + prev->flags = CPUFREQ_BOOST_FREQ;
>> + prev->frequency = prev->driver_data;
>
> Okay you are using driver_data as a local variable to keep this value
> safe which you might have overwritten. Maybe use a simple variable
> prev_freq for this. It would be much more readable in that case and
> you wouldn't end up abusing the driver_data field.
>
>> + }
>> +
>> + break;
>> + }
>> + prev_cc = core_count;
>> + }
>> + c->table[i].frequency = CPUFREQ_TABLE_END;
>
> Wouldn't you end up writing on c->table[40].frequency here if there
> are 40 frequency value present ?
Yeah, the loop condition needs to be fixed.
-Saravana
^ permalink raw reply
* Re: [PATCH v2] schedutil: Allow cpufreq requests to be made even when kthread kicked
From: Joel Fernandes @ 2018-05-21 18:05 UTC (permalink / raw)
To: Patrick Bellasi
Cc: linux-kernel, Viresh Kumar, Rafael J . Wysocki, Peter Zijlstra,
Ingo Molnar, Juri Lelli, Luca Abeni, Todd Kjos, claudio,
kernel-team, linux-pm
In-Reply-To: <20180521105055.GQ30654@e110439-lin>
On Mon, May 21, 2018 at 11:50:55AM +0100, Patrick Bellasi wrote:
> On 18-May 11:55, Joel Fernandes (Google.) wrote:
> > From: "Joel Fernandes (Google)" <joel@joelfernandes.org>
> >
> > Currently there is a chance of a schedutil cpufreq update request to be
> > dropped if there is a pending update request. This pending request can
> > be delayed if there is a scheduling delay of the irq_work and the wake
> > up of the schedutil governor kthread.
> >
> > A very bad scenario is when a schedutil request was already just made,
> > such as to reduce the CPU frequency, then a newer request to increase
> > CPU frequency (even sched deadline urgent frequency increase requests)
> > can be dropped, even though the rate limits suggest that its Ok to
> > process a request. This is because of the way the work_in_progress flag
> > is used.
> >
> > This patch improves the situation by allowing new requests to happen
> > even though the old one is still being processed. Note that in this
> > approach, if an irq_work was already issued, we just update next_freq
> > and don't bother to queue another request so there's no extra work being
> > done to make this happen.
>
> Maybe I'm missing something but... is not this patch just a partial
> mitigation of the issue you descrive above?
>
> If a DL freq increase is queued, with this patch we store the request
> but we don't actually increase the frequency until the next schedutil
> update, which can be one tick away... isn't it?
>
> If that's the case, maybe something like the following can complete
> the cure?
>
> ---8<---
> #define SUGOV_FREQ_NONE 0
>
> static unsigned int sugov_work_update(struct sugov_policy *sg_policy,
> unsigned int prev_freq)
> {
> unsigned long irq_flags;
> bool update_freq = true;
> unsigned int next_freq;
>
> /*
> * Hold sg_policy->update_lock shortly to handle the case where:
> * incase sg_policy->next_freq is read here, and then updated by
> * sugov_update_shared just before work_in_progress is set to false
> * here, we may miss queueing the new update.
> *
> * Note: If a work was queued after the update_lock is released,
> * sugov_work will just be called again by kthread_work code; and the
> * request will be proceed before the sugov thread sleeps.
> */
> raw_spin_lock_irqsave(&sg_policy->update_lock, irq_flags);
> next_freq = sg_policy->next_freq;
> sg_policy->work_in_progress = false;
> if (prev_freq == next_freq)
> update_freq = false;
About this patch on top of mine, I believe this check is already being done
by sugov_update_commit? :
static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time,
unsigned int next_freq)
{
struct cpufreq_policy *policy = sg_policy->policy;
if (sg_policy->next_freq == next_freq)
return;
sg_policy->next_freq = next_freq;
sg_policy->last_freq_update_time = time;
----
thanks,
- Joel
^ permalink raw reply
* Re: [PATCH v3 2/2] cpufreq: schedutil: Cleanup and document iowait boost
From: Joel Fernandes @ 2018-05-21 17:46 UTC (permalink / raw)
To: Patrick Bellasi
Cc: linux-kernel, linux-pm, Ingo Molnar, Peter Zijlstra,
Rafael J . Wysocki, Viresh Kumar, Vincent Guittot,
Dietmar Eggemann, Juri Lelli, kernel-team
In-Reply-To: <20180521085120.7902-3-patrick.bellasi@arm.com>
On Mon, May 21, 2018 at 09:51:20AM +0100, Patrick Bellasi wrote:
> The iowait boosting code has been recently updated to add a progressive
> boosting behavior which allows to be less aggressive in boosting tasks
> doing only sporadic IO operations, thus being more energy efficient for
> example on mobile platforms.
>
> The current code is now however a bit convoluted. Some functionalities
> (e.g. iowait boost reset) are replicated in different paths and their
> documentation is slightly misaligned.
>
> Let's cleanup the code by consolidating all the IO wait boosting related
> functionality within within few dedicated functions and better define
> their role:
>
> - sugov_iowait_boost: set/increase the IO wait boost of a CPU
> - sugov_iowait_apply: apply/reduce the IO wait boost of a CPU
>
> Both these two function are used at every sugov updated and they makes
makes->make
updated->update
> use of a unified IO wait boost reset policy provided by:
>
> - sugov_iowait_reset: reset/disable the IO wait boost of a CPU
> if a CPU is not updated for more then one tick
>
> This makes possible a cleaner and more self-contained design for the IO
> wait boosting code since the rest of the sugov update routines, both for
> single and shared frequency domains, follow the same template:
>
> /* Configure IO boost, if required */
> sugov_iowait_boost()
>
> /* Return here if freq change is in progress or throttled */
>
> /* Collect and aggregate utilization information */
> sugov_get_util()
> sugov_aggregate_util()
>
> /*
> * Add IO boost, if currently enabled, on top of the aggregated
> * utilization value
> */
> sugov_iowait_apply()
>
> As a extra bonus, let's also add the documentation for the new
> functions and better align the in-code documentation.
Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org>
thanks,
- Joel
[..]
^ permalink raw reply
* Re: [PATCH v2] schedutil: Allow cpufreq requests to be made even when kthread kicked
From: Patrick Bellasi @ 2018-05-21 17:41 UTC (permalink / raw)
To: Joel Fernandes
Cc: Joel Fernandes (Google.), linux-kernel, Viresh Kumar,
Rafael J . Wysocki, Peter Zijlstra, Ingo Molnar, Juri Lelli,
Luca Abeni, Todd Kjos, claudio, kernel-team, linux-pm
In-Reply-To: <20180521172001.GA21678@joelaf.mtv.corp.google.com>
On 21-May 10:20, Joel Fernandes wrote:
> Hi Patrick,
>
> On Mon, May 21, 2018 at 06:00:50PM +0100, Patrick Bellasi wrote:
> > On 21-May 08:49, Joel Fernandes wrote:
> > > On Mon, May 21, 2018 at 11:50:55AM +0100, Patrick Bellasi wrote:
> > > > On 18-May 11:55, Joel Fernandes (Google.) wrote:
> > > > > From: "Joel Fernandes (Google)" <joel@joelfernandes.org>
> > > > >
> > > > > Currently there is a chance of a schedutil cpufreq update request to be
> > > > > dropped if there is a pending update request. This pending request can
> > > > > be delayed if there is a scheduling delay of the irq_work and the wake
> > > > > up of the schedutil governor kthread.
> > > > >
> > > > > A very bad scenario is when a schedutil request was already just made,
> > > > > such as to reduce the CPU frequency, then a newer request to increase
> > > > > CPU frequency (even sched deadline urgent frequency increase requests)
> > > > > can be dropped, even though the rate limits suggest that its Ok to
> > > > > process a request. This is because of the way the work_in_progress flag
> > > > > is used.
> > > > >
> > > > > This patch improves the situation by allowing new requests to happen
> > > > > even though the old one is still being processed. Note that in this
> > > > > approach, if an irq_work was already issued, we just update next_freq
> > > > > and don't bother to queue another request so there's no extra work being
> > > > > done to make this happen.
> > > >
> > > > Maybe I'm missing something but... is not this patch just a partial
> > > > mitigation of the issue you descrive above?
> > > >
> > > > If a DL freq increase is queued, with this patch we store the request
> > > > but we don't actually increase the frequency until the next schedutil
> > > > update, which can be one tick away... isn't it?
> > > >
> > > > If that's the case, maybe something like the following can complete
> > > > the cure?
> > >
> > > We already discussed this and thought of this case, I think you missed a
> > > previous thread [1]. The outer loop in the kthread_work subsystem will take
> > > care of calling sugov_work again incase another request was queued which we
> > > happen to miss.
> >
> > Ok, I missed that thread... my bad.
>
> Sure no problem, sorry I was just pointing out the thread, not blaming you
> for not reading it ;)
Sure, np here too ;)
> > However, [1] made me noticing that your solution works under the
> > assumption that we keep queuing a new kworker job for each request we
> > get, isn't it?
>
> Not at each request, but each request after work_in_progress was cleared by the
> sugov_work. Any requests that happen between work_in_progress is set and
> cleared only result in updating of the next_freq.
I see, so we enqueue for the time of:
mutex_lock(&sg_policy->work_lock);
__cpufreq_driver_target(sg_policy->policy, freq, CPUFREQ_RELATION_L);
mutex_unlock(&sg_policy->work_lock);
> > If that's the case, this means that if, for example, during a
> > frequency switch you get a request to reduce the frequency (e.g.
> > deadline task passing the 0-lag time) and right after a request to
> > increase the frequency (e.g. the current FAIR task tick)... you will
> > enqueue a freq drop followed by a freq increase and actually do two
> > frequency hops?
>
> Yes possibly,
Not sure about the time window above, I can try to get some
measurements tomorrow.
> I see your point but I'm not sure if the tight loop around that
> is worth the complexity, or atleast is within the scope of my patch.
> Perhaps the problem you describe can be looked at as a future enhancement?
Sure, I already have it as a patch on top of your. I can post it
afterwards and we can discuss whether it makes sense or not.
Still have to better check, but I think that maybe we can skip
the queueing altogether if some work is already pending... in case we
wanna go for a dedicated inner loop like the one I was proposing.
Apart that, I think that your patch is already fixing 90% of the
issue we have now.
> thanks,
>
> - Joel
--
#include <best/regards.h>
Patrick Bellasi
^ permalink raw reply
* Re: [PATCH v3 1/2] cpufreq: schedutil: Fix iowait boost reset
From: Joel Fernandes @ 2018-05-21 17:33 UTC (permalink / raw)
To: Patrick Bellasi
Cc: linux-kernel, linux-pm, Ingo Molnar, Peter Zijlstra,
Rafael J . Wysocki, Viresh Kumar, Vincent Guittot,
Dietmar Eggemann, Juri Lelli, kernel-team
In-Reply-To: <20180521085120.7902-2-patrick.bellasi@arm.com>
On Mon, May 21, 2018 at 09:51:19AM +0100, Patrick Bellasi wrote:
> A more energy efficient update of the IO wait boosting mechanism has
> been introduced in:
>
> commit a5a0809bc58e ("cpufreq: schedutil: Make iowait boost more energy efficient")
>
> where the boost value is expected to be:
>
> - doubled at each successive wakeup from IO
> staring from the minimum frequency supported by a CPU
>
> - reset when a CPU is not updated for more then one tick
> by either disabling the IO wait boost or resetting its value to the
> minimum frequency if this new update requires an IO boost.
>
> This approach is supposed to "ignore" boosting for sporadic wakeups from
> IO, while still getting the frequency boosted to the maximum to benefit
> long sequence of wakeup from IO operations.
>
> However, these assumptions are not always satisfied.
> For example, when an IO boosted CPU enters idle for more the one tick
> and then wakes up after an IO wait, since in sugov_set_iowait_boost() we
> first check the IOWAIT flag, we keep doubling the iowait boost instead
> of restarting from the minimum frequency value.
>
> This misbehavior could happen mainly on non-shared frequency domains,
> thus defeating the energy efficiency optimization, but it can also
> happen on shared frequency domain systems.
>
> Let fix this issue in sugov_set_iowait_boost() by:
> - first check the IO wait boost reset conditions
> to eventually reset the boost value
> - then applying the correct IO boost value
> if required by the caller
>
> Reported-by: Viresh Kumar <viresh.kumar@linaro.org>
> Signed-off-by: Patrick Bellasi <patrick.bellasi@arm.com>
> Cc: Ingo Molnar <mingo@redhat.com>
> Cc: Peter Zijlstra <peterz@infradead.org>
> Cc: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
> Cc: Viresh Kumar <viresh.kumar@linaro.org>
> Cc: Joel Fernandes <joelaf@google.com>
> Cc: Juri Lelli <juri.lelli@redhat.com>
> Cc: Dietmar Eggemann <dietmar.eggemann@arm.com>
> Cc: linux-kernel@vger.kernel.org
> Cc: linux-pm@vger.kernel.org
> Fixes: a5a0809bc58e ("cpufreq: schedutil: Make iowait boost more energy efficient")
>
> ---
> Changes in v3:
> - split the fix into a separated patch (this one)
> - added "Fixes" tag (Viresh)
> ---
> kernel/sched/cpufreq_schedutil.c | 18 ++++++++++--------
> 1 file changed, 10 insertions(+), 8 deletions(-)
>
> diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> index e13df951aca7..c4063e578e4d 100644
> --- a/kernel/sched/cpufreq_schedutil.c
> +++ b/kernel/sched/cpufreq_schedutil.c
> @@ -203,6 +203,16 @@ static unsigned long sugov_aggregate_util(struct sugov_cpu *sg_cpu)
>
> static void sugov_set_iowait_boost(struct sugov_cpu *sg_cpu, u64 time, unsigned int flags)
> {
> + /* Clear iowait_boost if the CPU apprears to have been idle. */
> + if (sg_cpu->iowait_boost) {
> + s64 delta_ns = time - sg_cpu->last_update;
> +
> + if (delta_ns > TICK_NSEC) {
> + sg_cpu->iowait_boost = 0;
> + sg_cpu->iowait_boost_pending = false;
> + }
> + }
> +
Yes, I guess this effects single policies only. For shared, we are resetting
the iowait boost on the wake-up-from-idle update anyway. So even if it was
doubled, it would be reset.
Looks good to me! thanks,
Reviewed-by: Joel Fernandes (Google) <joel@joelfernandes.org>
^ permalink raw reply
* Re: [PATCH v2] schedutil: Allow cpufreq requests to be made even when kthread kicked
From: Joel Fernandes @ 2018-05-21 17:20 UTC (permalink / raw)
To: Patrick Bellasi
Cc: Joel Fernandes (Google.), linux-kernel, Viresh Kumar,
Rafael J . Wysocki, Peter Zijlstra, Ingo Molnar, Juri Lelli,
Luca Abeni, Todd Kjos, claudio, kernel-team, linux-pm
In-Reply-To: <20180521170050.GT30654@e110439-lin>
Hi Patrick,
On Mon, May 21, 2018 at 06:00:50PM +0100, Patrick Bellasi wrote:
> On 21-May 08:49, Joel Fernandes wrote:
> > On Mon, May 21, 2018 at 11:50:55AM +0100, Patrick Bellasi wrote:
> > > On 18-May 11:55, Joel Fernandes (Google.) wrote:
> > > > From: "Joel Fernandes (Google)" <joel@joelfernandes.org>
> > > >
> > > > Currently there is a chance of a schedutil cpufreq update request to be
> > > > dropped if there is a pending update request. This pending request can
> > > > be delayed if there is a scheduling delay of the irq_work and the wake
> > > > up of the schedutil governor kthread.
> > > >
> > > > A very bad scenario is when a schedutil request was already just made,
> > > > such as to reduce the CPU frequency, then a newer request to increase
> > > > CPU frequency (even sched deadline urgent frequency increase requests)
> > > > can be dropped, even though the rate limits suggest that its Ok to
> > > > process a request. This is because of the way the work_in_progress flag
> > > > is used.
> > > >
> > > > This patch improves the situation by allowing new requests to happen
> > > > even though the old one is still being processed. Note that in this
> > > > approach, if an irq_work was already issued, we just update next_freq
> > > > and don't bother to queue another request so there's no extra work being
> > > > done to make this happen.
> > >
> > > Maybe I'm missing something but... is not this patch just a partial
> > > mitigation of the issue you descrive above?
> > >
> > > If a DL freq increase is queued, with this patch we store the request
> > > but we don't actually increase the frequency until the next schedutil
> > > update, which can be one tick away... isn't it?
> > >
> > > If that's the case, maybe something like the following can complete
> > > the cure?
> >
> > We already discussed this and thought of this case, I think you missed a
> > previous thread [1]. The outer loop in the kthread_work subsystem will take
> > care of calling sugov_work again incase another request was queued which we
> > happen to miss.
>
> Ok, I missed that thread... my bad.
Sure no problem, sorry I was just pointing out the thread, not blaming you
for not reading it ;)
> However, [1] made me noticing that your solution works under the
> assumption that we keep queuing a new kworker job for each request we
> get, isn't it?
Not at each request, but each request after work_in_progress was cleared by the
sugov_work. Any requests that happen between work_in_progress is set and
cleared only result in updating of the next_freq.
> If that's the case, this means that if, for example, during a
> frequency switch you get a request to reduce the frequency (e.g.
> deadline task passing the 0-lag time) and right after a request to
> increase the frequency (e.g. the current FAIR task tick)... you will
> enqueue a freq drop followed by a freq increase and actually do two
> frequency hops?
Yes possibly, I see your point but I'm not sure if the tight loop around that
is worth the complexity, or atleast is within the scope of my patch. Perhaps
the problem you describe can be looked at as a future enhancement?
thanks,
- Joel
^ permalink raw reply
* Re: [PATCH v2] schedutil: Allow cpufreq requests to be made even when kthread kicked
From: Patrick Bellasi @ 2018-05-21 17:00 UTC (permalink / raw)
To: Joel Fernandes
Cc: Joel Fernandes (Google.), linux-kernel, Viresh Kumar,
Rafael J . Wysocki, Peter Zijlstra, Ingo Molnar, Juri Lelli,
Luca Abeni, Todd Kjos, claudio, kernel-team, linux-pm
In-Reply-To: <20180521154957.GA14065@joelaf.mtv.corp.google.com>
On 21-May 08:49, Joel Fernandes wrote:
> On Mon, May 21, 2018 at 11:50:55AM +0100, Patrick Bellasi wrote:
> > On 18-May 11:55, Joel Fernandes (Google.) wrote:
> > > From: "Joel Fernandes (Google)" <joel@joelfernandes.org>
> > >
> > > Currently there is a chance of a schedutil cpufreq update request to be
> > > dropped if there is a pending update request. This pending request can
> > > be delayed if there is a scheduling delay of the irq_work and the wake
> > > up of the schedutil governor kthread.
> > >
> > > A very bad scenario is when a schedutil request was already just made,
> > > such as to reduce the CPU frequency, then a newer request to increase
> > > CPU frequency (even sched deadline urgent frequency increase requests)
> > > can be dropped, even though the rate limits suggest that its Ok to
> > > process a request. This is because of the way the work_in_progress flag
> > > is used.
> > >
> > > This patch improves the situation by allowing new requests to happen
> > > even though the old one is still being processed. Note that in this
> > > approach, if an irq_work was already issued, we just update next_freq
> > > and don't bother to queue another request so there's no extra work being
> > > done to make this happen.
> >
> > Maybe I'm missing something but... is not this patch just a partial
> > mitigation of the issue you descrive above?
> >
> > If a DL freq increase is queued, with this patch we store the request
> > but we don't actually increase the frequency until the next schedutil
> > update, which can be one tick away... isn't it?
> >
> > If that's the case, maybe something like the following can complete
> > the cure?
>
> We already discussed this and thought of this case, I think you missed a
> previous thread [1]. The outer loop in the kthread_work subsystem will take
> care of calling sugov_work again incase another request was queued which we
> happen to miss.
Ok, I missed that thread... my bad.
However, [1] made me noticing that your solution works under the
assumption that we keep queuing a new kworker job for each request we
get, isn't it?
If that's the case, this means that if, for example, during a
frequency switch you get a request to reduce the frequency (e.g.
deadline task passing the 0-lag time) and right after a request to
increase the frequency (e.g. the current FAIR task tick)... you will
enqueue a freq drop followed by a freq increase and actually do two
frequency hops?
> So I don't think more complexity is needed to handle the case
> you're bringing up.
>
> thanks!
>
> - Joel
>
> [1] https://lkml.org/lkml/2018/5/17/668
>
--
#include <best/regards.h>
Patrick Bellasi
^ permalink raw reply
* Re: [PATCH v2] schedutil: Allow cpufreq requests to be made even when kthread kicked
From: Joel Fernandes @ 2018-05-21 16:13 UTC (permalink / raw)
To: Rafael J. Wysocki
Cc: Viresh Kumar, Joel Fernandes (Google.), Linux Kernel Mailing List,
Rafael J . Wysocki, Peter Zijlstra, Ingo Molnar, Patrick Bellasi,
Juri Lelli, Luca Abeni, Todd Kjos, Claudio Scordino, kernel-team,
Linux PM
In-Reply-To: <CAJZ5v0jbJ3HfLyP6VZ2PuG0q1n=faX3G98ruwK-o1ro+gv7B9w@mail.gmail.com>
On Mon, May 21, 2018 at 10:29:52AM +0200, Rafael J. Wysocki wrote:
> On Mon, May 21, 2018 at 7:14 AM, Viresh Kumar <viresh.kumar@linaro.org> wrote:
> > On 18-05-18, 11:55, Joel Fernandes (Google.) wrote:
> >> From: "Joel Fernandes (Google)" <joel@joelfernandes.org>
> >>
> >> Currently there is a chance of a schedutil cpufreq update request to be
> >> dropped if there is a pending update request. This pending request can
> >> be delayed if there is a scheduling delay of the irq_work and the wake
> >> up of the schedutil governor kthread.
> >>
> >> A very bad scenario is when a schedutil request was already just made,
> >> such as to reduce the CPU frequency, then a newer request to increase
> >> CPU frequency (even sched deadline urgent frequency increase requests)
> >> can be dropped, even though the rate limits suggest that its Ok to
> >> process a request. This is because of the way the work_in_progress flag
> >> is used.
> >>
> >> This patch improves the situation by allowing new requests to happen
> >> even though the old one is still being processed. Note that in this
> >> approach, if an irq_work was already issued, we just update next_freq
> >> and don't bother to queue another request so there's no extra work being
> >> done to make this happen.
> >
> > Now that this isn't an RFC anymore, you shouldn't have added below
> > paragraph here. It could go to the comments section though.
> >
> >> I had brought up this issue at the OSPM conference and Claudio had a
> >> discussion RFC with an alternate approach [1]. I prefer the approach as
> >> done in the patch below since it doesn't need any new flags and doesn't
> >> cause any other extra overhead.
> >>
> >> [1] https://patchwork.kernel.org/patch/10384261/
> >>
> >> LGTMed-by: Viresh Kumar <viresh.kumar@linaro.org>
> >> LGTMed-by: Juri Lelli <juri.lelli@redhat.com>
> >
> > Looks like a Tag you just invented ? :)
>
> Yeah.
>
> The LGTM from Juri can be converned into an ACK silently IMO. That
> said I have added Looks-good-to: tags to a couple of commits. :-)
Cool, I'll covert them to Acks :-)
[..]
> >> v1 -> v2: Minor style related changes.
> >>
> >> kernel/sched/cpufreq_schedutil.c | 34 ++++++++++++++++++++++++--------
> >> 1 file changed, 26 insertions(+), 8 deletions(-)
> >>
> >> diff --git a/kernel/sched/cpufreq_schedutil.c b/kernel/sched/cpufreq_schedutil.c
> >> index e13df951aca7..5c482ec38610 100644
> >> --- a/kernel/sched/cpufreq_schedutil.c
> >> +++ b/kernel/sched/cpufreq_schedutil.c
> >> @@ -92,9 +92,6 @@ static bool sugov_should_update_freq(struct sugov_policy *sg_policy, u64 time)
> >> !cpufreq_can_do_remote_dvfs(sg_policy->policy))
> >> return false;
> >>
> >> - if (sg_policy->work_in_progress)
> >> - return false;
> >> -
> >> if (unlikely(sg_policy->need_freq_update)) {
> >> sg_policy->need_freq_update = false;
> >> /*
> >> @@ -128,7 +125,7 @@ static void sugov_update_commit(struct sugov_policy *sg_policy, u64 time,
> >>
> >> policy->cur = next_freq;
> >> trace_cpu_frequency(next_freq, smp_processor_id());
> >> - } else {
> >> + } else if (!sg_policy->work_in_progress) {
> >> sg_policy->work_in_progress = true;
> >> irq_work_queue(&sg_policy->irq_work);
> >> }
> >> @@ -291,6 +288,13 @@ static void sugov_update_single(struct update_util_data *hook, u64 time,
> >>
> >> ignore_dl_rate_limit(sg_cpu, sg_policy);
> >>
> >> + /*
> >> + * For slow-switch systems, single policy requests can't run at the
> >> + * moment if update is in progress, unless we acquire update_lock.
> >> + */
> >> + if (sg_policy->work_in_progress)
> >> + return;
> >> +
> >
> > I would still want this to go away :)
> >
> > @Rafael, will it be fine to get locking in place for unshared policy
> > platforms ?
>
> As long as it doesn't affect the fast switch path in any way.
I just realized that on a single policy switch that uses the governor thread,
there will be 1 thread per-CPU. The sugov_update_single will be called on the
same CPU with interrupts disabled. In sugov_work, we are doing a
raw_spin_lock_irqsave which also disables interrupts. So I don't think
there's any possibility of a race happening on the same CPU between the
frequency update request and the sugov_work executing. In other words, I feel
we can drop the above if (..) statement for single policies completely and
only keep the changes for the shared policy. Viresh since you brought up the
single policy issue initially which made me add this if statememnt, could you
let me know if you agree with what I just said?
> >> if (!sugov_should_update_freq(sg_policy, time))
> >> return;
> >>
> >> @@ -382,13 +386,27 @@ sugov_update_shared(struct update_util_data *hook, u64 time, unsigned int flags)
> >> static void sugov_work(struct kthread_work *work)
> >> {
> >> struct sugov_policy *sg_policy = container_of(work, struct sugov_policy, work);
> >> + unsigned int freq;
> >> + unsigned long flags;
> >> +
> >> + /*
> >> + * Hold sg_policy->update_lock shortly to handle the case where:
> >> + * incase sg_policy->next_freq is read here, and then updated by
> >> + * sugov_update_shared just before work_in_progress is set to false
> >> + * here, we may miss queueing the new update.
> >> + *
> >> + * Note: If a work was queued after the update_lock is released,
> >> + * sugov_work will just be called again by kthread_work code; and the
> >> + * request will be proceed before the sugov thread sleeps.
> >> + */
> >> + raw_spin_lock_irqsave(&sg_policy->update_lock, flags);
> >> + freq = sg_policy->next_freq;
> >> + sg_policy->work_in_progress = false;
> >> + raw_spin_unlock_irqrestore(&sg_policy->update_lock, flags);
> >>
> >> mutex_lock(&sg_policy->work_lock);
> >> - __cpufreq_driver_target(sg_policy->policy, sg_policy->next_freq,
> >> - CPUFREQ_RELATION_L);
> >> + __cpufreq_driver_target(sg_policy->policy, freq, CPUFREQ_RELATION_L);
> >> mutex_unlock(&sg_policy->work_lock);
> >> -
> >> - sg_policy->work_in_progress = false;
> >> }
> >>
> >> static void sugov_irq_work(struct irq_work *irq_work)
> >
> > Fix the commit log and you can add my
>
> I can fix it up.
>
> > Acked-by: Viresh Kumar <viresh.kumar@linaro.org>
Thanks!
- Joel
^ permalink raw reply
* Re: [PATCH v2] schedutil: Allow cpufreq requests to be made even when kthread kicked
From: Joel Fernandes @ 2018-05-21 15:49 UTC (permalink / raw)
To: Patrick Bellasi
Cc: Joel Fernandes (Google.), linux-kernel, Viresh Kumar,
Rafael J . Wysocki, Peter Zijlstra, Ingo Molnar, Juri Lelli,
Luca Abeni, Todd Kjos, claudio, kernel-team, linux-pm
In-Reply-To: <20180521105055.GQ30654@e110439-lin>
On Mon, May 21, 2018 at 11:50:55AM +0100, Patrick Bellasi wrote:
> On 18-May 11:55, Joel Fernandes (Google.) wrote:
> > From: "Joel Fernandes (Google)" <joel@joelfernandes.org>
> >
> > Currently there is a chance of a schedutil cpufreq update request to be
> > dropped if there is a pending update request. This pending request can
> > be delayed if there is a scheduling delay of the irq_work and the wake
> > up of the schedutil governor kthread.
> >
> > A very bad scenario is when a schedutil request was already just made,
> > such as to reduce the CPU frequency, then a newer request to increase
> > CPU frequency (even sched deadline urgent frequency increase requests)
> > can be dropped, even though the rate limits suggest that its Ok to
> > process a request. This is because of the way the work_in_progress flag
> > is used.
> >
> > This patch improves the situation by allowing new requests to happen
> > even though the old one is still being processed. Note that in this
> > approach, if an irq_work was already issued, we just update next_freq
> > and don't bother to queue another request so there's no extra work being
> > done to make this happen.
>
> Maybe I'm missing something but... is not this patch just a partial
> mitigation of the issue you descrive above?
>
> If a DL freq increase is queued, with this patch we store the request
> but we don't actually increase the frequency until the next schedutil
> update, which can be one tick away... isn't it?
>
> If that's the case, maybe something like the following can complete
> the cure?
We already discussed this and thought of this case, I think you missed a
previous thread [1]. The outer loop in the kthread_work subsystem will take
care of calling sugov_work again incase another request was queued which we
happen to miss. So I don't think more complexity is needed to handle the case
you're bringing up.
thanks!
- Joel
[1] https://lkml.org/lkml/2018/5/17/668
^ permalink raw reply
* Re: OMAP serial runtime PM and autosuspend (was: Re: [PATCH 4/7] dt-bindings: gnss: add u-blox binding))
From: Tony Lindgren @ 2018-05-21 15:48 UTC (permalink / raw)
To: Johan Hovold
Cc: Sebastian Reichel, H. Nikolaus Schaller, Andreas Kemnade,
Mark Rutland, Arnd Bergmann, Pavel Machek,
linux-kernel@vger.kernel.org,
open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
Greg Kroah-Hartman, Rob Herring, linux-serial, linux-omap,
linux-pm
In-Reply-To: <20180521134830.GR30172@localhost>
* Johan Hovold <johan@kernel.org> [180521 13:50]:
> On Thu, May 17, 2018 at 10:10:38AM -0700, Tony Lindgren wrote:
> > * Johan Hovold <johan@kernel.org> [180517 10:12]:
> > > No, defaulting to "on" (i.e. calling pm_runtime_forbid()) wouldn't work
> > > either as that would also prevent the device from runtime suspending
> > > just as the current negative autosuspend delay does.
> >
> > Well in that case we should just stick with -1 value for the
> > autosuspend. And just do pm_runtime_put_sync_suspend() after
> > probe and on close.
>
> That won't work either as a negative autosuspend delay prevents runtime
> suspend completely (by grabbing an extra RPM reference).
Well so negative autosuspend delay is working as documented then :)
> > > I fail to see how we can implement this using the current toolbox. What
> > > you're after here is really a mechanism for selecting between two
> > > different runtime PM schemes at runtime:
> > >
> > > 1. normal serial RPM, where the controller is active while the
> > > port is open (this should be the safe default)
> >
> > Agreed. And that is the case already.
>
> Yes, but it's not really the case today as since omap-serial (and
> 8250-omap) sets a negative autosuspend at probe and hence does not
> runtime-suspend when the port is closed. So that's the long-standing bug
> which needs fixing.
Yes the bug for closed ports needs to be fixed for sure.
> > > 2. aggressive serial RPM, where the controller is allowed to
> > > suspend while the port is open even though this may result in
> > > lost characters when waking up on incoming data
> >
> > In this case it seems that the only thing needed is to just
> > configure the autosuspend delay for the parent port. The use of
> > -1 has been around since the start of runtime PM AFAIK, so maybe
> > we should just document it. I guess we could also introduce
> > pm_runtime_block_autoidle_unless_configured() :)
>
> The implications of a negative autosuspend delay are already documented
> (in Documentation/power/runtime_pm.txt); it's just the omap drivers that
> gets it wrong when trying to do things which aren't currently supported
> (and never have been).
>
> So I still think we need a new mechanism for this.
Well if you have some better mechanism in mind let's try it out. Short of
sprinkling pm_runtime_force_suspend/resume calls all over, I'm out of ideas
right now.
> > > For normal ttys, we need a user-space interface for selecting between
> > > the two, and for serdev we may want a way to select the RPM scheme from
> > > within the kernel.
> > >
> > > Note that with my serdev controller runtime PM patch, serdev core could
> > > always opt for aggressive PM (as by default serdev core holds an RPM
> > > reference for the controller while the port is open).
> >
> > So if your serdev controller was to set the parent autosuspend
> > delay on open() and set it back on close() this should work?
>
> Is it really the job of a serdev driver to set the autosuspend delay of
> a parent controller? Isn't this somethings which depends on the
> characteristics of the controller (possibly configurable by user space)
> such as the cost of runtime suspending and resuming?
Only in some cases will the serdev driver know it's safe to configure
the parent controller. Configuring the parent controller from userspace
works just fine as we've seen for years now.
> The patch I posted works with what we have today; if a parent serial
> controller driver uses aggressive runtime PM by default or after having
> been configured through sysfs to do so.
Yeah let's stick with configuring the parent controller from userspace
for now at least.
> What I'm getting at here is that the delay should be set by the serial
> driver implementing aggressive runtime PM. Then all we need is a
> mechanism to determine whether an extra RPM reference should be taken at
> tty open or not (configurable by user space, defaulting to yes).
OK yeah some additional on/off switch seems to be missing here.
> Specifically, the serial drivers themselves would always use
> autosuspend and not have to deal with supporting the two RPM schemes
> (normal vs aggressive runtime PM).
OK. So if I understand your idea right, we could have autosuspend timeout
set to 3000ms in the 8250_omap.c but still default to RPM blocked?
Then user can enable aggressive PM via /sys as desired, right?
Regards,
Tony
^ permalink raw reply
* [RFC PATCH v3 10/10] arch_topology: Start Energy Aware Scheduling
From: Quentin Perret @ 2018-05-21 14:25 UTC (permalink / raw)
To: peterz, rjw, gregkh, linux-kernel, linux-pm
Cc: mingo, dietmar.eggemann, morten.rasmussen, chris.redpath,
patrick.bellasi, valentin.schneider, vincent.guittot,
thara.gopinath, viresh.kumar, tkjos, joelaf, smuckle, adharmap,
skannan, pkondeti, juri.lelli, edubezval, srinivas.pandruvada,
currojerez, javi.merino, quentin.perret
In-Reply-To: <20180521142505.6522-1-quentin.perret@arm.com>
Energy Aware Scheduling starts when the scheduling domains are built if the
Energy Model is present and all conditions are met. However, in the typical
case of Arm/Arm64 systems, the Energy Model is provided after the scheduling
domains are first built at boot time, which results in EAS staying
disabled.
This commit fixes this issue by re-building the scheduling domain from the
arch topology driver, once CPUfreq is up and running and when the capacity
of the CPUs have been updated to their final value.
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Quentin Perret <quentin.perret@arm.com>
---
drivers/base/arch_topology.c | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c
index e7cb0c6ade81..7f9fa10ef940 100644
--- a/drivers/base/arch_topology.c
+++ b/drivers/base/arch_topology.c
@@ -15,6 +15,8 @@
#include <linux/slab.h>
#include <linux/string.h>
#include <linux/sched/topology.h>
+#include <linux/energy_model.h>
+#include <linux/cpuset.h>
DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE;
@@ -173,6 +175,9 @@ static cpumask_var_t cpus_to_visit;
static void parsing_done_workfn(struct work_struct *work);
static DECLARE_WORK(parsing_done_work, parsing_done_workfn);
+static void start_eas_workfn(struct work_struct *work);
+static DECLARE_WORK(start_eas_work, start_eas_workfn);
+
static int
init_cpu_capacity_callback(struct notifier_block *nb,
unsigned long val,
@@ -204,6 +209,7 @@ init_cpu_capacity_callback(struct notifier_block *nb,
free_raw_capacity();
pr_debug("cpu_capacity: parsing done\n");
schedule_work(&parsing_done_work);
+ schedule_work(&start_eas_work);
}
return 0;
@@ -249,6 +255,19 @@ static void parsing_done_workfn(struct work_struct *work)
free_cpumask_var(cpus_to_visit);
}
+static void start_eas_workfn(struct work_struct *work)
+{
+ /* Make sure the EM knows about the updated CPU capacities. */
+ rcu_read_lock();
+ em_rescale_cpu_capacity();
+ rcu_read_unlock();
+
+ /* Inform the scheduler about the EM availability. */
+ cpus_read_lock();
+ rebuild_sched_domains();
+ cpus_read_unlock();
+}
+
#else
core_initcall(free_raw_capacity);
#endif
--
2.17.0
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox