Merge branches 'pm-core' and 'pm-runtime'
Merge a core power management update and runtime PM framework updates for 6.19-rc1: - Add WQ_UNBOUND to pm_wq workqueue (Marco Crivellari) - Add runtime PM wrapper macros for ACQUIRE()/ACQUIRE_ERR() and use them in the PCI core and the ACPI TAD driver (Rafael Wysocki) - Improve runtime PM in the ACPI TAD driver (Rafael Wysocki) - Update pm_runtime_allow/forbid() documentation (Rafael Wysocki) - Fix typos in runtime.c comments (Malaya Kumar Rout) * pm-core: PM: WQ_UNBOUND added to pm_wq workqueue * pm-runtime: PCI/sysfs: Use PM_RUNTIME_ACQUIRE()/PM_RUNTIME_ACQUIRE_ERR() ACPI: TAD: Use PM_RUNTIME_ACQUIRE()/PM_RUNTIME_ACQUIRE_ERR() PM: runtime: Wrapper macros for ACQUIRE()/ACQUIRE_ERR() PM: runtime: fix typos in runtime.c comments ACPI: TAD: Improve runtime PM using guard macros ACPI: TAD: Rearrange runtime PM operations in acpi_tad_remove() PM: runtime: docs: Update pm_runtime_allow/forbid() documentation
This commit is contained in:
@@ -480,16 +480,6 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
|
||||
`bool pm_runtime_status_suspended(struct device *dev);`
|
||||
- return true if the device's runtime PM status is 'suspended'
|
||||
|
||||
`void pm_runtime_allow(struct device *dev);`
|
||||
- set the power.runtime_auto flag for the device and decrease its usage
|
||||
counter (used by the /sys/devices/.../power/control interface to
|
||||
effectively allow the device to be power managed at run time)
|
||||
|
||||
`void pm_runtime_forbid(struct device *dev);`
|
||||
- unset the power.runtime_auto flag for the device and increase its usage
|
||||
counter (used by the /sys/devices/.../power/control interface to
|
||||
effectively prevent the device from being power managed at run time)
|
||||
|
||||
`void pm_runtime_no_callbacks(struct device *dev);`
|
||||
- set the power.no_callbacks flag for the device and remove the runtime
|
||||
PM attributes from /sys/devices/.../power (or prevent them from being
|
||||
|
||||
@@ -90,19 +90,18 @@ static int acpi_tad_set_real_time(struct device *dev, struct acpi_tad_rt *rt)
|
||||
args[0].buffer.pointer = (u8 *)rt;
|
||||
args[0].buffer.length = sizeof(*rt);
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
PM_RUNTIME_ACQUIRE(dev, pm);
|
||||
if (PM_RUNTIME_ACQUIRE_ERR(&pm))
|
||||
return -ENXIO;
|
||||
|
||||
status = acpi_evaluate_integer(handle, "_SRT", &arg_list, &retval);
|
||||
|
||||
pm_runtime_put_sync(dev);
|
||||
|
||||
if (ACPI_FAILURE(status) || retval)
|
||||
return -EIO;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int acpi_tad_get_real_time(struct device *dev, struct acpi_tad_rt *rt)
|
||||
static int acpi_tad_evaluate_grt(struct device *dev, struct acpi_tad_rt *rt)
|
||||
{
|
||||
acpi_handle handle = ACPI_HANDLE(dev);
|
||||
struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER };
|
||||
@@ -111,12 +110,7 @@ static int acpi_tad_get_real_time(struct device *dev, struct acpi_tad_rt *rt)
|
||||
acpi_status status;
|
||||
int ret = -EIO;
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
status = acpi_evaluate_object(handle, "_GRT", NULL, &output);
|
||||
|
||||
pm_runtime_put_sync(dev);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
goto out_free;
|
||||
|
||||
@@ -139,6 +133,21 @@ out_free:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int acpi_tad_get_real_time(struct device *dev, struct acpi_tad_rt *rt)
|
||||
{
|
||||
int ret;
|
||||
|
||||
PM_RUNTIME_ACQUIRE(dev, pm);
|
||||
if (PM_RUNTIME_ACQUIRE_ERR(&pm))
|
||||
return -ENXIO;
|
||||
|
||||
ret = acpi_tad_evaluate_grt(dev, rt);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *acpi_tad_rt_next_field(char *s, int *val)
|
||||
{
|
||||
char *p;
|
||||
@@ -266,12 +275,11 @@ static int acpi_tad_wake_set(struct device *dev, char *method, u32 timer_id,
|
||||
args[0].integer.value = timer_id;
|
||||
args[1].integer.value = value;
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
PM_RUNTIME_ACQUIRE(dev, pm);
|
||||
if (PM_RUNTIME_ACQUIRE_ERR(&pm))
|
||||
return -ENXIO;
|
||||
|
||||
status = acpi_evaluate_integer(handle, method, &arg_list, &retval);
|
||||
|
||||
pm_runtime_put_sync(dev);
|
||||
|
||||
if (ACPI_FAILURE(status) || retval)
|
||||
return -EIO;
|
||||
|
||||
@@ -314,12 +322,11 @@ static ssize_t acpi_tad_wake_read(struct device *dev, char *buf, char *method,
|
||||
|
||||
args[0].integer.value = timer_id;
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
PM_RUNTIME_ACQUIRE(dev, pm);
|
||||
if (PM_RUNTIME_ACQUIRE_ERR(&pm))
|
||||
return -ENXIO;
|
||||
|
||||
status = acpi_evaluate_integer(handle, method, &arg_list, &retval);
|
||||
|
||||
pm_runtime_put_sync(dev);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
@@ -370,12 +377,11 @@ static int acpi_tad_clear_status(struct device *dev, u32 timer_id)
|
||||
|
||||
args[0].integer.value = timer_id;
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
PM_RUNTIME_ACQUIRE(dev, pm);
|
||||
if (PM_RUNTIME_ACQUIRE_ERR(&pm))
|
||||
return -ENXIO;
|
||||
|
||||
status = acpi_evaluate_integer(handle, "_CWS", &arg_list, &retval);
|
||||
|
||||
pm_runtime_put_sync(dev);
|
||||
|
||||
if (ACPI_FAILURE(status) || retval)
|
||||
return -EIO;
|
||||
|
||||
@@ -411,12 +417,11 @@ static ssize_t acpi_tad_status_read(struct device *dev, char *buf, u32 timer_id)
|
||||
|
||||
args[0].integer.value = timer_id;
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
PM_RUNTIME_ACQUIRE(dev, pm);
|
||||
if (PM_RUNTIME_ACQUIRE_ERR(&pm))
|
||||
return -ENXIO;
|
||||
|
||||
status = acpi_evaluate_integer(handle, "_GWS", &arg_list, &retval);
|
||||
|
||||
pm_runtime_put_sync(dev);
|
||||
|
||||
if (ACPI_FAILURE(status))
|
||||
return -EIO;
|
||||
|
||||
@@ -563,8 +568,6 @@ static void acpi_tad_remove(struct platform_device *pdev)
|
||||
|
||||
device_init_wakeup(dev, false);
|
||||
|
||||
pm_runtime_get_sync(dev);
|
||||
|
||||
if (dd->capabilities & ACPI_TAD_RT)
|
||||
sysfs_remove_group(&dev->kobj, &acpi_tad_time_attr_group);
|
||||
|
||||
@@ -573,14 +576,16 @@ static void acpi_tad_remove(struct platform_device *pdev)
|
||||
|
||||
sysfs_remove_group(&dev->kobj, &acpi_tad_attr_group);
|
||||
|
||||
acpi_tad_disable_timer(dev, ACPI_TAD_AC_TIMER);
|
||||
acpi_tad_clear_status(dev, ACPI_TAD_AC_TIMER);
|
||||
if (dd->capabilities & ACPI_TAD_DC_WAKE) {
|
||||
acpi_tad_disable_timer(dev, ACPI_TAD_DC_TIMER);
|
||||
acpi_tad_clear_status(dev, ACPI_TAD_DC_TIMER);
|
||||
scoped_guard(pm_runtime_noresume, dev) {
|
||||
acpi_tad_disable_timer(dev, ACPI_TAD_AC_TIMER);
|
||||
acpi_tad_clear_status(dev, ACPI_TAD_AC_TIMER);
|
||||
if (dd->capabilities & ACPI_TAD_DC_WAKE) {
|
||||
acpi_tad_disable_timer(dev, ACPI_TAD_DC_TIMER);
|
||||
acpi_tad_clear_status(dev, ACPI_TAD_DC_TIMER);
|
||||
}
|
||||
}
|
||||
|
||||
pm_runtime_put_sync(dev);
|
||||
pm_runtime_suspend(dev);
|
||||
pm_runtime_disable(dev);
|
||||
acpi_remove_cmos_rtc_space_handler(handle);
|
||||
}
|
||||
|
||||
@@ -90,7 +90,7 @@ static void update_pm_runtime_accounting(struct device *dev)
|
||||
/*
|
||||
* Because ktime_get_mono_fast_ns() is not monotonic during
|
||||
* timekeeping updates, ensure that 'now' is after the last saved
|
||||
* timesptamp.
|
||||
* timestamp.
|
||||
*/
|
||||
if (now < last)
|
||||
return;
|
||||
@@ -217,7 +217,7 @@ static int dev_memalloc_noio(struct device *dev, void *data)
|
||||
* resume/suspend callback of any one of its ancestors(or the
|
||||
* block device itself), the deadlock may be triggered inside the
|
||||
* memory allocation since it might not complete until the block
|
||||
* device becomes active and the involed page I/O finishes. The
|
||||
* device becomes active and the involved page I/O finishes. The
|
||||
* situation is pointed out first by Alan Stern. Network device
|
||||
* are involved in iSCSI kind of situation.
|
||||
*
|
||||
@@ -1210,7 +1210,7 @@ EXPORT_SYMBOL_GPL(__pm_runtime_resume);
|
||||
*
|
||||
* Otherwise, if its runtime PM status is %RPM_ACTIVE and (1) @ign_usage_count
|
||||
* is set, or (2) @dev is not ignoring children and its active child count is
|
||||
* nonero, or (3) the runtime PM usage counter of @dev is not zero, increment
|
||||
* nonzero, or (3) the runtime PM usage counter of @dev is not zero, increment
|
||||
* the usage counter of @dev and return 1.
|
||||
*
|
||||
* Otherwise, return 0 without changing the usage counter.
|
||||
@@ -1664,9 +1664,12 @@ EXPORT_SYMBOL_GPL(devm_pm_runtime_get_noresume);
|
||||
* pm_runtime_forbid - Block runtime PM of a device.
|
||||
* @dev: Device to handle.
|
||||
*
|
||||
* Increase the device's usage count and clear its power.runtime_auto flag,
|
||||
* so that it cannot be suspended at run time until pm_runtime_allow() is called
|
||||
* for it.
|
||||
* Resume @dev if already suspended and block runtime suspend of @dev in such
|
||||
* a way that it can be unblocked via the /sys/devices/.../power/control
|
||||
* interface, or otherwise by calling pm_runtime_allow().
|
||||
*
|
||||
* Calling this function many times in a row has the same effect as calling it
|
||||
* once.
|
||||
*/
|
||||
void pm_runtime_forbid(struct device *dev)
|
||||
{
|
||||
@@ -1687,7 +1690,13 @@ EXPORT_SYMBOL_GPL(pm_runtime_forbid);
|
||||
* pm_runtime_allow - Unblock runtime PM of a device.
|
||||
* @dev: Device to handle.
|
||||
*
|
||||
* Decrease the device's usage count and set its power.runtime_auto flag.
|
||||
* Unblock runtime suspend of @dev after it has been blocked by
|
||||
* pm_runtime_forbid() (for instance, if it has been blocked via the
|
||||
* /sys/devices/.../power/control interface), check if @dev can be
|
||||
* suspended and suspend it in that case.
|
||||
*
|
||||
* Calling this function many times in a row has the same effect as calling it
|
||||
* once.
|
||||
*/
|
||||
void pm_runtime_allow(struct device *dev)
|
||||
{
|
||||
|
||||
@@ -1517,8 +1517,8 @@ static ssize_t reset_method_store(struct device *dev,
|
||||
return count;
|
||||
}
|
||||
|
||||
ACQUIRE(pm_runtime_active_try, pm)(dev);
|
||||
if (ACQUIRE_ERR(pm_runtime_active_try, &pm))
|
||||
PM_RUNTIME_ACQUIRE(dev, pm);
|
||||
if (PM_RUNTIME_ACQUIRE_ERR(&pm))
|
||||
return -ENXIO;
|
||||
|
||||
if (sysfs_streq(buf, "default")) {
|
||||
|
||||
@@ -637,6 +637,30 @@ DEFINE_GUARD_COND(pm_runtime_active_auto, _try,
|
||||
DEFINE_GUARD_COND(pm_runtime_active_auto, _try_enabled,
|
||||
pm_runtime_resume_and_get(_T), _RET == 0)
|
||||
|
||||
/* ACQUIRE() wrapper macros for the guards defined above. */
|
||||
|
||||
#define PM_RUNTIME_ACQUIRE(_dev, _var) \
|
||||
ACQUIRE(pm_runtime_active_try, _var)(_dev)
|
||||
|
||||
#define PM_RUNTIME_ACQUIRE_AUTOSUSPEND(_dev, _var) \
|
||||
ACQUIRE(pm_runtime_active_auto_try, _var)(_dev)
|
||||
|
||||
#define PM_RUNTIME_ACQUIRE_IF_ENABLED(_dev, _var) \
|
||||
ACQUIRE(pm_runtime_active_try_enabled, _var)(_dev)
|
||||
|
||||
#define PM_RUNTIME_ACQUIRE_IF_ENABLED_AUTOSUSPEND(_dev, _var) \
|
||||
ACQUIRE(pm_runtime_active_auto_try_enabled, _var)(_dev)
|
||||
|
||||
/*
|
||||
* ACQUIRE_ERR() wrapper macro for guard pm_runtime_active.
|
||||
*
|
||||
* Always check PM_RUNTIME_ACQUIRE_ERR() after using one of the
|
||||
* PM_RUNTIME_ACQUIRE*() macros defined above (yes, it can be used with
|
||||
* any of them) and if it is nonzero, avoid accessing the given device.
|
||||
*/
|
||||
#define PM_RUNTIME_ACQUIRE_ERR(_var_ptr) \
|
||||
ACQUIRE_ERR(pm_runtime_active, _var_ptr)
|
||||
|
||||
/**
|
||||
* pm_runtime_put_sync - Drop device usage counter and run "idle check" if 0.
|
||||
* @dev: Target device.
|
||||
|
||||
@@ -1068,7 +1068,7 @@ EXPORT_SYMBOL_GPL(pm_wq);
|
||||
|
||||
static int __init pm_start_workqueue(void)
|
||||
{
|
||||
pm_wq = alloc_workqueue("pm", WQ_FREEZABLE, 0);
|
||||
pm_wq = alloc_workqueue("pm", WQ_FREEZABLE | WQ_UNBOUND, 0);
|
||||
|
||||
return pm_wq ? 0 : -ENOMEM;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user