mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 17:57:38 -04:00
Merge branches 'pm-core', 'pm-sleep', 'pm-acpi' and 'pm-domains'
* pm-core: PM: runtime: Add pm_runtime_get_if_active() * pm-sleep: PM: sleep: wakeup: Skip wakeup_source_sysfs_remove() if device is not there PM / hibernate: Remove unnecessary compat ioctl overrides PM: hibernate: fix docs for ioctls that return loff_t via pointer PM: sleep: wakeup: Use built-in RCU list checking PM: sleep: core: Use built-in RCU list checking * pm-acpi: ACPI: PM: s2idle: Refine active GPEs check ACPICA: Allow acpi_any_gpe_status_set() to skip one GPE ACPI: PM: s2idle: Fix comment in acpi_s2idle_prepare_late() * pm-domains: cpuidle: psci: Split psci_dt_cpu_init_idle() PM / Domains: Allow no domain-idle-states DT property in genpd when parsing
This commit is contained in:
@@ -2653,7 +2653,7 @@ static int genpd_iterate_idle_states(struct device_node *dn,
|
||||
|
||||
ret = of_count_phandle_with_args(dn, "domain-idle-states", NULL);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
return ret == -ENOENT ? 0 : ret;
|
||||
|
||||
/* Loop over the phandles until all the requested entry is found */
|
||||
of_for_each_phandle(&it, ret, dn, "domain-idle-states", NULL, 0) {
|
||||
|
||||
@@ -40,6 +40,10 @@
|
||||
|
||||
typedef int (*pm_callback_t)(struct device *);
|
||||
|
||||
#define list_for_each_entry_rcu_locked(pos, head, member) \
|
||||
list_for_each_entry_rcu(pos, head, member, \
|
||||
device_links_read_lock_held())
|
||||
|
||||
/*
|
||||
* The entries in the dpm_list list are in a depth first order, simply
|
||||
* because children are guaranteed to be discovered after parents, and
|
||||
@@ -266,7 +270,7 @@ static void dpm_wait_for_suppliers(struct device *dev, bool async)
|
||||
* callbacks freeing the link objects for the links in the list we're
|
||||
* walking.
|
||||
*/
|
||||
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
|
||||
list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node)
|
||||
if (READ_ONCE(link->status) != DL_STATE_DORMANT)
|
||||
dpm_wait(link->supplier, async);
|
||||
|
||||
@@ -323,7 +327,7 @@ static void dpm_wait_for_consumers(struct device *dev, bool async)
|
||||
* continue instead of trying to continue in parallel with its
|
||||
* unregistration).
|
||||
*/
|
||||
list_for_each_entry_rcu(link, &dev->links.consumers, s_node)
|
||||
list_for_each_entry_rcu_locked(link, &dev->links.consumers, s_node)
|
||||
if (READ_ONCE(link->status) != DL_STATE_DORMANT)
|
||||
dpm_wait(link->consumer, async);
|
||||
|
||||
@@ -1235,7 +1239,7 @@ static void dpm_superior_set_must_resume(struct device *dev)
|
||||
|
||||
idx = device_links_read_lock();
|
||||
|
||||
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
|
||||
list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node)
|
||||
link->supplier->power.must_resume = true;
|
||||
|
||||
device_links_read_unlock(idx);
|
||||
@@ -1695,7 +1699,7 @@ static void dpm_clear_superiors_direct_complete(struct device *dev)
|
||||
|
||||
idx = device_links_read_lock();
|
||||
|
||||
list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) {
|
||||
list_for_each_entry_rcu_locked(link, &dev->links.suppliers, c_node) {
|
||||
spin_lock_irq(&link->supplier->power.lock);
|
||||
link->supplier->power.direct_complete = false;
|
||||
spin_unlock_irq(&link->supplier->power.lock);
|
||||
|
||||
@@ -1087,29 +1087,47 @@ int __pm_runtime_resume(struct device *dev, int rpmflags)
|
||||
EXPORT_SYMBOL_GPL(__pm_runtime_resume);
|
||||
|
||||
/**
|
||||
* pm_runtime_get_if_in_use - Conditionally bump up the device's usage counter.
|
||||
* pm_runtime_get_if_active - 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.
|
||||
* Otherwise, if the device's 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 return 1. Otherwise return 0 without changing the counter.
|
||||
*
|
||||
* If ign_usage_count is true, the function can be used to prevent suspending
|
||||
* the device when its runtime PM status is RPM_ACTIVE.
|
||||
*
|
||||
* If ign_usage_count is false, the function can be used to prevent suspending
|
||||
* the device when both its runtime PM status is RPM_ACTIVE and its usage_count
|
||||
* is non-zero.
|
||||
*
|
||||
* The caller is resposible for putting the device's usage count when ther
|
||||
* return value is greater than zero.
|
||||
*/
|
||||
int pm_runtime_get_if_in_use(struct device *dev)
|
||||
int pm_runtime_get_if_active(struct device *dev, bool ign_usage_count)
|
||||
{
|
||||
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);
|
||||
if (dev->power.disable_depth > 0) {
|
||||
retval = -EINVAL;
|
||||
} else if (dev->power.runtime_status != RPM_ACTIVE) {
|
||||
retval = 0;
|
||||
} else if (ign_usage_count) {
|
||||
retval = 1;
|
||||
atomic_inc(&dev->power.usage_count);
|
||||
} else {
|
||||
retval = atomic_inc_not_zero(&dev->power.usage_count);
|
||||
}
|
||||
trace_rpm_usage_rcuidle(dev, 0);
|
||||
spin_unlock_irqrestore(&dev->power.lock, flags);
|
||||
|
||||
return retval;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(pm_runtime_get_if_in_use);
|
||||
EXPORT_SYMBOL_GPL(pm_runtime_get_if_active);
|
||||
|
||||
/**
|
||||
* __pm_runtime_set_status - Set runtime PM status of a device.
|
||||
|
||||
@@ -24,6 +24,9 @@ suspend_state_t pm_suspend_target_state;
|
||||
#define pm_suspend_target_state (PM_SUSPEND_ON)
|
||||
#endif
|
||||
|
||||
#define list_for_each_entry_rcu_locked(pos, head, member) \
|
||||
list_for_each_entry_rcu(pos, head, member, \
|
||||
srcu_read_lock_held(&wakeup_srcu))
|
||||
/*
|
||||
* If set, the suspend/hibernate code will abort transitions to a sleep state
|
||||
* if wakeup events are registered during or immediately before the transition.
|
||||
@@ -241,7 +244,9 @@ void wakeup_source_unregister(struct wakeup_source *ws)
|
||||
{
|
||||
if (ws) {
|
||||
wakeup_source_remove(ws);
|
||||
wakeup_source_sysfs_remove(ws);
|
||||
if (ws->dev)
|
||||
wakeup_source_sysfs_remove(ws);
|
||||
|
||||
wakeup_source_destroy(ws);
|
||||
}
|
||||
}
|
||||
@@ -405,7 +410,7 @@ void device_wakeup_arm_wake_irqs(void)
|
||||
int srcuidx;
|
||||
|
||||
srcuidx = srcu_read_lock(&wakeup_srcu);
|
||||
list_for_each_entry_rcu(ws, &wakeup_sources, entry)
|
||||
list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry)
|
||||
dev_pm_arm_wake_irq(ws->wakeirq);
|
||||
srcu_read_unlock(&wakeup_srcu, srcuidx);
|
||||
}
|
||||
@@ -421,7 +426,7 @@ void device_wakeup_disarm_wake_irqs(void)
|
||||
int srcuidx;
|
||||
|
||||
srcuidx = srcu_read_lock(&wakeup_srcu);
|
||||
list_for_each_entry_rcu(ws, &wakeup_sources, entry)
|
||||
list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry)
|
||||
dev_pm_disarm_wake_irq(ws->wakeirq);
|
||||
srcu_read_unlock(&wakeup_srcu, srcuidx);
|
||||
}
|
||||
@@ -874,7 +879,7 @@ void pm_print_active_wakeup_sources(void)
|
||||
struct wakeup_source *last_activity_ws = NULL;
|
||||
|
||||
srcuidx = srcu_read_lock(&wakeup_srcu);
|
||||
list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
|
||||
list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry) {
|
||||
if (ws->active) {
|
||||
pm_pr_dbg("active wakeup source: %s\n", ws->name);
|
||||
active = 1;
|
||||
@@ -1025,7 +1030,7 @@ void pm_wakep_autosleep_enabled(bool set)
|
||||
int srcuidx;
|
||||
|
||||
srcuidx = srcu_read_lock(&wakeup_srcu);
|
||||
list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
|
||||
list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry) {
|
||||
spin_lock_irq(&ws->lock);
|
||||
if (ws->autosleep_enabled != set) {
|
||||
ws->autosleep_enabled = set;
|
||||
@@ -1104,7 +1109,7 @@ static void *wakeup_sources_stats_seq_start(struct seq_file *m,
|
||||
}
|
||||
|
||||
*srcuidx = srcu_read_lock(&wakeup_srcu);
|
||||
list_for_each_entry_rcu(ws, &wakeup_sources, entry) {
|
||||
list_for_each_entry_rcu_locked(ws, &wakeup_sources, entry) {
|
||||
if (n-- <= 0)
|
||||
return ws;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user