Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

PM: runtime: Add pm_runtime_get_if_active()

pm_runtime_get_if_in_use() bumps up the PM-runtime usage count if it
is not equal to zero and the device's PM-runtime status is 'active'.
This works for drivers that do not use autoidle, but for those that
do, the function returns zero even when the device is active.

In order to maintain sane device state while the device is powered on
in the hope that it'll be needed, pm_runtime_get_if_active(dev, true)
returns a positive value if the device's PM-runtime status is 'active'
when it is called, in which case it also increments the device's usage
count.

If the second argument of pm_runtime_get_if_active() is 'false', the
function behaves just like pm_runtime_get_if_in_use(), so redefine
the latter as a wrapper around the former.

Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com>
[ rjw: Changelog ]
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Sakari Ailus and committed by
Rafael J. Wysocki
c111566b 98d54f81

+44 -10
+6
Documentation/power/runtime_pm.rst
··· 382 382 nonzero, increment the counter and return 1; otherwise return 0 without 383 383 changing the counter 384 384 385 + `int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count);` 386 + - return -EINVAL if 'power.disable_depth' is nonzero; otherwise, if the 387 + runtime PM status is RPM_ACTIVE, and either ign_usage_count is true 388 + or the device's usage_count is non-zero, increment the counter and 389 + return 1; otherwise return 0 without changing the counter 390 + 385 391 `void pm_runtime_put_noidle(struct device *dev);` 386 392 - decrement the device's usage counter 387 393
+27 -9
drivers/base/power/runtime.c
··· 1087 1087 EXPORT_SYMBOL_GPL(__pm_runtime_resume); 1088 1088 1089 1089 /** 1090 - * pm_runtime_get_if_in_use - Conditionally bump up the device's usage counter. 1090 + * pm_runtime_get_if_active - Conditionally bump up the device's usage counter. 1091 1091 * @dev: Device to handle. 1092 1092 * 1093 1093 * Return -EINVAL if runtime PM is disabled for the device. 1094 1094 * 1095 - * If that's not the case and if the device's runtime PM status is RPM_ACTIVE 1096 - * and the runtime PM usage counter is nonzero, increment the counter and 1097 - * return 1. Otherwise return 0 without changing the counter. 1095 + * Otherwise, if the device's runtime PM status is RPM_ACTIVE and either 1096 + * ign_usage_count is true or the device's usage_count is non-zero, increment 1097 + * the counter and return 1. Otherwise return 0 without changing the counter. 1098 + * 1099 + * If ign_usage_count is true, the function can be used to prevent suspending 1100 + * the device when its runtime PM status is RPM_ACTIVE. 1101 + * 1102 + * If ign_usage_count is false, the function can be used to prevent suspending 1103 + * the device when both its runtime PM status is RPM_ACTIVE and its usage_count 1104 + * is non-zero. 1105 + * 1106 + * The caller is resposible for putting the device's usage count when ther 1107 + * return value is greater than zero. 1098 1108 */ 1099 - int pm_runtime_get_if_in_use(struct device *dev) 1109 + int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count) 1100 1110 { 1101 1111 unsigned long flags; 1102 1112 int retval; 1103 1113 1104 1114 spin_lock_irqsave(&dev->power.lock, flags); 1105 - retval = dev->power.disable_depth > 0 ? -EINVAL : 1106 - dev->power.runtime_status == RPM_ACTIVE 1107 - && atomic_inc_not_zero(&dev->power.usage_count); 1115 + if (dev->power.disable_depth > 0) { 1116 + retval = -EINVAL; 1117 + } else if (dev->power.runtime_status != RPM_ACTIVE) { 1118 + retval = 0; 1119 + } else if (ign_usage_count) { 1120 + retval = 1; 1121 + atomic_inc(&dev->power.usage_count); 1122 + } else { 1123 + retval = atomic_inc_not_zero(&dev->power.usage_count); 1124 + } 1108 1125 trace_rpm_usage_rcuidle(dev, 0); 1109 1126 spin_unlock_irqrestore(&dev->power.lock, flags); 1127 + 1110 1128 return retval; 1111 1129 } 1112 - EXPORT_SYMBOL_GPL(pm_runtime_get_if_in_use); 1130 + EXPORT_SYMBOL_GPL(pm_runtime_get_if_active); 1113 1131 1114 1132 /** 1115 1133 * __pm_runtime_set_status - Set runtime PM status of a device.
+11 -1
include/linux/pm_runtime.h
··· 38 38 extern int __pm_runtime_idle(struct device *dev, int rpmflags); 39 39 extern int __pm_runtime_suspend(struct device *dev, int rpmflags); 40 40 extern int __pm_runtime_resume(struct device *dev, int rpmflags); 41 - extern int pm_runtime_get_if_in_use(struct device *dev); 41 + extern int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count); 42 42 extern int pm_schedule_suspend(struct device *dev, unsigned int delay); 43 43 extern int __pm_runtime_set_status(struct device *dev, unsigned int status); 44 44 extern int pm_runtime_barrier(struct device *dev); ··· 59 59 extern void pm_runtime_put_suppliers(struct device *dev); 60 60 extern void pm_runtime_new_link(struct device *dev); 61 61 extern void pm_runtime_drop_link(struct device *dev); 62 + 63 + static inline int pm_runtime_get_if_in_use(struct device *dev) 64 + { 65 + return pm_runtime_get_if_active(dev, false); 66 + } 62 67 63 68 static inline void pm_suspend_ignore_children(struct device *dev, bool enable) 64 69 { ··· 145 140 return -ENOSYS; 146 141 } 147 142 static inline int pm_runtime_get_if_in_use(struct device *dev) 143 + { 144 + return -EINVAL; 145 + } 146 + static inline int pm_runtime_get_if_active(struct device *dev, 147 + bool ign_usage_count) 148 148 { 149 149 return -EINVAL; 150 150 }