Skip to content

Commit 9a0abc3

Browse files
committed
PM: runtime: Add auto-cleanup macros for "resume and get" operations
It is generally useful to be able to automatically drop a device's runtime PM usage counter incremented by runtime PM operations that resume a device and bump up its usage counter [1]. To that end, add guard definition macros allowing pm_runtime_put() and pm_runtime_put_autosuspend() to be used for the auto-cleanup in those cases. Simply put, a piece of code like below: pm_runtime_get_sync(dev); ..... pm_runtime_put(dev); return 0; can be transformed with guard() like: guard(pm_runtime_active)(dev); ..... return 0; (see the pm_runtime_put() call is gone). However, it is better to do proper error handling in the majority of cases, so doing something like this instead of the above is recommended: ACQUIRE(pm_runtime_active_try, pm)(dev); if (ACQUIRE_ERR(pm_runtime_active_try, &pm)) return -ENXIO; ..... return 0; In all of the cases in which runtime PM is known to be enabled for the given device or the device can be regarded as operational (and so it can be accessed) with runtime PM disabled, a piece of code like: ret = pm_runtime_resume_and_get(dev); if (ret < 0) return ret; ..... pm_runtime_put(dev); return 0; can be changed as follows: ACQUIRE(pm_runtime_active_try, pm)(dev); ret = ACQUIRE_ERR(pm_runtime_active_try, &pm); if (ret < 0) return ret; ..... return 0; (again, see the pm_runtime_put() call is gone). Still, if the device cannot be accessed unless runtime PM has been enabled for it, the pm_runtime_active_try_enabled guard variant needs to be used, that is (in the context of the example above): ACQUIRE(pm_runtime_active_try_enabled, pm)(dev); ret = ACQUIRE_ERR(pm_runtime_active_try_enabled, &pm); if (ret < 0) return ret; ..... return 0; When the original code calls pm_runtime_put_autosuspend(), use one of the "auto" guard variants, pm_runtime_active_auto/_try/_enabled, so for example, a piece of code like: ret = pm_runtime_resume_and_get(dev); if (ret < 0) return ret; ..... pm_runtime_put_autosuspend(dev); return 0; will become: ACQUIRE(pm_runtime_active_auto_try_enabled, pm)(dev); ret = ACQUIRE_ERR(pm_runtime_active_auto_try_enabled, &pm); if (ret < 0) return ret; ..... return 0; Note that the cases in which the return value of pm_runtime_get_sync() is checked can also be handled with the help of the new guard macros. For example, a piece of code like: ret = pm_runtime_get_sync(dev); if (ret < 0) { pm_runtime_put(dev); return ret; } ..... pm_runtime_put(dev); return 0; can be rewritten as: ACQUIRE(pm_runtime_active_auto_try_enabled, pm)(dev); ret = ACQUIRE_ERR(pm_runtime_active_auto_try_enabled, &pm); if (ret < 0) return ret; ..... return 0; or pm_runtime_get_active_try can be used if transparent handling of disabled runtime PM is desirable. Link: https://lore.kernel.org/linux-pm/878qimv24u.wl-tiwai@suse.de/ [1] Link: https://lore.kernel.org/linux-pm/20250926150613.000073a4@huawei.com/ Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Acked-by: Dan Williams <dan.j.williams@intel.com> Reviewed-by: Takashi Iwai <tiwai@suse.de> Link: https://patch.msgid.link/2238241.irdbgypaU6@rafael.j.wysocki [ rjw: Fixed leftovers from the previous version in the changelog ] Reviewed-by: Jonathan Cameron <jonathan.cameron@huawei.com> Reviewed-by: Dhruva Gole <d-gole@ti.com> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
1 parent fed7eaa commit 9a0abc3

2 files changed

Lines changed: 37 additions & 9 deletions

File tree

drivers/base/power/runtime.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,8 @@ static int rpm_resume(struct device *dev, int rpmflags)
799799
if (dev->power.runtime_status == RPM_ACTIVE &&
800800
dev->power.last_status == RPM_ACTIVE)
801801
retval = 1;
802+
else if (rpmflags & RPM_TRANSPARENT)
803+
goto out;
802804
else
803805
retval = -EACCES;
804806
}

include/linux/pm_runtime.h

Lines changed: 35 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#define RPM_GET_PUT 0x04 /* Increment/decrement the
2222
usage_count */
2323
#define RPM_AUTO 0x08 /* Use autosuspend_delay */
24+
#define RPM_TRANSPARENT 0x10 /* Succeed if runtime PM is disabled */
2425

2526
/*
2627
* Use this for defining a set of PM operations to be used in all situations
@@ -512,6 +513,19 @@ static inline int pm_runtime_get_sync(struct device *dev)
512513
return __pm_runtime_resume(dev, RPM_GET_PUT);
513514
}
514515

516+
static inline int pm_runtime_get_active(struct device *dev, int rpmflags)
517+
{
518+
int ret;
519+
520+
ret = __pm_runtime_resume(dev, RPM_GET_PUT | rpmflags);
521+
if (ret < 0) {
522+
pm_runtime_put_noidle(dev);
523+
return ret;
524+
}
525+
526+
return 0;
527+
}
528+
515529
/**
516530
* pm_runtime_resume_and_get - Bump up usage counter of a device and resume it.
517531
* @dev: Target device.
@@ -522,15 +536,7 @@ static inline int pm_runtime_get_sync(struct device *dev)
522536
*/
523537
static inline int pm_runtime_resume_and_get(struct device *dev)
524538
{
525-
int ret;
526-
527-
ret = __pm_runtime_resume(dev, RPM_GET_PUT);
528-
if (ret < 0) {
529-
pm_runtime_put_noidle(dev);
530-
return ret;
531-
}
532-
533-
return 0;
539+
return pm_runtime_get_active(dev, 0);
534540
}
535541

536542
/**
@@ -610,6 +616,26 @@ static inline int pm_runtime_put_autosuspend(struct device *dev)
610616
return __pm_runtime_put_autosuspend(dev);
611617
}
612618

619+
DEFINE_GUARD(pm_runtime_active, struct device *,
620+
pm_runtime_get_sync(_T), pm_runtime_put(_T));
621+
DEFINE_GUARD(pm_runtime_active_auto, struct device *,
622+
pm_runtime_get_sync(_T), pm_runtime_put_autosuspend(_T));
623+
/*
624+
* Use the following guards with ACQUIRE()/ACQUIRE_ERR().
625+
*
626+
* The difference between the "_try" and "_try_enabled" variants is that the
627+
* former do not produce an error when runtime PM is disabled for the given
628+
* device.
629+
*/
630+
DEFINE_GUARD_COND(pm_runtime_active, _try,
631+
pm_runtime_get_active(_T, RPM_TRANSPARENT))
632+
DEFINE_GUARD_COND(pm_runtime_active, _try_enabled,
633+
pm_runtime_resume_and_get(_T))
634+
DEFINE_GUARD_COND(pm_runtime_active_auto, _try,
635+
pm_runtime_get_active(_T, RPM_TRANSPARENT))
636+
DEFINE_GUARD_COND(pm_runtime_active_auto, _try_enabled,
637+
pm_runtime_resume_and_get(_T))
638+
613639
/**
614640
* pm_runtime_put_sync - Drop device usage counter and run "idle check" if 0.
615641
* @dev: Target device.

0 commit comments

Comments
 (0)