linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] regulator: core: if voltage scaling fails, restore original
@ 2012-12-12 11:45 Paolo Pisati
  2012-12-12 11:45 ` [PATCH] regulator: core: if voltage scaling fails, restore original voltage values Paolo Pisati
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Paolo Pisati @ 2012-12-12 11:45 UTC (permalink / raw)
  To: linux-omap
  Cc: Paul Walmsley, Liam Girdwood, Mark Brown, linux-kernel, Paolo Pisati

And after a second look it's clear what's going on:

[...]
[    5.575744] cpu cpu0: cpufreq-omap: 300 MHz, -1 mV --> 800 MHz, 1325 mV
[    5.582946] voltdm_scale: No voltage scale API registered for vdd_mpu_iva
[    5.590332] cpu cpu0: omap_target: unable to scale voltage up.
[1]
[    5.596649] notification 1 of frequency transition to 300000 kHz
[    5.603179] FREQ: 300000 - CPU: 0
[    5.606597] governor: change or update limits
[    5.611572] __cpufreq_governor for CPU 0, event 3
[    5.616699] setting to 800000 kHz because of event 3
[    5.622039] target for CPU 0: 800000 kHz, relation 1
[    5.627441] request for target 800000 kHz (relation: 1) for cpu 0
[    5.634063] target is 2 (800000 kHz, 2)
[    5.638183] notification 0 of frequency transition to 800000 kHz
[    5.644775] cpu cpu0: cpufreq-omap: 300 MHz, -1 mV --> 800 MHz, 1325 mV
[2]
[hangs here]

first time[1] it tries to ramp up frequency (and thus voltage),
regulator_set_voltage() returns an error and we exit:

omap-cpufreq.c::omap_target():

	...
    dev_dbg(mpu_dev, "cpufreq-omap: %u MHz, %ld mV --> %u MHz, %ld mV\n",
        freqs.old / 1000, volt_old ? volt_old / 1000 : -1,
        freqs.new / 1000, volt ? volt / 1000 : -1);

    /* scaling up?  scale voltage before frequency */
    if (mpu_reg && (freqs.new > freqs.old)) {
        r = regulator_set_voltage(mpu_reg, volt - tol, volt + tol);
        if (r < 0) {
            dev_warn(mpu_dev, "%s: unable to scale voltage up.\n",
                 __func__);
            freqs.new = freqs.old;
            goto done;
        }
    }

	ret = clk_set_rate(mpu_clk, freqs.new * 1000);
	...

but inside regulator_set_voltage(), we save the new regulator voltage before
actually ramping up:

core.c::regulator_set_voltage():
	...
    regulator->min_uV = min_uV;
    regulator->max_uV = max_uV;

    ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
    if (ret < 0)
        goto out2;

    ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);  <-- ERROR!!!
    if (ret < 0)
        goto out2;
	...


and by the time we try to change frequency again[2], regulator_set_voltage()
is a noop because it thinks we are already at the desired voltage:

core.c::regulator_set_voltage():

	...
    /* If we're setting the same range as last time the change
     * should be a noop (some cpufreq implementations use the same
     * voltage for multiple frequencies, for example).
     */
    if (regulator->min_uV == min_uV && regulator->max_uV == max_uV)
        goto out;
	...

and as a consequence, in omap_target(), we call clk_set_rate() with
the wrong voltage.

The attached patch restore the original regulator voltage values in case
of an error.

CCing stable@ since it predates 2.6.38rc1 when the noop optimization was
introduced:

commit 95a3c23ae620c1b4c499746e70f4034bdc067737
Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
Date:   Thu Dec 16 15:49:37 2010 +0000

    regulator: Optimise out noop voltage changes

Paolo Pisati (1):
  regulator: core: if voltage scaling fails, restore original voltage
    values

 drivers/regulator/core.c |   16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

-- 
1.7.10.4


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

* [PATCH] regulator: core: if voltage scaling fails, restore original voltage values
  2012-12-12 11:45 [PATCH] regulator: core: if voltage scaling fails, restore original Paolo Pisati
@ 2012-12-12 11:45 ` Paolo Pisati
  2012-12-12 18:13   ` Robert Nelson
  2012-12-13  5:06 ` [PATCH] regulator: core: if voltage scaling fails, restore original Paul Walmsley
  2012-12-13  5:15 ` Mark Brown
  2 siblings, 1 reply; 8+ messages in thread
From: Paolo Pisati @ 2012-12-12 11:45 UTC (permalink / raw)
  To: linux-omap
  Cc: Paul Walmsley, Liam Girdwood, Mark Brown, linux-kernel, Paolo Pisati

Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
---
 drivers/regulator/core.c |   16 ++++++++++++++--
 1 file changed, 14 insertions(+), 2 deletions(-)

diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index e872c8b..c347fd0 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -2250,6 +2250,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
 {
 	struct regulator_dev *rdev = regulator->rdev;
 	int ret = 0;
+	int old_min_uV, old_max_uV;
 
 	mutex_lock(&rdev->mutex);
 
@@ -2271,18 +2272,29 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
 	ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
 	if (ret < 0)
 		goto out;
+	
+	/* restore original values in case of error */
+	old_min_uV = regulator->min_uV;
+	old_max_uV = regulator->max_uV;
 	regulator->min_uV = min_uV;
 	regulator->max_uV = max_uV;
 
 	ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
 	if (ret < 0)
-		goto out;
+		goto out2;
 
 	ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
-
+	if (ret < 0)
+		goto out2;
+	
 out:
 	mutex_unlock(&rdev->mutex);
 	return ret;
+out2:
+	regulator->min_uV = old_min_uV;
+	regulator->max_uV = old_max_uV;
+	mutex_unlock(&rdev->mutex);
+	return ret;
 }
 EXPORT_SYMBOL_GPL(regulator_set_voltage);
 
-- 
1.7.10.4


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

* Re: [PATCH] regulator: core: if voltage scaling fails, restore original voltage values
  2012-12-12 11:45 ` [PATCH] regulator: core: if voltage scaling fails, restore original voltage values Paolo Pisati
@ 2012-12-12 18:13   ` Robert Nelson
  2012-12-12 19:00     ` Felipe Balbi
  0 siblings, 1 reply; 8+ messages in thread
From: Robert Nelson @ 2012-12-12 18:13 UTC (permalink / raw)
  To: Paolo Pisati; +Cc: linux-omap, linux-kernel

On Wed, Dec 12, 2012 at 5:45 AM, Paolo Pisati
<paolo.pisati@canonical.com> wrote:
> Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
> ---
>  drivers/regulator/core.c |   16 ++++++++++++++--
>  1 file changed, 14 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
> index e872c8b..c347fd0 100644
> --- a/drivers/regulator/core.c
> +++ b/drivers/regulator/core.c
> @@ -2250,6 +2250,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
>  {
>         struct regulator_dev *rdev = regulator->rdev;
>         int ret = 0;
> +       int old_min_uV, old_max_uV;
>
>         mutex_lock(&rdev->mutex);
>
> @@ -2271,18 +2272,29 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
>         ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
>         if (ret < 0)
>                 goto out;
> +
> +       /* restore original values in case of error */
> +       old_min_uV = regulator->min_uV;
> +       old_max_uV = regulator->max_uV;
>         regulator->min_uV = min_uV;
>         regulator->max_uV = max_uV;
>
>         ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
>         if (ret < 0)
> -               goto out;
> +               goto out2;
>
>         ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
> -
> +       if (ret < 0)
> +               goto out2;
> +
>  out:
>         mutex_unlock(&rdev->mutex);
>         return ret;
> +out2:
> +       regulator->min_uV = old_min_uV;
> +       regulator->max_uV = old_max_uV;
> +       mutex_unlock(&rdev->mutex);
> +       return ret;
>  }
>  EXPORT_SYMBOL_GPL(regulator_set_voltage);
>
> --
> 1.7.10.4

Nice! This fixes the 800Mhz lockup on bootup after a software reset we
were seeing on the Beagle xM's with v3.7.x/v3.6.x...

Tested-by: Robert Nelson <robertcnelson@gmail.com>

Regards,

-- 
Robert Nelson
http://www.rcn-ee.com/

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

* Re: [PATCH] regulator: core: if voltage scaling fails, restore original voltage values
  2012-12-12 18:13   ` Robert Nelson
@ 2012-12-12 19:00     ` Felipe Balbi
  0 siblings, 0 replies; 8+ messages in thread
From: Felipe Balbi @ 2012-12-12 19:00 UTC (permalink / raw)
  To: Robert Nelson; +Cc: Paolo Pisati, linux-omap, linux-kernel

[-- Attachment #1: Type: text/plain, Size: 2231 bytes --]

Hi,

On Wed, Dec 12, 2012 at 12:13:35PM -0600, Robert Nelson wrote:
> On Wed, Dec 12, 2012 at 5:45 AM, Paolo Pisati
> <paolo.pisati@canonical.com> wrote:
> > Signed-off-by: Paolo Pisati <paolo.pisati@canonical.com>
> > ---
> >  drivers/regulator/core.c |   16 ++++++++++++++--
> >  1 file changed, 14 insertions(+), 2 deletions(-)
> >
> > diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
> > index e872c8b..c347fd0 100644
> > --- a/drivers/regulator/core.c
> > +++ b/drivers/regulator/core.c
> > @@ -2250,6 +2250,7 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
> >  {
> >         struct regulator_dev *rdev = regulator->rdev;
> >         int ret = 0;
> > +       int old_min_uV, old_max_uV;
> >
> >         mutex_lock(&rdev->mutex);
> >
> > @@ -2271,18 +2272,29 @@ int regulator_set_voltage(struct regulator *regulator, int min_uV, int max_uV)
> >         ret = regulator_check_voltage(rdev, &min_uV, &max_uV);
> >         if (ret < 0)
> >                 goto out;
> > +
> > +       /* restore original values in case of error */
> > +       old_min_uV = regulator->min_uV;
> > +       old_max_uV = regulator->max_uV;
> >         regulator->min_uV = min_uV;
> >         regulator->max_uV = max_uV;
> >
> >         ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
> >         if (ret < 0)
> > -               goto out;
> > +               goto out2;
> >
> >         ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);
> > -
> > +       if (ret < 0)
> > +               goto out2;
> > +
> >  out:
> >         mutex_unlock(&rdev->mutex);
> >         return ret;
> > +out2:
> > +       regulator->min_uV = old_min_uV;
> > +       regulator->max_uV = old_max_uV;
> > +       mutex_unlock(&rdev->mutex);
> > +       return ret;
> >  }
> >  EXPORT_SYMBOL_GPL(regulator_set_voltage);
> >
> > --
> > 1.7.10.4
> 
> Nice! This fixes the 800Mhz lockup on bootup after a software reset we
> were seeing on the Beagle xM's with v3.7.x/v3.6.x...
> 
> Tested-by: Robert Nelson <robertcnelson@gmail.com>

if this fixes a boot lockup with older kernel, I believe this deserves a
Cc: stable@vger.kernel.org.

-- 
balbi

[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 836 bytes --]

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

* Re: [PATCH] regulator: core: if voltage scaling fails, restore original
  2012-12-12 11:45 [PATCH] regulator: core: if voltage scaling fails, restore original Paolo Pisati
  2012-12-12 11:45 ` [PATCH] regulator: core: if voltage scaling fails, restore original voltage values Paolo Pisati
@ 2012-12-13  5:06 ` Paul Walmsley
  2012-12-13  5:08   ` Paul Walmsley
  2012-12-13  5:15 ` Mark Brown
  2 siblings, 1 reply; 8+ messages in thread
From: Paul Walmsley @ 2012-12-13  5:06 UTC (permalink / raw)
  To: Paolo Pisati; +Cc: linux-omap, Liam Girdwood, Mark Brown, linux-kernel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 801 bytes --]

On Wed, 12 Dec 2012, Paolo Pisati wrote:

> but inside regulator_set_voltage(), we save the new regulator voltage before
> actually ramping up:
> 
> core.c::regulator_set_voltage():
> 	...
>     regulator->min_uV = min_uV;
>     regulator->max_uV = max_uV;
> 
>     ret = regulator_check_consumers(rdev, &min_uV, &max_uV);
>     if (ret < 0)
>         goto out2;
> 
>     ret = _regulator_do_set_voltage(rdev, min_uV, max_uV);  <-- ERROR!!!
>     if (ret < 0)
>         goto out2;
> 	...

I'm not too familiar with this code.  But isn't this where the bug is, 
rather than in that optimization commit you mentioned?  Seems to me, 
naïvely, that in the above code, regulator->min_uV and regulator->max_uV 
should be set only after _regulator_do_set_voltage() succeeds?


- Paul

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

* Re: [PATCH] regulator: core: if voltage scaling fails, restore original
  2012-12-13  5:06 ` [PATCH] regulator: core: if voltage scaling fails, restore original Paul Walmsley
@ 2012-12-13  5:08   ` Paul Walmsley
  0 siblings, 0 replies; 8+ messages in thread
From: Paul Walmsley @ 2012-12-13  5:08 UTC (permalink / raw)
  To: Paolo Pisati; +Cc: linux-omap, Liam Girdwood, Mark Brown, linux-kernel

[-- Attachment #1: Type: TEXT/PLAIN, Size: 311 bytes --]

On Thu, 13 Dec 2012, Paul Walmsley wrote:

> Seems to me, naïvely, that in the above code, regulator->min_uV and 
> regulator->max_uV should be set only after _regulator_do_set_voltage() 
> succeeds?

Eh, never mind.  Looks like you took a similar strategy in the subsequent 
patch you sent..


- Paul

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

* Re: [PATCH] regulator: core: if voltage scaling fails, restore original
  2012-12-12 11:45 [PATCH] regulator: core: if voltage scaling fails, restore original Paolo Pisati
  2012-12-12 11:45 ` [PATCH] regulator: core: if voltage scaling fails, restore original voltage values Paolo Pisati
  2012-12-13  5:06 ` [PATCH] regulator: core: if voltage scaling fails, restore original Paul Walmsley
@ 2012-12-13  5:15 ` Mark Brown
  2012-12-13  8:58   ` Paolo Pisati
  2 siblings, 1 reply; 8+ messages in thread
From: Mark Brown @ 2012-12-13  5:15 UTC (permalink / raw)
  To: Paolo Pisati; +Cc: linux-omap, Paul Walmsley, Liam Girdwood, linux-kernel

On Wed, Dec 12, 2012 at 12:45:52PM +0100, Paolo Pisati wrote:
> And after a second look it's clear what's going on:

After a second look at what?  You've not provided any context, I've no
idea what you're talking about here.

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

* Re: [PATCH] regulator: core: if voltage scaling fails, restore original
  2012-12-13  5:15 ` Mark Brown
@ 2012-12-13  8:58   ` Paolo Pisati
  0 siblings, 0 replies; 8+ messages in thread
From: Paolo Pisati @ 2012-12-13  8:58 UTC (permalink / raw)
  To: Mark Brown
  Cc: Paolo Pisati, linux-omap, Paul Walmsley, Liam Girdwood, linux-kernel

On Thu, Dec 13, 2012 at 05:15:33AM +0000, Mark Brown wrote:
> On Wed, Dec 12, 2012 at 12:45:52PM +0100, Paolo Pisati wrote:
> > And after a second look it's clear what's going on:
> 
> After a second look at what?  You've not provided any context, I've no
> idea what you're talking about here.

forgot the --in-reply-to=..., i'll resend as a new thread.

-- 
bye,
p.

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

end of thread, other threads:[~2012-12-13  8:58 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-12-12 11:45 [PATCH] regulator: core: if voltage scaling fails, restore original Paolo Pisati
2012-12-12 11:45 ` [PATCH] regulator: core: if voltage scaling fails, restore original voltage values Paolo Pisati
2012-12-12 18:13   ` Robert Nelson
2012-12-12 19:00     ` Felipe Balbi
2012-12-13  5:06 ` [PATCH] regulator: core: if voltage scaling fails, restore original Paul Walmsley
2012-12-13  5:08   ` Paul Walmsley
2012-12-13  5:15 ` Mark Brown
2012-12-13  8:58   ` Paolo Pisati

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).