* [PATCH V2 2/5] cpufreq: send new set of notification for transition failures
2013-12-02 5:34 [PATCH V2 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Viresh Kumar
@ 2013-12-02 5:34 ` Viresh Kumar
2013-12-02 5:34 ` [PATCH V2 3/5] cpufreq: pcc: " Viresh Kumar
` (3 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Viresh Kumar @ 2013-12-02 5:34 UTC (permalink / raw)
To: rjw; +Cc: linaro-kernel, patches, cpufreq, linux-pm, linux-kernel,
Viresh Kumar
In the current code, if we fail during a frequency transition we simply send the
POSTCHANGE notification with old frequency. This isn't enough.
One of the core user of these notifications is the code responsible for keeping
loops_per_jiffy aligned with frequency change. And mostly it is written as:
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
update-loops-per-jiffy...
}
So, suppose we are changing to a higher frequency and failed during transition,
then following will happen:
- CPUFREQ_PRECHANGE notification with freq-new > freq-old
- CPUFREQ_POSTCHANGE notification with freq-new == freq-old
The first one will update loops_per_jiffy and second one will do nothing. Even
if we send the 2nd notification by exchanging values of freq-new and old, some
users of these notifications might get unstable.
This can be fixed by simply calling cpufreq_notify_post_transition() with error
code and this routine will take care of sending notifications in correct order.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/cpufreq/cpufreq.c | 13 ++-----------
1 file changed, 2 insertions(+), 11 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 3b877d4..a7fcb84 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1815,17 +1815,8 @@ int __cpufreq_driver_target(struct cpufreq_policy *policy,
pr_err("%s: Failed to change cpu frequency: %d\n",
__func__, retval);
- if (notify) {
- /*
- * Notify with old freq in case we failed to change
- * frequency
- */
- if (retval)
- freqs.new = freqs.old;
-
- cpufreq_notify_transition(policy, &freqs,
- CPUFREQ_POSTCHANGE);
- }
+ if (notify)
+ cpufreq_notify_post_transition(policy, &freqs, retval);
}
out:
--
1.7.12.rc2.18.g61b472e
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH V2 3/5] cpufreq: pcc: send new set of notification for transition failures
2013-12-02 5:34 [PATCH V2 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Viresh Kumar
2013-12-02 5:34 ` [PATCH V2 2/5] cpufreq: send new set of notification for transition failures Viresh Kumar
@ 2013-12-02 5:34 ` Viresh Kumar
2013-12-02 5:34 ` [PATCH V2 4/5] cpufreq: powernow-k8: " Viresh Kumar
` (2 subsequent siblings)
4 siblings, 0 replies; 6+ messages in thread
From: Viresh Kumar @ 2013-12-02 5:34 UTC (permalink / raw)
To: rjw; +Cc: linaro-kernel, patches, cpufreq, linux-pm, linux-kernel,
Viresh Kumar
In the current code, if we fail during a frequency transition we simply send the
POSTCHANGE notification with old frequency. This isn't enough.
One of the core user of these notifications is the code responsible for keeping
loops_per_jiffy aligned with frequency change. And mostly it is written as:
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
update-loops-per-jiffy...
}
So, suppose we are changing to a higher frequency and failed during transition,
then following will happen:
- CPUFREQ_PRECHANGE notification with freq-new > freq-old
- CPUFREQ_POSTCHANGE notification with freq-new == freq-old
The first one will update loops_per_jiffy and second one will do nothing. Even
if we send the 2nd notification by exchanging values of freq-new and old, some
users of these notifications might get unstable.
This can be fixed by simply calling cpufreq_notify_post_transition() with error
code and this routine will take care of sending notifications in correct order.
Also it fills freqs.old before starting the first notification, this was missing
since ever.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/cpufreq/pcc-cpufreq.c | 18 +++++++-----------
1 file changed, 7 insertions(+), 11 deletions(-)
diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c
index e2b4f40..1c0f106 100644
--- a/drivers/cpufreq/pcc-cpufreq.c
+++ b/drivers/cpufreq/pcc-cpufreq.c
@@ -213,6 +213,7 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy,
cpu, target_freq,
(pcch_virt_addr + pcc_cpu_data->input_offset));
+ freqs.old = policy->cur;
freqs.new = target_freq;
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
@@ -228,25 +229,20 @@ static int pcc_cpufreq_target(struct cpufreq_policy *policy,
memset_io((pcch_virt_addr + pcc_cpu_data->input_offset), 0, BUF_SZ);
status = ioread16(&pcch_hdr->status);
+ iowrite16(0, &pcch_hdr->status);
+
+ cpufreq_notify_post_transition(policy, &freqs, status != CMD_COMPLETE);
+ spin_unlock(&pcc_lock);
+
if (status != CMD_COMPLETE) {
pr_debug("target: FAILED for cpu %d, with status: 0x%x\n",
cpu, status);
- goto cmd_incomplete;
+ return -EINVAL;
}
- iowrite16(0, &pcch_hdr->status);
- cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
pr_debug("target: was SUCCESSFUL for cpu %d\n", cpu);
- spin_unlock(&pcc_lock);
return 0;
-
-cmd_incomplete:
- freqs.new = freqs.old;
- cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
- iowrite16(0, &pcch_hdr->status);
- spin_unlock(&pcc_lock);
- return -EINVAL;
}
static int pcc_get_offset(int cpu)
--
1.7.12.rc2.18.g61b472e
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH V2 4/5] cpufreq: powernow-k8: send new set of notification for transition failures
2013-12-02 5:34 [PATCH V2 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Viresh Kumar
2013-12-02 5:34 ` [PATCH V2 2/5] cpufreq: send new set of notification for transition failures Viresh Kumar
2013-12-02 5:34 ` [PATCH V2 3/5] cpufreq: pcc: " Viresh Kumar
@ 2013-12-02 5:34 ` Viresh Kumar
2013-12-02 5:34 ` [PATCH V2 5/5] cpufreq: unicore2: " Viresh Kumar
2014-01-06 1:16 ` [PATCH V2 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Rafael J. Wysocki
4 siblings, 0 replies; 6+ messages in thread
From: Viresh Kumar @ 2013-12-02 5:34 UTC (permalink / raw)
To: rjw; +Cc: linaro-kernel, patches, cpufreq, linux-pm, linux-kernel,
Viresh Kumar
In the current code, if we fail during a frequency transition we simply send the
POSTCHANGE notification with old frequency. This isn't enough.
One of the core user of these notifications is the code responsible for keeping
loops_per_jiffy aligned with frequency change. And mostly it is written as:
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
update-loops-per-jiffy...
}
So, suppose we are changing to a higher frequency and failed during transition,
then following will happen:
- CPUFREQ_PRECHANGE notification with freq-new > freq-old
- CPUFREQ_POSTCHANGE notification with freq-new == freq-old
The first one will update loops_per_jiffy and second one will do nothing. Even
if we send the 2nd notification by exchanging values of freq-new and old, some
users of these notifications might get unstable.
This can be fixed by simply calling cpufreq_notify_post_transition() with error
code and this routine will take care of sending notifications in correct order.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/cpufreq/powernow-k8.c | 7 +------
1 file changed, 1 insertion(+), 6 deletions(-)
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index 0023c7d..e10b646 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -964,14 +964,9 @@ static int transition_frequency_fidvid(struct powernow_k8_data *data,
cpufreq_cpu_put(policy);
cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
res = transition_fid_vid(data, fid, vid);
- if (res)
- freqs.new = freqs.old;
- else
- freqs.new = find_khz_freq_from_fid(data->currfid);
+ cpufreq_notify_post_transition(policy, &freqs, res);
- cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
return res;
}
--
1.7.12.rc2.18.g61b472e
^ permalink raw reply related [flat|nested] 6+ messages in thread* [PATCH V2 5/5] cpufreq: unicore2: send new set of notification for transition failures
2013-12-02 5:34 [PATCH V2 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Viresh Kumar
` (2 preceding siblings ...)
2013-12-02 5:34 ` [PATCH V2 4/5] cpufreq: powernow-k8: " Viresh Kumar
@ 2013-12-02 5:34 ` Viresh Kumar
2014-01-06 1:16 ` [PATCH V2 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Rafael J. Wysocki
4 siblings, 0 replies; 6+ messages in thread
From: Viresh Kumar @ 2013-12-02 5:34 UTC (permalink / raw)
To: rjw; +Cc: linaro-kernel, patches, cpufreq, linux-pm, linux-kernel,
Viresh Kumar
In the current code, if we fail during a frequency transition we simply send the
POSTCHANGE notification with old frequency. This isn't enough.
One of the core user of these notifications is the code responsible for keeping
loops_per_jiffy aligned with frequency change. And mostly it is written as:
if ((val == CPUFREQ_PRECHANGE && freq->old < freq->new) ||
(val == CPUFREQ_POSTCHANGE && freq->old > freq->new)) {
update-loops-per-jiffy...
}
So, suppose we are changing to a higher frequency and failed during transition,
then following will happen:
- CPUFREQ_PRECHANGE notification with freq-new > freq-old
- CPUFREQ_POSTCHANGE notification with freq-new == freq-old
The first one will update loops_per_jiffy and second one will do nothing. Even
if we send the 2nd notification by exchanging values of freq-new and old, some
users of these notifications might get unstable.
This can be fixed by simply calling cpufreq_notify_post_transition() with error
code and this routine will take care of sending notifications in correct order.
Also it returns a proper error message in case frequency transition failed.
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---
drivers/cpufreq/unicore2-cpufreq.c | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
diff --git a/drivers/cpufreq/unicore2-cpufreq.c b/drivers/cpufreq/unicore2-cpufreq.c
index 951152f..99d280d6 100644
--- a/drivers/cpufreq/unicore2-cpufreq.c
+++ b/drivers/cpufreq/unicore2-cpufreq.c
@@ -38,19 +38,17 @@ static int ucv2_target(struct cpufreq_policy *policy,
unsigned int target_freq,
unsigned int relation)
{
- unsigned int cur = policy->cur;
struct cpufreq_freqs freqs;
+ int ret;
- cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
- if (!clk_set_rate(policy->clk, target_freq * 1000)) {
- freqs.old = cur;
- freqs.new = target_freq;
- }
+ freqs.old = policy->cur;
+ freqs.new = target_freq;
- cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
+ cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+ ret = clk_set_rate(policy->clk, target_freq * 1000);
+ cpufreq_notify_post_transition(policy, &freqs, ret);
- return 0;
+ return ret;
}
static int __init ucv2_cpu_init(struct cpufreq_policy *policy)
--
1.7.12.rc2.18.g61b472e
^ permalink raw reply related [flat|nested] 6+ messages in thread* Re: [PATCH V2 1/5] cpufreq: Introduce cpufreq_notify_post_transition()
2013-12-02 5:34 [PATCH V2 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Viresh Kumar
` (3 preceding siblings ...)
2013-12-02 5:34 ` [PATCH V2 5/5] cpufreq: unicore2: " Viresh Kumar
@ 2014-01-06 1:16 ` Rafael J. Wysocki
4 siblings, 0 replies; 6+ messages in thread
From: Rafael J. Wysocki @ 2014-01-06 1:16 UTC (permalink / raw)
To: Viresh Kumar; +Cc: linaro-kernel, patches, cpufreq, linux-pm, linux-kernel
On Monday, December 02, 2013 11:04:12 AM Viresh Kumar wrote:
> This introduces another routine cpufreq_notify_post_transition() which can be
> used to send POSTCHANGE notification for new freq with or without both
> {PRE|POST}CHANGE notifications for last freq. This is useful at multiple places,
> specially for sending transition failure notifications.
>
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
I've queued this series up for 3.14, but I folded patches [3-5/5] into [2/5]
(and needed to rebase the unicore2 changes).
Every time you want to copy-paste the changelog from one patch to another
(please don't do that any more) you should rather think about sending a
combination of the two as one patch.
Thanks!
> ---
>
> V1->V2:
> - Not required to push it for 3.13 anymore and can go in 3.14.
> - Rebased over following patchset as there were conflicts in unicore2 driver if
> following patchset is applied first (which should be the case):
> https://lkml.org/lkml/2013/10/30/553 (create cpufreq_generic_get() routine)
>
> drivers/cpufreq/cpufreq.c | 14 ++++++++++++++
> include/linux/cpufreq.h | 2 ++
> 2 files changed, 16 insertions(+)
>
> diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
> index 5e27def..3b877d4 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -338,6 +338,20 @@ void cpufreq_notify_transition(struct cpufreq_policy *policy,
> }
> EXPORT_SYMBOL_GPL(cpufreq_notify_transition);
>
> +/* Do post notifications when there are chances that transition has failed */
> +void cpufreq_notify_post_transition(struct cpufreq_policy *policy,
> + struct cpufreq_freqs *freqs, int transition_failed)
> +{
> + cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE);
> + if (!transition_failed)
> + return;
> +
> + swap(freqs->old, freqs->new);
> + cpufreq_notify_transition(policy, freqs, CPUFREQ_PRECHANGE);
> + cpufreq_notify_transition(policy, freqs, CPUFREQ_POSTCHANGE);
> +}
> +EXPORT_SYMBOL_GPL(cpufreq_notify_post_transition);
> +
>
> /*********************************************************************
> * SYSFS INTERFACE *
> diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h
> index 276e646..b26bfab 100644
> --- a/include/linux/cpufreq.h
> +++ b/include/linux/cpufreq.h
> @@ -316,6 +316,8 @@ int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list);
>
> void cpufreq_notify_transition(struct cpufreq_policy *policy,
> struct cpufreq_freqs *freqs, unsigned int state);
> +void cpufreq_notify_post_transition(struct cpufreq_policy *policy,
> + struct cpufreq_freqs *freqs, int transition_failed);
>
> #else /* CONFIG_CPU_FREQ */
> static inline int cpufreq_register_notifier(struct notifier_block *nb,
>
--
I speak only for myself.
Rafael J. Wysocki, Intel Open Source Technology Center.
^ permalink raw reply [flat|nested] 6+ messages in thread