mirror of
https://github.com/torvalds/linux.git
synced 2024-12-24 11:51:27 +00:00
Merge branch 'pm-runtime'
Merge changes related to the runtime power management of devices for 6.9-rc1: - Simplify pm_runtime_get_if_active() usage and add a replacement for pm_runtime_put_autosuspend() (Sakari Ailus). - Add a tracepoint for runtime_status changes tracking (Vilas Bhat). - Fix section title markdown in the runtime PM documentation (Yiwei Lin). * pm-runtime: Documentation: PM: Fix runtime_pm.rst markdown syntax PM: runtime: add tracepoint for runtime_status changes PM: runtime: Add pm_runtime_put_autosuspend() replacement PM: runtime: Simplify pm_runtime_get_if_active() usage
This commit is contained in:
commit
7874b581c7
@ -154,7 +154,7 @@ 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
|
||||
0, then the PM core will attempt to carry out a runtime suspend of the device,
|
||||
also respecting devices configured for autosuspend. In essence this means a
|
||||
call to pm_runtime_autosuspend() (do note that drivers needs to update the
|
||||
call to __pm_runtime_autosuspend() (do note that drivers needs to update the
|
||||
device last busy mark, pm_runtime_mark_last_busy(), to control the delay under
|
||||
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
|
||||
@ -396,10 +396,9 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
|
||||
nonzero, increment the counter and return 1; otherwise return 0 without
|
||||
changing the counter
|
||||
|
||||
`int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count);`
|
||||
`int pm_runtime_get_if_active(struct device *dev);`
|
||||
- return -EINVAL if 'power.disable_depth' is nonzero; otherwise, if the
|
||||
runtime PM status is RPM_ACTIVE, and either ign_usage_count is true
|
||||
or the device's usage_count is non-zero, increment the counter and
|
||||
runtime PM status is RPM_ACTIVE, increment the counter and
|
||||
return 1; otherwise return 0 without changing the counter
|
||||
|
||||
`void pm_runtime_put_noidle(struct device *dev);`
|
||||
@ -410,6 +409,10 @@ drivers/base/power/runtime.c and include/linux/pm_runtime.h:
|
||||
pm_request_idle(dev) and return its result
|
||||
|
||||
`int pm_runtime_put_autosuspend(struct device *dev);`
|
||||
- does the same as __pm_runtime_put_autosuspend() for now, but in the
|
||||
future, will also call pm_runtime_mark_last_busy() as well, DO NOT USE!
|
||||
|
||||
`int __pm_runtime_put_autosuspend(struct device *dev);`
|
||||
- decrement the device's usage counter; if the result is 0 then run
|
||||
pm_request_autosuspend(dev) and return its result
|
||||
|
||||
@ -540,6 +543,7 @@ It is safe to execute the following helper functions from interrupt context:
|
||||
- pm_runtime_put_noidle()
|
||||
- pm_runtime_put()
|
||||
- pm_runtime_put_autosuspend()
|
||||
- __pm_runtime_put_autosuspend()
|
||||
- pm_runtime_enable()
|
||||
- pm_suspend_ignore_children()
|
||||
- pm_runtime_set_active()
|
||||
@ -730,6 +734,7 @@ out the following operations:
|
||||
for it, respectively.
|
||||
|
||||
7. Generic subsystem callbacks
|
||||
==============================
|
||||
|
||||
Subsystems may wish to conserve code space by using the set of generic power
|
||||
management callbacks provided by the PM core, defined in
|
||||
@ -865,9 +870,9 @@ automatically be delayed until the desired period of inactivity has elapsed.
|
||||
|
||||
Inactivity is determined based on the power.last_busy field. Drivers should
|
||||
call pm_runtime_mark_last_busy() to update this field after carrying out I/O,
|
||||
typically just before calling pm_runtime_put_autosuspend(). The desired length
|
||||
of the inactivity period is a matter of policy. Subsystems can set this length
|
||||
initially by calling pm_runtime_set_autosuspend_delay(), but after device
|
||||
typically just before calling __pm_runtime_put_autosuspend(). The desired
|
||||
length of the inactivity period is a matter of policy. Subsystems can set this
|
||||
length initially by calling pm_runtime_set_autosuspend_delay(), but after device
|
||||
registration the length should be controlled by user space, using the
|
||||
/sys/devices/.../power/autosuspend_delay_ms attribute.
|
||||
|
||||
@ -878,7 +883,7 @@ instead of the non-autosuspend counterparts::
|
||||
|
||||
Instead of: pm_runtime_suspend use: pm_runtime_autosuspend;
|
||||
Instead of: pm_schedule_suspend use: pm_request_autosuspend;
|
||||
Instead of: pm_runtime_put use: pm_runtime_put_autosuspend;
|
||||
Instead of: pm_runtime_put use: __pm_runtime_put_autosuspend;
|
||||
Instead of: pm_runtime_put_sync use: pm_runtime_put_sync_autosuspend.
|
||||
|
||||
Drivers may also continue to use the non-autosuspend helper functions; they
|
||||
@ -917,7 +922,7 @@ Here is a schematic pseudo-code example::
|
||||
lock(&foo->private_lock);
|
||||
if (--foo->num_pending_requests == 0) {
|
||||
pm_runtime_mark_last_busy(&foo->dev);
|
||||
pm_runtime_put_autosuspend(&foo->dev);
|
||||
__pm_runtime_put_autosuspend(&foo->dev);
|
||||
} else {
|
||||
foo_process_next_request(foo);
|
||||
}
|
||||
|
@ -309,7 +309,7 @@ int ivpu_rpm_get_if_active(struct ivpu_device *vdev)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = pm_runtime_get_if_active(vdev->drm.dev, false);
|
||||
ret = pm_runtime_get_if_in_use(vdev->drm.dev);
|
||||
drm_WARN_ON(&vdev->drm, ret < 0);
|
||||
|
||||
return ret;
|
||||
|
@ -94,6 +94,7 @@ static void update_pm_runtime_accounting(struct device *dev)
|
||||
static void __update_runtime_status(struct device *dev, enum rpm_status status)
|
||||
{
|
||||
update_pm_runtime_accounting(dev);
|
||||
trace_rpm_status(dev, status);
|
||||
dev->power.runtime_status = status;
|
||||
}
|
||||
|
||||
@ -1176,7 +1177,7 @@ int __pm_runtime_resume(struct device *dev, int rpmflags)
|
||||
EXPORT_SYMBOL_GPL(__pm_runtime_resume);
|
||||
|
||||
/**
|
||||
* pm_runtime_get_if_active - Conditionally bump up device usage counter.
|
||||
* pm_runtime_get_conditional - Conditionally bump up device usage counter.
|
||||
* @dev: Device to handle.
|
||||
* @ign_usage_count: Whether or not to look at the current usage counter value.
|
||||
*
|
||||
@ -1197,7 +1198,7 @@ EXPORT_SYMBOL_GPL(__pm_runtime_resume);
|
||||
* The caller is responsible for decrementing the runtime PM usage counter of
|
||||
* @dev after this function has returned a positive value for it.
|
||||
*/
|
||||
int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count)
|
||||
static int pm_runtime_get_conditional(struct device *dev, bool ign_usage_count)
|
||||
{
|
||||
unsigned long flags;
|
||||
int retval;
|
||||
@ -1218,8 +1219,39 @@ int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count)
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_runtime_get_if_active - Bump up runtime PM usage counter if the device is
|
||||
* in active state
|
||||
* @dev: Target device.
|
||||
*
|
||||
* Increment the runtime PM usage counter of @dev if its runtime PM status is
|
||||
* %RPM_ACTIVE, in which case it returns 1. If the device is in a different
|
||||
* state, 0 is returned. -EINVAL is returned if runtime PM is disabled for the
|
||||
* device, in which case also the usage_count will remain unmodified.
|
||||
*/
|
||||
int pm_runtime_get_if_active(struct device *dev)
|
||||
{
|
||||
return pm_runtime_get_conditional(dev, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_runtime_get_if_active);
|
||||
|
||||
/**
|
||||
* pm_runtime_get_if_in_use - Conditionally bump up runtime PM usage counter.
|
||||
* @dev: Target device.
|
||||
*
|
||||
* Increment the runtime PM usage counter of @dev if its runtime PM status is
|
||||
* %RPM_ACTIVE and its runtime PM usage counter is greater than 0, in which case
|
||||
* it returns 1. If the device is in a different state or its usage_count is 0,
|
||||
* 0 is returned. -EINVAL is returned if runtime PM is disabled for the device,
|
||||
* in which case also the usage_count will remain unmodified.
|
||||
*/
|
||||
int pm_runtime_get_if_in_use(struct device *dev)
|
||||
{
|
||||
return pm_runtime_get_conditional(dev, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_runtime_get_if_in_use);
|
||||
|
||||
/**
|
||||
* __pm_runtime_set_status - Set runtime PM status of a device.
|
||||
* @dev: Device to handle.
|
||||
|
@ -246,7 +246,10 @@ static intel_wakeref_t __intel_runtime_pm_get_if_active(struct intel_runtime_pm
|
||||
* function, since the power state is undefined. This applies
|
||||
* atm to the late/early system suspend/resume handlers.
|
||||
*/
|
||||
if (pm_runtime_get_if_active(rpm->kdev, ignore_usecount) <= 0)
|
||||
if ((ignore_usecount &&
|
||||
pm_runtime_get_if_active(rpm->kdev) <= 0) ||
|
||||
(!ignore_usecount &&
|
||||
pm_runtime_get_if_in_use(rpm->kdev) <= 0))
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -330,7 +330,7 @@ int xe_pm_runtime_put(struct xe_device *xe)
|
||||
|
||||
int xe_pm_runtime_get_if_active(struct xe_device *xe)
|
||||
{
|
||||
return pm_runtime_get_if_active(xe->drm.dev, true);
|
||||
return pm_runtime_get_if_active(xe->drm.dev);
|
||||
}
|
||||
|
||||
void xe_pm_assert_unbounded_bridge(struct xe_device *xe)
|
||||
|
@ -674,7 +674,7 @@ static int ccs_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
break;
|
||||
}
|
||||
|
||||
pm_status = pm_runtime_get_if_active(&client->dev, true);
|
||||
pm_status = pm_runtime_get_if_active(&client->dev);
|
||||
if (!pm_status)
|
||||
return 0;
|
||||
|
||||
|
@ -3287,7 +3287,7 @@ static int ov64a40_set_ctrl(struct v4l2_ctrl *ctrl)
|
||||
exp_max, 1, exp_val);
|
||||
}
|
||||
|
||||
pm_status = pm_runtime_get_if_active(ov64a40->dev, true);
|
||||
pm_status = pm_runtime_get_if_active(ov64a40->dev);
|
||||
if (!pm_status)
|
||||
return 0;
|
||||
|
||||
|
@ -1052,7 +1052,7 @@ static int thp7312_s_ctrl(struct v4l2_ctrl *ctrl)
|
||||
if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
|
||||
return -EINVAL;
|
||||
|
||||
if (!pm_runtime_get_if_active(thp7312->dev, true))
|
||||
if (!pm_runtime_get_if_active(thp7312->dev))
|
||||
return 0;
|
||||
|
||||
switch (ctrl->id) {
|
||||
|
@ -92,7 +92,7 @@ static void ipa_smp2p_notify(struct ipa_smp2p *smp2p)
|
||||
return;
|
||||
|
||||
dev = &smp2p->ipa->pdev->dev;
|
||||
smp2p->power_on = pm_runtime_get_if_active(dev, true) > 0;
|
||||
smp2p->power_on = pm_runtime_get_if_active(dev) > 0;
|
||||
|
||||
/* Signal whether the IPA power is enabled */
|
||||
mask = BIT(smp2p->enabled_bit);
|
||||
|
@ -2532,7 +2532,7 @@ static void pci_pme_list_scan(struct work_struct *work)
|
||||
* course of the call.
|
||||
*/
|
||||
if (bdev) {
|
||||
bref = pm_runtime_get_if_active(bdev, true);
|
||||
bref = pm_runtime_get_if_active(bdev);
|
||||
if (!bref)
|
||||
continue;
|
||||
|
||||
|
@ -72,7 +72,8 @@ extern int pm_runtime_force_resume(struct device *dev);
|
||||
extern int __pm_runtime_idle(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_get_if_active(struct device *dev, bool ign_usage_count);
|
||||
extern int pm_runtime_get_if_active(struct device *dev);
|
||||
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_runtime_set_status(struct device *dev, unsigned int status);
|
||||
extern int pm_runtime_barrier(struct device *dev);
|
||||
@ -94,18 +95,6 @@ extern void pm_runtime_release_supplier(struct device_link *link);
|
||||
|
||||
extern int devm_pm_runtime_enable(struct device *dev);
|
||||
|
||||
/**
|
||||
* pm_runtime_get_if_in_use - Conditionally bump up runtime PM usage counter.
|
||||
* @dev: Target device.
|
||||
*
|
||||
* Increment the runtime PM usage counter of @dev if its runtime PM status is
|
||||
* %RPM_ACTIVE and its runtime PM usage counter is greater than 0.
|
||||
*/
|
||||
static inline int pm_runtime_get_if_in_use(struct device *dev)
|
||||
{
|
||||
return pm_runtime_get_if_active(dev, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_suspend_ignore_children - Set runtime PM behavior regarding children.
|
||||
* @dev: Target device.
|
||||
@ -275,8 +264,7 @@ static inline int pm_runtime_get_if_in_use(struct device *dev)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
static inline int pm_runtime_get_if_active(struct device *dev,
|
||||
bool ign_usage_count)
|
||||
static inline int pm_runtime_get_if_active(struct device *dev)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
@ -460,6 +448,18 @@ static inline int pm_runtime_put(struct device *dev)
|
||||
return __pm_runtime_idle(dev, RPM_GET_PUT | RPM_ASYNC);
|
||||
}
|
||||
|
||||
/**
|
||||
* __pm_runtime_put_autosuspend - Drop device usage counter and queue autosuspend if 0.
|
||||
* @dev: Target device.
|
||||
*
|
||||
* Decrement the runtime PM usage counter of @dev and if it turns out to be
|
||||
* equal to 0, queue up a work item for @dev like in pm_request_autosuspend().
|
||||
*/
|
||||
static inline int __pm_runtime_put_autosuspend(struct device *dev)
|
||||
{
|
||||
return __pm_runtime_suspend(dev, RPM_GET_PUT | RPM_ASYNC | RPM_AUTO);
|
||||
}
|
||||
|
||||
/**
|
||||
* pm_runtime_put_autosuspend - Drop device usage counter and queue autosuspend if 0.
|
||||
* @dev: Target device.
|
||||
|
@ -101,6 +101,48 @@ TRACE_EVENT(rpm_return_int,
|
||||
__entry->ret)
|
||||
);
|
||||
|
||||
#define RPM_STATUS_STRINGS \
|
||||
EM(RPM_INVALID, "RPM_INVALID") \
|
||||
EM(RPM_ACTIVE, "RPM_ACTIVE") \
|
||||
EM(RPM_RESUMING, "RPM_RESUMING") \
|
||||
EM(RPM_SUSPENDED, "RPM_SUSPENDED") \
|
||||
EMe(RPM_SUSPENDING, "RPM_SUSPENDING")
|
||||
|
||||
/* Enums require being exported to userspace, for user tool parsing. */
|
||||
#undef EM
|
||||
#undef EMe
|
||||
#define EM(a, b) TRACE_DEFINE_ENUM(a);
|
||||
#define EMe(a, b) TRACE_DEFINE_ENUM(a);
|
||||
|
||||
RPM_STATUS_STRINGS
|
||||
|
||||
/*
|
||||
* Now redefine the EM() and EMe() macros to map the enums to the strings that
|
||||
* will be printed in the output.
|
||||
*/
|
||||
#undef EM
|
||||
#undef EMe
|
||||
#define EM(a, b) { a, b },
|
||||
#define EMe(a, b) { a, b }
|
||||
|
||||
TRACE_EVENT(rpm_status,
|
||||
TP_PROTO(struct device *dev, enum rpm_status status),
|
||||
TP_ARGS(dev, status),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__string(name, dev_name(dev))
|
||||
__field(int, status)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__assign_str(name, dev_name(dev));
|
||||
__entry->status = status;
|
||||
),
|
||||
|
||||
TP_printk("%s status=%s", __get_str(name),
|
||||
__print_symbolic(__entry->status, RPM_STATUS_STRINGS))
|
||||
);
|
||||
|
||||
#endif /* _TRACE_RUNTIME_POWER_H */
|
||||
|
||||
/* This part must be outside protection */
|
||||
|
@ -612,7 +612,7 @@ EXPORT_SYMBOL_GPL(snd_hdac_power_up_pm);
|
||||
int snd_hdac_keep_power_up(struct hdac_device *codec)
|
||||
{
|
||||
if (!atomic_inc_not_zero(&codec->in_pm)) {
|
||||
int ret = pm_runtime_get_if_active(&codec->dev, true);
|
||||
int ret = pm_runtime_get_if_active(&codec->dev);
|
||||
if (!ret)
|
||||
return -1;
|
||||
if (ret < 0)
|
||||
|
Loading…
Reference in New Issue
Block a user