Commit a436b6a1 authored by Rafael J. Wysocki's avatar Rafael J. Wysocki

PM / runtime: Add new helper for conditional usage count incrementation

Introduce a new runtime PM function, pm_runtime_get_if_in_use(),
that will increment the device's runtime PM usage counter and
return 1 if its status is RPM_ACTIVE and its usage counter
is greater than 0 at the same time (0 will be returned otherwise).

This is useful for things that should only be done if the device
is active (from the runtime PM perspective) and used by somebody
(as indicated by the usage counter) already and they are not worth
bothering otherwise.
Requested-by: default avatarImre Deak <imre.deak@intel.com>
Reviewed-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent d89d7ff9
...@@ -371,6 +371,12 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h: ...@@ -371,6 +371,12 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
- increment the device's usage counter, run pm_runtime_resume(dev) and - increment the device's usage counter, run pm_runtime_resume(dev) and
return its result return its result
int pm_runtime_get_if_in_use(struct device *dev);
- return -EINVAL if 'power.disable_depth' is nonzero; otherwise, if the
runtime PM status is RPM_ACTIVE and the runtime PM usage counter is
nonzero, increment the counter and return 1; otherwise return 0 without
changing the counter
void pm_runtime_put_noidle(struct device *dev); void pm_runtime_put_noidle(struct device *dev);
- decrement the device's usage counter - decrement the device's usage counter
......
...@@ -965,6 +965,30 @@ int __pm_runtime_resume(struct device *dev, int rpmflags) ...@@ -965,6 +965,30 @@ int __pm_runtime_resume(struct device *dev, int rpmflags)
} }
EXPORT_SYMBOL_GPL(__pm_runtime_resume); EXPORT_SYMBOL_GPL(__pm_runtime_resume);
/**
* pm_runtime_get_if_in_use - Conditionally bump up the device's usage counter.
* @dev: Device to handle.
*
* Return -EINVAL if runtime PM is disabled for the device.
*
* If that's not the case and if the device's runtime PM status is RPM_ACTIVE
* and the runtime PM usage counter is nonzero, increment the counter and
* return 1. Otherwise return 0 without changing the counter.
*/
int pm_runtime_get_if_in_use(struct device *dev)
{
unsigned long flags;
int retval;
spin_lock_irqsave(&dev->power.lock, flags);
retval = dev->power.disable_depth > 0 ? -EINVAL :
dev->power.runtime_status == RPM_ACTIVE
&& atomic_inc_not_zero(&dev->power.usage_count);
spin_unlock_irqrestore(&dev->power.lock, flags);
return retval;
}
EXPORT_SYMBOL_GPL(pm_runtime_get_if_in_use);
/** /**
* __pm_runtime_set_status - Set runtime PM status of a device. * __pm_runtime_set_status - Set runtime PM status of a device.
* @dev: Device to handle. * @dev: Device to handle.
......
...@@ -39,6 +39,7 @@ extern int pm_runtime_force_resume(struct device *dev); ...@@ -39,6 +39,7 @@ extern int pm_runtime_force_resume(struct device *dev);
extern int __pm_runtime_idle(struct device *dev, int rpmflags); extern int __pm_runtime_idle(struct device *dev, int rpmflags);
extern int __pm_runtime_suspend(struct device *dev, int rpmflags); extern int __pm_runtime_suspend(struct device *dev, int rpmflags);
extern int __pm_runtime_resume(struct device *dev, int rpmflags); extern int __pm_runtime_resume(struct device *dev, int rpmflags);
extern int pm_runtime_get_if_in_use(struct device *dev);
extern int pm_schedule_suspend(struct device *dev, unsigned int delay); extern int pm_schedule_suspend(struct device *dev, unsigned int delay);
extern int __pm_runtime_set_status(struct device *dev, unsigned int status); extern int __pm_runtime_set_status(struct device *dev, unsigned int status);
extern int pm_runtime_barrier(struct device *dev); extern int pm_runtime_barrier(struct device *dev);
...@@ -143,6 +144,10 @@ static inline int pm_schedule_suspend(struct device *dev, unsigned int delay) ...@@ -143,6 +144,10 @@ static inline int pm_schedule_suspend(struct device *dev, unsigned int delay)
{ {
return -ENOSYS; return -ENOSYS;
} }
static inline int pm_runtime_get_if_in_use(struct device *dev)
{
return -EINVAL;
}
static inline int __pm_runtime_set_status(struct device *dev, static inline int __pm_runtime_set_status(struct device *dev,
unsigned int status) { return 0; } unsigned int status) { return 0; }
static inline int pm_runtime_barrier(struct device *dev) { return 0; } static inline int pm_runtime_barrier(struct device *dev) { return 0; }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment