forked from mirrors/linux
		
	PM / Runtime: Respect autosuspend when idle triggers suspend
For devices which don't have a .runtime_idle() callback or if it returns 0, rpm_idle() will end up in triggering a call to rpm_suspend(), thus trying to carry out a runtime suspend directly from runtime_idle(). In the above situation we want to respect devices which has enabled autosuspend, we therfore append the flag sent to rpm_suspend with RPM_AUTO. Do note that drivers still needs to update the device last busy mark, to control the delay for this circumstance. Updated runtime PM documentation accordingly. Signed-off-by: Ulf Hansson <ulf.hansson@linaro.org> Acked-by: Kevin Hilman <khilman@linaro.org> Acked-by: Alan Stern <stern@rowland.harvard.edu> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
		
							parent
							
								
									61e6cfa80d
								
							
						
					
					
						commit
						d66e6db28d
					
				
					 2 changed files with 11 additions and 8 deletions
				
			
		| 
						 | 
					@ -145,11 +145,13 @@ The action performed by the idle callback is totally dependent on the subsystem
 | 
				
			||||||
if the device can be suspended (i.e. if all of the conditions necessary for
 | 
					if the device can be suspended (i.e. if all of the conditions necessary for
 | 
				
			||||||
suspending the device are satisfied) and to queue up a suspend request for the
 | 
					suspending the device are satisfied) and to queue up a suspend request for the
 | 
				
			||||||
device in that case.  If there is no idle callback, or if the callback returns
 | 
					device in that case.  If there is no idle callback, or if the callback returns
 | 
				
			||||||
0, then the PM core will attempt to carry out a runtime suspend of the device;
 | 
					0, then the PM core will attempt to carry out a runtime suspend of the device,
 | 
				
			||||||
in essence, it will call pm_runtime_suspend() directly.  To prevent this (for
 | 
					also respecting devices configured for autosuspend.  In essence this means a
 | 
				
			||||||
example, if the callback routine has started a delayed suspend), the routine
 | 
					call to pm_runtime_autosuspend() (do note that drivers needs to update the
 | 
				
			||||||
should return a non-zero value.  Negative error return codes are ignored by the
 | 
					device last busy mark, pm_runtime_mark_last_busy(), to control the delay under
 | 
				
			||||||
PM core.
 | 
					this circumstance).  To prevent this (for example, if the callback routine has
 | 
				
			||||||
 | 
					started a delayed suspend), the routine must return a non-zero value.  Negative
 | 
				
			||||||
 | 
					error return codes are ignored by the PM core.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
The helper functions provided by the PM core, described in Section 4, guarantee
 | 
					The helper functions provided by the PM core, described in Section 4, guarantee
 | 
				
			||||||
that the following constraints are met with respect to runtime PM callbacks for
 | 
					that the following constraints are met with respect to runtime PM callbacks for
 | 
				
			||||||
| 
						 | 
					@ -308,7 +310,7 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
 | 
				
			||||||
    - execute the subsystem-level idle callback for the device; returns an
 | 
					    - execute the subsystem-level idle callback for the device; returns an
 | 
				
			||||||
      error code on failure, where -EINPROGRESS means that ->runtime_idle() is
 | 
					      error code on failure, where -EINPROGRESS means that ->runtime_idle() is
 | 
				
			||||||
      already being executed; if there is no callback or the callback returns 0
 | 
					      already being executed; if there is no callback or the callback returns 0
 | 
				
			||||||
      then run pm_runtime_suspend(dev) and return its result
 | 
					      then run pm_runtime_autosuspend(dev) and return its result
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  int pm_runtime_suspend(struct device *dev);
 | 
					  int pm_runtime_suspend(struct device *dev);
 | 
				
			||||||
    - execute the subsystem-level suspend callback for the device; returns 0 on
 | 
					    - execute the subsystem-level suspend callback for the device; returns 0 on
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -258,7 +258,8 @@ static int __rpm_callback(int (*cb)(struct device *), struct device *dev)
 | 
				
			||||||
 * Check if the device's runtime PM status allows it to be suspended.  If
 | 
					 * Check if the device's runtime PM status allows it to be suspended.  If
 | 
				
			||||||
 * another idle notification has been started earlier, return immediately.  If
 | 
					 * another idle notification has been started earlier, return immediately.  If
 | 
				
			||||||
 * the RPM_ASYNC flag is set then queue an idle-notification request; otherwise
 | 
					 * the RPM_ASYNC flag is set then queue an idle-notification request; otherwise
 | 
				
			||||||
 * run the ->runtime_idle() callback directly.
 | 
					 * run the ->runtime_idle() callback directly. If the ->runtime_idle callback
 | 
				
			||||||
 | 
					 * doesn't exist or if it returns 0, call rpm_suspend with the RPM_AUTO flag.
 | 
				
			||||||
 *
 | 
					 *
 | 
				
			||||||
 * This function must be called under dev->power.lock with interrupts disabled.
 | 
					 * This function must be called under dev->power.lock with interrupts disabled.
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
| 
						 | 
					@ -331,7 +332,7 @@ static int rpm_idle(struct device *dev, int rpmflags)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 out:
 | 
					 out:
 | 
				
			||||||
	trace_rpm_return_int(dev, _THIS_IP_, retval);
 | 
						trace_rpm_return_int(dev, _THIS_IP_, retval);
 | 
				
			||||||
	return retval ? retval : rpm_suspend(dev, rpmflags);
 | 
						return retval ? retval : rpm_suspend(dev, rpmflags | RPM_AUTO);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue