linux-pm.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/5] cpufreq: Introduce cpufreq_notify_post_transition()
@ 2013-11-30 15:56 Viresh Kumar
  2013-11-30 15:56 ` [PATCH 2/5] cpufreq: send new set of notification for transition failures Viresh Kumar
                   ` (4 more replies)
  0 siblings, 5 replies; 7+ messages in thread
From: Viresh Kumar @ 2013-11-30 15:56 UTC (permalink / raw)
  To: rjw; +Cc: linaro-kernel, patches, cpufreq, linux-pm, linux-kernel,
	Viresh Kumar

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 in case of failures. This is useful
at multiple places, specially for sending transition failure notifications.

Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
---

Hi Rafael,

Please see if you want to take it for 3.13 or 14, as this fixes bugs which are
partly introduced in 3.13..

 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 606224a..a862aa9 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -324,6 +324,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 ee5fe9d..57e48db 100644
--- a/include/linux/cpufreq.h
+++ b/include/linux/cpufreq.h
@@ -314,6 +314,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,
-- 
1.7.12.rc2.18.g61b472e


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

* [PATCH 2/5] cpufreq: send new set of notification for transition failures
  2013-11-30 15:56 [PATCH 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Viresh Kumar
@ 2013-11-30 15:56 ` Viresh Kumar
  2013-11-30 15:56 ` [PATCH 3/5] cpufreq: pcc: " Viresh Kumar
                   ` (3 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Viresh Kumar @ 2013-11-30 15:56 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 a862aa9..557bb49 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -1764,17 +1764,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] 7+ messages in thread

* [PATCH 3/5] cpufreq: pcc: send new set of notification for transition failures
  2013-11-30 15:56 [PATCH 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Viresh Kumar
  2013-11-30 15:56 ` [PATCH 2/5] cpufreq: send new set of notification for transition failures Viresh Kumar
@ 2013-11-30 15:56 ` Viresh Kumar
  2013-11-30 15:56 ` [PATCH 4/5] cpufreq: powernow-k8: " Viresh Kumar
                   ` (2 subsequent siblings)
  4 siblings, 0 replies; 7+ messages in thread
From: Viresh Kumar @ 2013-11-30 15:56 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] 7+ messages in thread

* [PATCH 4/5] cpufreq: powernow-k8: send new set of notification for transition failures
  2013-11-30 15:56 [PATCH 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Viresh Kumar
  2013-11-30 15:56 ` [PATCH 2/5] cpufreq: send new set of notification for transition failures Viresh Kumar
  2013-11-30 15:56 ` [PATCH 3/5] cpufreq: pcc: " Viresh Kumar
@ 2013-11-30 15:56 ` Viresh Kumar
  2013-11-30 15:56 ` [PATCH 5/5] cpufreq: unicore2: " Viresh Kumar
  2013-11-30 20:20 ` [PATCH 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Rafael J. Wysocki
  4 siblings, 0 replies; 7+ messages in thread
From: Viresh Kumar @ 2013-11-30 15:56 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] 7+ messages in thread

* [PATCH 5/5] cpufreq: unicore2: send new set of notification for transition failures
  2013-11-30 15:56 [PATCH 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Viresh Kumar
                   ` (2 preceding siblings ...)
  2013-11-30 15:56 ` [PATCH 4/5] cpufreq: powernow-k8: " Viresh Kumar
@ 2013-11-30 15:56 ` Viresh Kumar
  2013-11-30 20:20 ` [PATCH 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Rafael J. Wysocki
  4 siblings, 0 replies; 7+ messages in thread
From: Viresh Kumar @ 2013-11-30 15:56 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 | 15 +++++++--------
 1 file changed, 7 insertions(+), 8 deletions(-)

diff --git a/drivers/cpufreq/unicore2-cpufreq.c b/drivers/cpufreq/unicore2-cpufreq.c
index 653ae29..3e79dae 100644
--- a/drivers/cpufreq/unicore2-cpufreq.c
+++ b/drivers/cpufreq/unicore2-cpufreq.c
@@ -49,17 +49,16 @@ static int ucv2_target(struct cpufreq_policy *policy,
 	unsigned int cur = ucv2_getspeed(0);
 	struct cpufreq_freqs freqs;
 	struct clk *mclk = clk_get(NULL, "MAIN_CLK");
+	int ret;
 
-	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
-
-	if (!clk_set_rate(mclk, target_freq * 1000)) {
-		freqs.old = cur;
-		freqs.new = target_freq;
-	}
+	freqs.old = cur;
+	freqs.new = target_freq;
 
-	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);
+	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
+	ret = clk_set_rate(mclk, 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] 7+ messages in thread

* Re: [PATCH 1/5] cpufreq: Introduce cpufreq_notify_post_transition()
  2013-11-30 15:56 [PATCH 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Viresh Kumar
                   ` (3 preceding siblings ...)
  2013-11-30 15:56 ` [PATCH 5/5] cpufreq: unicore2: " Viresh Kumar
@ 2013-11-30 20:20 ` Rafael J. Wysocki
  2013-12-01  2:48   ` Viresh Kumar
  4 siblings, 1 reply; 7+ messages in thread
From: Rafael J. Wysocki @ 2013-11-30 20:20 UTC (permalink / raw)
  To: Viresh Kumar; +Cc: linaro-kernel, patches, cpufreq, linux-pm, linux-kernel

On Saturday, November 30, 2013 09:26:19 PM 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 in case of failures. This is useful
> at multiple places, specially for sending transition failure notifications.
> 
> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
> ---
> 
> Hi Rafael,
> 
> Please see if you want to take it for 3.13 or 14, as this fixes bugs which are
> partly introduced in 3.13..

Which ones?

Rafael


>  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 606224a..a862aa9 100644
> --- a/drivers/cpufreq/cpufreq.c
> +++ b/drivers/cpufreq/cpufreq.c
> @@ -324,6 +324,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 ee5fe9d..57e48db 100644
> --- a/include/linux/cpufreq.h
> +++ b/include/linux/cpufreq.h
> @@ -314,6 +314,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] 7+ messages in thread

* Re: [PATCH 1/5] cpufreq: Introduce cpufreq_notify_post_transition()
  2013-11-30 20:20 ` [PATCH 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Rafael J. Wysocki
@ 2013-12-01  2:48   ` Viresh Kumar
  0 siblings, 0 replies; 7+ messages in thread
From: Viresh Kumar @ 2013-12-01  2:48 UTC (permalink / raw)
  To: Rafael J. Wysocki
  Cc: Lists linaro-kernel, Patch Tracking, cpufreq@vger.kernel.org,
	linux-pm@vger.kernel.org, Linux Kernel Mailing List

On 1 December 2013 01:50, Rafael J. Wysocki <rjw@rjwysocki.net> wrote:
> On Saturday, November 30, 2013 09:26:19 PM 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 in case of failures. This is useful
>> at multiple places, specially for sending transition failure notifications.
>>
>> Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>
>> ---
>>
>> Hi Rafael,
>>
>> Please see if you want to take it for 3.13 or 14, as this fixes bugs which are
>> partly introduced in 3.13..
>
> Which ones?

Patch:

commit d4019f0a92ab802f385cc9c8ad3ab7b5449712cb
Author: Viresh Kumar <viresh.kumar@linaro.org>
Date:   Wed Aug 14 19:38:24 2013 +0530

    cpufreq: move freq change notifications to cpufreq core

adds:

diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
+               retval = cpufreq_driver->target_index(policy, index);
+               if (retval)
+                       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);
+               }


And I thought it might go in 3.13, but surely it doesn't fix any
obvious kernel crashes. It only fixes stuff when target_index() fails.

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

end of thread, other threads:[~2013-12-01  2:48 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2013-11-30 15:56 [PATCH 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Viresh Kumar
2013-11-30 15:56 ` [PATCH 2/5] cpufreq: send new set of notification for transition failures Viresh Kumar
2013-11-30 15:56 ` [PATCH 3/5] cpufreq: pcc: " Viresh Kumar
2013-11-30 15:56 ` [PATCH 4/5] cpufreq: powernow-k8: " Viresh Kumar
2013-11-30 15:56 ` [PATCH 5/5] cpufreq: unicore2: " Viresh Kumar
2013-11-30 20:20 ` [PATCH 1/5] cpufreq: Introduce cpufreq_notify_post_transition() Rafael J. Wysocki
2013-12-01  2:48   ` Viresh Kumar

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).