RE: [PATCH 1/1] PM / Runtime: let rpm_resume fail if rpm disabled and device suspended.

2014-06-19 Thread Allen Yu
On Thursday, June 19, 2014, Rafael J. Wysocki wrote:
> On Thursday, June 19, 2014 04:23:29 PM Allen Yu wrote:
> > On Thursday, June 19, 2014, Rafael J. Wysocki wrote:
> > > On Wednesday, June 18, 2014 11:30:51 AM Alan Stern wrote:
> > > > On Tue, 17 Jun 2014, Rafael J. Wysocki wrote:
> > > >
> > > > > On Tuesday, June 17, 2014 10:37:03 PM Rafael J. Wysocki wrote:
> > > > > > On Tuesday, June 17, 2014 10:26:14 PM Rafael J. Wysocki wrote:
> > > > > > > On Tuesday, June 17, 2014 10:11:32 AM Alan Stern wrote:
> > > > > > > > On Mon, 16 Jun 2014, Rafael J. Wysocki wrote:
> > > > > > > >
> > > > > > > > > > For reasons having nothing to do with Allen's
> > > > > > > > > > suggested change, I wonder if we shouldn't replace
> > > > > > > > > > this line with
> > > something like:
> > > > > > > > > >
> > > > > > > > > > -   else if (dev->power.disable_depth == 1 && dev-
> > > >power.is_suspended
> > > > > > > > > > +   else if (dev->power.disable > 0 &&
> > > > > > > > > > +!dev->power.is_suspended
> > > > > > > > > > && dev->power.runtime_status == RPM_ACTIVE)
> > > > > > > > > > retval = 1;
> > > > > > > > > >
> > > > > > > > > > It seems that I've been bitten by this several times in the
> past.
> > > > > > > > > > When a device is disabled for runtime PM, and more or
> > > > > > > > > > less permanently stuck in the RPM_ACTIVE state, calls
> > > > > > > > > > to
> > > > > > > > > > pm_runtime_resume() or
> > > > > > > > > > pm_runtime_get_sync() shouldn't fail.
> > > > > > > > > >
> > > > > > > > > > For example, suppose some devices of a certain type
> > > > > > > > > > support runtime power management but others don't.  We
> > > > > > > > > > naturally want to call
> > > > > > > > > > pm_runtime_disable() for the ones that don't.  But we
> > > > > > > > > > also want the same driver to work for all the devices,
> > > > > > > > > > which means that
> > > > > > > > > > pm_runtime_get_sync() should return success --
> > > > > > > > > > otherwise the driver will think that something has gone
> wrong.
> > > > > > > > > >
> > > > > > > > > > Rafael, what do you think?
> > > > > > > > >
> > > > > > > > > That condition is there specifically to take care of the
> > > > > > > > > system suspend code path.  It means that if runtime PM
> > > > > > > > > is disabled, but it only has been disabled by the system
> > > > > > > > > suspend code path, we should treat the device as "active" (ie.
> > > return 1).  That won't work after the proposed change.
> > > > > > > >
> > > > > > > > Ah, yes, quite true.  Okay, suppose we replace that line with 
> > > > > > > > just:
> > > > > > > >
> > > > > > > > +   else if (dev->power.disable > 0
> > > > > > > >
> > > > > > > > > I guess drivers that want to work with devices where
> > > > > > > > > runtime PM may be disabled can just check the return
> > > > > > > > > value of
> > > rpm_resume() for -EACCES?
> > > > > > > >
> > > > > > > > They could, but it's extra work and it's extremely easy to
> > > > > > > > forget about.  I'd prefer not to do things that way.
> > > > > > >
> > > > > > > In that case we need to audit all code that checks the
> > > > > > > return value of
> > > > > > > __pm_runtime_resume() to verify that it doesn't depend on
> > > > > > > the current behavior in any way.  It shouldn't, but still.
> > > > > > >
> > > > > > > Also we prob

RE: [PATCH 1/1] PM / Runtime: let rpm_resume fail if rpm disabled and device suspended.

2014-06-19 Thread Allen Yu
e if dev->power.is_suspended flag is set and 
runtime_status is RPM_ACTIVE? Is it a state like "suspended but still can be 
accessed"? 

I'm just afraid the existing code would cause a device hang if we allow it to 
be accessed even though it's suspended (at this point RPM_ACTIVE could be 
meaningless). I don't understand the original motivation of these code. If it's 
a valid case, most likely it should be handled in the specific device driver 
instead of the PM core.

> 
> > > > Perhaps it'd be better to rework __pm_runtime_resume() to convert
> > > > the -EACCES return value from rpm_resume() into 0 if RPM_GET_PUT is
> set?
> > >
> > > Or do something like this?
> > >
> > > ---
> > >  drivers/base/power/runtime.c |3 ++-
> > >  1 file changed, 2 insertions(+), 1 deletion(-)
> > >
> > > Index: linux-pm/drivers/base/power/runtime.c
> > >
> ==
> =
> > > --- linux-pm.orig/drivers/base/power/runtime.c
> > > +++ linux-pm/drivers/base/power/runtime.c
> > > @@ -608,7 +608,8 @@ static int rpm_resume(struct device *dev
> > >   repeat:
> > >   if (dev->power.runtime_error)
> > >   retval = -EINVAL;
> > > - else if (dev->power.disable_depth == 1 && dev-
> >power.is_suspended
> > > + else if (((dev->power.disable_depth > 0 && (rpmflags &
> RPM_GET_PUT))
> > > + || (dev->power.disable_depth == 1 && dev-
> >power.is_suspended))
> > >   && dev->power.runtime_status == RPM_ACTIVE)
> > >   retval = 1;
> > >   else if (dev->power.disable_depth > 0)
> >
> > So pm_runtime_resume() and pm_request_resume() would still fail, but
> > pm_runtime_get() and pm_runtime_get_sync() would work?  I'm not sure
> > about the reason for this distinction.
> 
> The meaning of pm_runtime_get()/pm_runtime_get_sync() is "prevent the
> device from being suspended from now on and resume it if necessary" while
> "runtime PM disabled and runtime_status == RPM_ACTIVE" may be
> interpreted as "not necessary to resume", so it is reasonable to special case
> this particular situation for these particular routines IMHO.

As Rafael mentioned above that runtime_sataus is not meaningful if runtime PM 
is disabled, so shouldn't we avoid using the runtime_staus here and instead use 
dev->power.is_suspended only to decide the return value?

@@ -608,11 +608,13 @@ static int rpm_resume(struct device *dev, int rpmflags)
  repeat:
if (dev->power.runtime_error)
retval = -EINVAL;
-   else if (dev->power.disable_depth == 1 && dev->power.is_suspended
-   && dev->power.runtime_status == RPM_ACTIVE)
-   retval = 1;
-   else if (dev->power.disable_depth > 0)
-   retval = -EACCES;
+   else if (dev->power.disable_depth > 0) {
+   if (!dev->power.is_suspended)
+   retval = 1;
+   else
+   retval = -EACCES;
+   }
+
if (retval)
goto out;

However, this requires us to make sure device is in full functional state if 
it's not suspended before disabling runtime PM, just like the case runtime PM 
is not configured at all. And also requires device suspend routine to check 
dev->power.usage_count before suspending device.

Thanks,
Allen Yu
N�r��yb�X��ǧv�^�)޺{.n�+{zX����ܨ}���Ơz�:+v���zZ+��+zf���h���~i���z��w���?�&�)ߢf��^jǫy�m��@A�a���
0��h���i

RE: [PATCH 1/1] PM / Runtime: let rpm_resume fail if rpm disabled and device suspended.

2014-06-19 Thread Allen Yu
 being suspended from now on and resume it if necessary while
 runtime PM disabled and runtime_status == RPM_ACTIVE may be
 interpreted as not necessary to resume, so it is reasonable to special case
 this particular situation for these particular routines IMHO.

As Rafael mentioned above that runtime_sataus is not meaningful if runtime PM 
is disabled, so shouldn't we avoid using the runtime_staus here and instead use 
dev-power.is_suspended only to decide the return value?

@@ -608,11 +608,13 @@ static int rpm_resume(struct device *dev, int rpmflags)
  repeat:
if (dev-power.runtime_error)
retval = -EINVAL;
-   else if (dev-power.disable_depth == 1  dev-power.is_suspended
-dev-power.runtime_status == RPM_ACTIVE)
-   retval = 1;
-   else if (dev-power.disable_depth  0)
-   retval = -EACCES;
+   else if (dev-power.disable_depth  0) {
+   if (!dev-power.is_suspended)
+   retval = 1;
+   else
+   retval = -EACCES;
+   }
+
if (retval)
goto out;

However, this requires us to make sure device is in full functional state if 
it's not suspended before disabling runtime PM, just like the case runtime PM 
is not configured at all. And also requires device suspend routine to check 
dev-power.usage_count before suspending device.

Thanks,
Allen Yu
N�r��yb�X��ǧv�^�)޺{.n�+{zX����ܨ}���Ơz�j:+v���zZ+��+zf���h���~i���z��w���?��)ߢf��^jǫy�m��@A�a���
0��h���i

RE: [PATCH 1/1] PM / Runtime: let rpm_resume fail if rpm disabled and device suspended.

2014-06-19 Thread Allen Yu
On Thursday, June 19, 2014, Rafael J. Wysocki wrote:
 On Thursday, June 19, 2014 04:23:29 PM Allen Yu wrote:
  On Thursday, June 19, 2014, Rafael J. Wysocki wrote:
   On Wednesday, June 18, 2014 11:30:51 AM Alan Stern wrote:
On Tue, 17 Jun 2014, Rafael J. Wysocki wrote:
   
 On Tuesday, June 17, 2014 10:37:03 PM Rafael J. Wysocki wrote:
  On Tuesday, June 17, 2014 10:26:14 PM Rafael J. Wysocki wrote:
   On Tuesday, June 17, 2014 10:11:32 AM Alan Stern wrote:
On Mon, 16 Jun 2014, Rafael J. Wysocki wrote:
   
  For reasons having nothing to do with Allen's
  suggested change, I wonder if we shouldn't replace
  this line with
   something like:
 
  -   else if (dev-power.disable_depth == 1  dev-
   power.is_suspended
  +   else if (dev-power.disable  0 
  +!dev-power.is_suspended
   dev-power.runtime_status == RPM_ACTIVE)
  retval = 1;
 
  It seems that I've been bitten by this several times in the
 past.
  When a device is disabled for runtime PM, and more or
  less permanently stuck in the RPM_ACTIVE state, calls
  to
  pm_runtime_resume() or
  pm_runtime_get_sync() shouldn't fail.
 
  For example, suppose some devices of a certain type
  support runtime power management but others don't.  We
  naturally want to call
  pm_runtime_disable() for the ones that don't.  But we
  also want the same driver to work for all the devices,
  which means that
  pm_runtime_get_sync() should return success --
  otherwise the driver will think that something has gone
 wrong.
 
  Rafael, what do you think?

 That condition is there specifically to take care of the
 system suspend code path.  It means that if runtime PM
 is disabled, but it only has been disabled by the system
 suspend code path, we should treat the device as active (ie.
   return 1).  That won't work after the proposed change.
   
Ah, yes, quite true.  Okay, suppose we replace that line with 
just:
   
+   else if (dev-power.disable  0
   
 I guess drivers that want to work with devices where
 runtime PM may be disabled can just check the return
 value of
   rpm_resume() for -EACCES?
   
They could, but it's extra work and it's extremely easy to
forget about.  I'd prefer not to do things that way.
  
   In that case we need to audit all code that checks the
   return value of
   __pm_runtime_resume() to verify that it doesn't depend on
   the current behavior in any way.  It shouldn't, but still.
  
   Also we probably should drop the -EACCES return value from
   rpm_resume() in the same patch, because it specifically only
   covers the dev-power.disable  0 case (which BTW is
   consistent with the suspend side of things, so I'm totally
   unsure about that being
   the right thing to do to be honest).
   
It's still the correct action with runtime PM is disabled and the
device's runtime_status isn't RPM_ACTIVE.
  
   Well, we used to have the notion that runtime_status is not
   meaningful for devices with dev-power.disable_depth greater than 0
   (except for the special case in the suspend code path where we know
   why it is greater than 0).  I think it was useful. :-)
 
  So what's the exact state of device if dev-power.is_suspended flag is set
 and runtime_status is RPM_ACTIVE? Is it a state like suspended but still can
 be accessed?
 
  I'm just afraid the existing code would cause a device hang if we allow it 
  to
 be accessed even though it's suspended (at this point RPM_ACTIVE could be
 meaningless). I don't understand the original motivation of these code. If 
 it's
 a valid case, most likely it should be handled in the specific device driver
 instead of the PM core.
 
  
  Perhaps it'd be better to rework __pm_runtime_resume() to
  convert the -EACCES return value from rpm_resume() into 0 if
  RPM_GET_PUT is
   set?

 Or do something like this?

 ---
  drivers/base/power/runtime.c |3 ++-
  1 file changed, 2 insertions(+), 1 deletion(-)

 Index: linux-pm/drivers/base/power/runtime.c

  
 ==
   =
 --- linux-pm.orig/drivers/base/power/runtime.c
 +++ linux-pm/drivers/base/power/runtime.c
 @@ -608,7 +608,8 @@ static int rpm_resume(struct device *dev
   repeat:
   if (dev-power.runtime_error)
   retval = -EINVAL;
 - else if (dev-power.disable_depth == 1  dev-
   power.is_suspended
 + else if (((dev-power.disable_depth  0  (rpmflags 
   RPM_GET_PUT))
 + || (dev-power.disable_depth == 1  dev-
   power.is_suspended))
dev

RE: [PATCH 1/1] PM / Runtime: let rpm_resume fail if rpm disabled and device suspended.

2014-06-15 Thread Allen Yu
On Sat, 14 Jun 2014, Alan Stern wrote:

> > dev->power.is_suspended is set after core suspends device during system
> suspend.
> > This flag mostly means device is not operational (all I/O been
> > quiesced, no more data read or write acceptible, etc.), hence it's
> > dangerous to access hardware if device is suspended even though runtime
> PM status is RPM_ACTIVE.
> >
> > In turn, we should allow device to be accessed in case device is *not*
> > suspended and runtime PM status is RPM_ACTIVE, even if runtime PM
> > disabled. This corner case can happen to a device in a generic PM
> > domain if the domain is not powered off while preparing for a system-wide
> power transition.
> 
> I don't understand.  Even if the PM domain isn't powered off, the device's
> is_suspended flag will still be set by __device_suspend().

Yes, is_suspended flag will be set by __device_suspend(). But runtime PM can be 
disabled in pm_genpd_prepare():

914 static int pm_genpd_prepare(struct device *dev){
...
956 /*
957  * The PM domain must be in the GPD_STATE_ACTIVE state at this 
point,
958  * so pm_genpd_poweron() will return immediately, but if the device
959  * is suspended (e.g. it's been stopped by genpd_stop_dev()), we 
need
960  * to make it operational.
961  */
962 pm_runtime_resume(dev);
963 __pm_runtime_disable(dev, false);
...
978 }

And there is a gap between pm_genpd_prepare() and __device_suspend(), during 
which is_suspended flag is *not* yet set but runtime PM is disabled and device 
status is RPM_ACTIVE. 

> 
> >  In this case, runtime PM status will
> > be set to RPM_ACTIVE and then runtime PM is disabled. After that,
> > device driver may call pm_runtime_get_sync() and rpm_resume() should
> > return 1, because the device is still active as long as not been suspended.
> 
> Isn't that what the existing code does already?  Your patch seems to change
> it so that it _doesn't_ behave the way you want.
> 

The existing code return 1 for case is_suspended flag is set.  That means 
__device_suspend() has been called and device is not in operational state. 
Whereas the case I mentioned above is before device is suspended.
It's dangerous to access device if it's in suspended state, so I propose only 
allowing access to a device if it's not suspended (i.e. value of "is_suspneded" 
flag is false).

> > Signed-off-by: Allen Yu 
> > ---
> >  drivers/base/power/runtime.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/base/power/runtime.c
> > b/drivers/base/power/runtime.c index 67c7938..39885f1 100644
> > --- a/drivers/base/power/runtime.c
> > +++ b/drivers/base/power/runtime.c
> > @@ -608,7 +608,7 @@ static int rpm_resume(struct device *dev, int
> rpmflags)
> >   repeat:
> > if (dev->power.runtime_error)
> > retval = -EINVAL;
> > -   else if (dev->power.disable_depth == 1 && dev-
> >power.is_suspended
> > +   else if (dev->power.disable_depth == 1 && !dev-
> >power.is_suspended
> > && dev->power.runtime_status == RPM_ACTIVE)
> > retval = 1;
> 
> Alan Stern

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


RE: [PATCH 1/1] PM / Runtime: let rpm_resume fail if rpm disabled and device suspended.

2014-06-15 Thread Allen Yu
On Sat, 14 Jun 2014, Alan Stern wrote:

  dev-power.is_suspended is set after core suspends device during system
 suspend.
  This flag mostly means device is not operational (all I/O been
  quiesced, no more data read or write acceptible, etc.), hence it's
  dangerous to access hardware if device is suspended even though runtime
 PM status is RPM_ACTIVE.
 
  In turn, we should allow device to be accessed in case device is *not*
  suspended and runtime PM status is RPM_ACTIVE, even if runtime PM
  disabled. This corner case can happen to a device in a generic PM
  domain if the domain is not powered off while preparing for a system-wide
 power transition.
 
 I don't understand.  Even if the PM domain isn't powered off, the device's
 is_suspended flag will still be set by __device_suspend().

Yes, is_suspended flag will be set by __device_suspend(). But runtime PM can be 
disabled in pm_genpd_prepare():

914 static int pm_genpd_prepare(struct device *dev){
...
956 /*
957  * The PM domain must be in the GPD_STATE_ACTIVE state at this 
point,
958  * so pm_genpd_poweron() will return immediately, but if the device
959  * is suspended (e.g. it's been stopped by genpd_stop_dev()), we 
need
960  * to make it operational.
961  */
962 pm_runtime_resume(dev);
963 __pm_runtime_disable(dev, false);
...
978 }

And there is a gap between pm_genpd_prepare() and __device_suspend(), during 
which is_suspended flag is *not* yet set but runtime PM is disabled and device 
status is RPM_ACTIVE. 

 
   In this case, runtime PM status will
  be set to RPM_ACTIVE and then runtime PM is disabled. After that,
  device driver may call pm_runtime_get_sync() and rpm_resume() should
  return 1, because the device is still active as long as not been suspended.
 
 Isn't that what the existing code does already?  Your patch seems to change
 it so that it _doesn't_ behave the way you want.
 

The existing code return 1 for case is_suspended flag is set.  That means 
__device_suspend() has been called and device is not in operational state. 
Whereas the case I mentioned above is before device is suspended.
It's dangerous to access device if it's in suspended state, so I propose only 
allowing access to a device if it's not suspended (i.e. value of is_suspneded 
flag is false).

  Signed-off-by: Allen Yu all...@nvidia.com
  ---
   drivers/base/power/runtime.c | 2 +-
   1 file changed, 1 insertion(+), 1 deletion(-)
 
  diff --git a/drivers/base/power/runtime.c
  b/drivers/base/power/runtime.c index 67c7938..39885f1 100644
  --- a/drivers/base/power/runtime.c
  +++ b/drivers/base/power/runtime.c
  @@ -608,7 +608,7 @@ static int rpm_resume(struct device *dev, int
 rpmflags)
repeat:
  if (dev-power.runtime_error)
  retval = -EINVAL;
  -   else if (dev-power.disable_depth == 1  dev-
 power.is_suspended
  +   else if (dev-power.disable_depth == 1  !dev-
 power.is_suspended
   dev-power.runtime_status == RPM_ACTIVE)
  retval = 1;
 
 Alan Stern

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/1] PM / Runtime: let rpm_resume fail if rpm disabled and device suspended.

2014-06-14 Thread Allen Yu
dev->power.is_suspended is set after core suspends device during system suspend.
This flag mostly means device is not operational (all I/O been quiesced, no more
data read or write acceptible, etc.), hence it's dangerous to access hardware if
device is suspended even though runtime PM status is RPM_ACTIVE.

In turn, we should allow device to be accessed in case device is *not* suspended
and runtime PM status is RPM_ACTIVE, even if runtime PM disabled. This corner 
case
can happen to a device in a generic PM domain if the domain is not powered off 
while
preparing for a system-wide power transition. In this case, runtime PM status 
will
be set to RPM_ACTIVE and then runtime PM is disabled. After that, device driver 
may
call pm_runtime_get_sync() and rpm_resume() should return 1, because the device 
is
still active as long as not been suspended.

Signed-off-by: Allen Yu 
---
 drivers/base/power/runtime.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 67c7938..39885f1 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -608,7 +608,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
  repeat:
if (dev->power.runtime_error)
retval = -EINVAL;
-   else if (dev->power.disable_depth == 1 && dev->power.is_suspended
+   else if (dev->power.disable_depth == 1 && !dev->power.is_suspended
&& dev->power.runtime_status == RPM_ACTIVE)
retval = 1;
else if (dev->power.disable_depth > 0)
-- 
1.8.1.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


[PATCH 1/1] PM / Runtime: let rpm_resume fail if rpm disabled and device suspended.

2014-06-14 Thread Allen Yu
dev-power.is_suspended is set after core suspends device during system suspend.
This flag mostly means device is not operational (all I/O been quiesced, no more
data read or write acceptible, etc.), hence it's dangerous to access hardware if
device is suspended even though runtime PM status is RPM_ACTIVE.

In turn, we should allow device to be accessed in case device is *not* suspended
and runtime PM status is RPM_ACTIVE, even if runtime PM disabled. This corner 
case
can happen to a device in a generic PM domain if the domain is not powered off 
while
preparing for a system-wide power transition. In this case, runtime PM status 
will
be set to RPM_ACTIVE and then runtime PM is disabled. After that, device driver 
may
call pm_runtime_get_sync() and rpm_resume() should return 1, because the device 
is
still active as long as not been suspended.

Signed-off-by: Allen Yu all...@nvidia.com
---
 drivers/base/power/runtime.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c
index 67c7938..39885f1 100644
--- a/drivers/base/power/runtime.c
+++ b/drivers/base/power/runtime.c
@@ -608,7 +608,7 @@ static int rpm_resume(struct device *dev, int rpmflags)
  repeat:
if (dev-power.runtime_error)
retval = -EINVAL;
-   else if (dev-power.disable_depth == 1  dev-power.is_suspended
+   else if (dev-power.disable_depth == 1  !dev-power.is_suspended
 dev-power.runtime_status == RPM_ACTIVE)
retval = 1;
else if (dev-power.disable_depth  0)
-- 
1.8.1.5

--
To unsubscribe from this list: send the line unsubscribe linux-kernel in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/