162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * drivers/base/power/runtime.c - Helper functions for device runtime PM
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright (c) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
662306a36Sopenharmony_ci * Copyright (C) 2010 Alan Stern <stern@rowland.harvard.edu>
762306a36Sopenharmony_ci */
862306a36Sopenharmony_ci#include <linux/sched/mm.h>
962306a36Sopenharmony_ci#include <linux/ktime.h>
1062306a36Sopenharmony_ci#include <linux/hrtimer.h>
1162306a36Sopenharmony_ci#include <linux/export.h>
1262306a36Sopenharmony_ci#include <linux/pm_runtime.h>
1362306a36Sopenharmony_ci#include <linux/pm_wakeirq.h>
1462306a36Sopenharmony_ci#include <trace/events/rpm.h>
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci#include "../base.h"
1762306a36Sopenharmony_ci#include "power.h"
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_citypedef int (*pm_callback_t)(struct device *);
2062306a36Sopenharmony_ci
2162306a36Sopenharmony_cistatic pm_callback_t __rpm_get_callback(struct device *dev, size_t cb_offset)
2262306a36Sopenharmony_ci{
2362306a36Sopenharmony_ci	pm_callback_t cb;
2462306a36Sopenharmony_ci	const struct dev_pm_ops *ops;
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci	if (dev->pm_domain)
2762306a36Sopenharmony_ci		ops = &dev->pm_domain->ops;
2862306a36Sopenharmony_ci	else if (dev->type && dev->type->pm)
2962306a36Sopenharmony_ci		ops = dev->type->pm;
3062306a36Sopenharmony_ci	else if (dev->class && dev->class->pm)
3162306a36Sopenharmony_ci		ops = dev->class->pm;
3262306a36Sopenharmony_ci	else if (dev->bus && dev->bus->pm)
3362306a36Sopenharmony_ci		ops = dev->bus->pm;
3462306a36Sopenharmony_ci	else
3562306a36Sopenharmony_ci		ops = NULL;
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_ci	if (ops)
3862306a36Sopenharmony_ci		cb = *(pm_callback_t *)((void *)ops + cb_offset);
3962306a36Sopenharmony_ci	else
4062306a36Sopenharmony_ci		cb = NULL;
4162306a36Sopenharmony_ci
4262306a36Sopenharmony_ci	if (!cb && dev->driver && dev->driver->pm)
4362306a36Sopenharmony_ci		cb = *(pm_callback_t *)((void *)dev->driver->pm + cb_offset);
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	return cb;
4662306a36Sopenharmony_ci}
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci#define RPM_GET_CALLBACK(dev, callback) \
4962306a36Sopenharmony_ci		__rpm_get_callback(dev, offsetof(struct dev_pm_ops, callback))
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_cistatic int rpm_resume(struct device *dev, int rpmflags);
5262306a36Sopenharmony_cistatic int rpm_suspend(struct device *dev, int rpmflags);
5362306a36Sopenharmony_ci
5462306a36Sopenharmony_ci/**
5562306a36Sopenharmony_ci * update_pm_runtime_accounting - Update the time accounting of power states
5662306a36Sopenharmony_ci * @dev: Device to update the accounting for
5762306a36Sopenharmony_ci *
5862306a36Sopenharmony_ci * In order to be able to have time accounting of the various power states
5962306a36Sopenharmony_ci * (as used by programs such as PowerTOP to show the effectiveness of runtime
6062306a36Sopenharmony_ci * PM), we need to track the time spent in each state.
6162306a36Sopenharmony_ci * update_pm_runtime_accounting must be called each time before the
6262306a36Sopenharmony_ci * runtime_status field is updated, to account the time in the old state
6362306a36Sopenharmony_ci * correctly.
6462306a36Sopenharmony_ci */
6562306a36Sopenharmony_cistatic void update_pm_runtime_accounting(struct device *dev)
6662306a36Sopenharmony_ci{
6762306a36Sopenharmony_ci	u64 now, last, delta;
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci	if (dev->power.disable_depth > 0)
7062306a36Sopenharmony_ci		return;
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	last = dev->power.accounting_timestamp;
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci	now = ktime_get_mono_fast_ns();
7562306a36Sopenharmony_ci	dev->power.accounting_timestamp = now;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	/*
7862306a36Sopenharmony_ci	 * Because ktime_get_mono_fast_ns() is not monotonic during
7962306a36Sopenharmony_ci	 * timekeeping updates, ensure that 'now' is after the last saved
8062306a36Sopenharmony_ci	 * timesptamp.
8162306a36Sopenharmony_ci	 */
8262306a36Sopenharmony_ci	if (now < last)
8362306a36Sopenharmony_ci		return;
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	delta = now - last;
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci	if (dev->power.runtime_status == RPM_SUSPENDED)
8862306a36Sopenharmony_ci		dev->power.suspended_time += delta;
8962306a36Sopenharmony_ci	else
9062306a36Sopenharmony_ci		dev->power.active_time += delta;
9162306a36Sopenharmony_ci}
9262306a36Sopenharmony_ci
9362306a36Sopenharmony_cistatic void __update_runtime_status(struct device *dev, enum rpm_status status)
9462306a36Sopenharmony_ci{
9562306a36Sopenharmony_ci	update_pm_runtime_accounting(dev);
9662306a36Sopenharmony_ci	dev->power.runtime_status = status;
9762306a36Sopenharmony_ci}
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic u64 rpm_get_accounted_time(struct device *dev, bool suspended)
10062306a36Sopenharmony_ci{
10162306a36Sopenharmony_ci	u64 time;
10262306a36Sopenharmony_ci	unsigned long flags;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	spin_lock_irqsave(&dev->power.lock, flags);
10562306a36Sopenharmony_ci
10662306a36Sopenharmony_ci	update_pm_runtime_accounting(dev);
10762306a36Sopenharmony_ci	time = suspended ? dev->power.suspended_time : dev->power.active_time;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->power.lock, flags);
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_ci	return time;
11262306a36Sopenharmony_ci}
11362306a36Sopenharmony_ci
11462306a36Sopenharmony_ciu64 pm_runtime_active_time(struct device *dev)
11562306a36Sopenharmony_ci{
11662306a36Sopenharmony_ci	return rpm_get_accounted_time(dev, false);
11762306a36Sopenharmony_ci}
11862306a36Sopenharmony_ci
11962306a36Sopenharmony_ciu64 pm_runtime_suspended_time(struct device *dev)
12062306a36Sopenharmony_ci{
12162306a36Sopenharmony_ci	return rpm_get_accounted_time(dev, true);
12262306a36Sopenharmony_ci}
12362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_runtime_suspended_time);
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci/**
12662306a36Sopenharmony_ci * pm_runtime_deactivate_timer - Deactivate given device's suspend timer.
12762306a36Sopenharmony_ci * @dev: Device to handle.
12862306a36Sopenharmony_ci */
12962306a36Sopenharmony_cistatic void pm_runtime_deactivate_timer(struct device *dev)
13062306a36Sopenharmony_ci{
13162306a36Sopenharmony_ci	if (dev->power.timer_expires > 0) {
13262306a36Sopenharmony_ci		hrtimer_try_to_cancel(&dev->power.suspend_timer);
13362306a36Sopenharmony_ci		dev->power.timer_expires = 0;
13462306a36Sopenharmony_ci	}
13562306a36Sopenharmony_ci}
13662306a36Sopenharmony_ci
13762306a36Sopenharmony_ci/**
13862306a36Sopenharmony_ci * pm_runtime_cancel_pending - Deactivate suspend timer and cancel requests.
13962306a36Sopenharmony_ci * @dev: Device to handle.
14062306a36Sopenharmony_ci */
14162306a36Sopenharmony_cistatic void pm_runtime_cancel_pending(struct device *dev)
14262306a36Sopenharmony_ci{
14362306a36Sopenharmony_ci	pm_runtime_deactivate_timer(dev);
14462306a36Sopenharmony_ci	/*
14562306a36Sopenharmony_ci	 * In case there's a request pending, make sure its work function will
14662306a36Sopenharmony_ci	 * return without doing anything.
14762306a36Sopenharmony_ci	 */
14862306a36Sopenharmony_ci	dev->power.request = RPM_REQ_NONE;
14962306a36Sopenharmony_ci}
15062306a36Sopenharmony_ci
15162306a36Sopenharmony_ci/*
15262306a36Sopenharmony_ci * pm_runtime_autosuspend_expiration - Get a device's autosuspend-delay expiration time.
15362306a36Sopenharmony_ci * @dev: Device to handle.
15462306a36Sopenharmony_ci *
15562306a36Sopenharmony_ci * Compute the autosuspend-delay expiration time based on the device's
15662306a36Sopenharmony_ci * power.last_busy time.  If the delay has already expired or is disabled
15762306a36Sopenharmony_ci * (negative) or the power.use_autosuspend flag isn't set, return 0.
15862306a36Sopenharmony_ci * Otherwise return the expiration time in nanoseconds (adjusted to be nonzero).
15962306a36Sopenharmony_ci *
16062306a36Sopenharmony_ci * This function may be called either with or without dev->power.lock held.
16162306a36Sopenharmony_ci * Either way it can be racy, since power.last_busy may be updated at any time.
16262306a36Sopenharmony_ci */
16362306a36Sopenharmony_ciu64 pm_runtime_autosuspend_expiration(struct device *dev)
16462306a36Sopenharmony_ci{
16562306a36Sopenharmony_ci	int autosuspend_delay;
16662306a36Sopenharmony_ci	u64 expires;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	if (!dev->power.use_autosuspend)
16962306a36Sopenharmony_ci		return 0;
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	autosuspend_delay = READ_ONCE(dev->power.autosuspend_delay);
17262306a36Sopenharmony_ci	if (autosuspend_delay < 0)
17362306a36Sopenharmony_ci		return 0;
17462306a36Sopenharmony_ci
17562306a36Sopenharmony_ci	expires  = READ_ONCE(dev->power.last_busy);
17662306a36Sopenharmony_ci	expires += (u64)autosuspend_delay * NSEC_PER_MSEC;
17762306a36Sopenharmony_ci	if (expires > ktime_get_mono_fast_ns())
17862306a36Sopenharmony_ci		return expires;	/* Expires in the future */
17962306a36Sopenharmony_ci
18062306a36Sopenharmony_ci	return 0;
18162306a36Sopenharmony_ci}
18262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_runtime_autosuspend_expiration);
18362306a36Sopenharmony_ci
18462306a36Sopenharmony_cistatic int dev_memalloc_noio(struct device *dev, void *data)
18562306a36Sopenharmony_ci{
18662306a36Sopenharmony_ci	return dev->power.memalloc_noio;
18762306a36Sopenharmony_ci}
18862306a36Sopenharmony_ci
18962306a36Sopenharmony_ci/*
19062306a36Sopenharmony_ci * pm_runtime_set_memalloc_noio - Set a device's memalloc_noio flag.
19162306a36Sopenharmony_ci * @dev: Device to handle.
19262306a36Sopenharmony_ci * @enable: True for setting the flag and False for clearing the flag.
19362306a36Sopenharmony_ci *
19462306a36Sopenharmony_ci * Set the flag for all devices in the path from the device to the
19562306a36Sopenharmony_ci * root device in the device tree if @enable is true, otherwise clear
19662306a36Sopenharmony_ci * the flag for devices in the path whose siblings don't set the flag.
19762306a36Sopenharmony_ci *
19862306a36Sopenharmony_ci * The function should only be called by block device, or network
19962306a36Sopenharmony_ci * device driver for solving the deadlock problem during runtime
20062306a36Sopenharmony_ci * resume/suspend:
20162306a36Sopenharmony_ci *
20262306a36Sopenharmony_ci *     If memory allocation with GFP_KERNEL is called inside runtime
20362306a36Sopenharmony_ci *     resume/suspend callback of any one of its ancestors(or the
20462306a36Sopenharmony_ci *     block device itself), the deadlock may be triggered inside the
20562306a36Sopenharmony_ci *     memory allocation since it might not complete until the block
20662306a36Sopenharmony_ci *     device becomes active and the involed page I/O finishes. The
20762306a36Sopenharmony_ci *     situation is pointed out first by Alan Stern. Network device
20862306a36Sopenharmony_ci *     are involved in iSCSI kind of situation.
20962306a36Sopenharmony_ci *
21062306a36Sopenharmony_ci * The lock of dev_hotplug_mutex is held in the function for handling
21162306a36Sopenharmony_ci * hotplug race because pm_runtime_set_memalloc_noio() may be called
21262306a36Sopenharmony_ci * in async probe().
21362306a36Sopenharmony_ci *
21462306a36Sopenharmony_ci * The function should be called between device_add() and device_del()
21562306a36Sopenharmony_ci * on the affected device(block/network device).
21662306a36Sopenharmony_ci */
21762306a36Sopenharmony_civoid pm_runtime_set_memalloc_noio(struct device *dev, bool enable)
21862306a36Sopenharmony_ci{
21962306a36Sopenharmony_ci	static DEFINE_MUTEX(dev_hotplug_mutex);
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci	mutex_lock(&dev_hotplug_mutex);
22262306a36Sopenharmony_ci	for (;;) {
22362306a36Sopenharmony_ci		bool enabled;
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_ci		/* hold power lock since bitfield is not SMP-safe. */
22662306a36Sopenharmony_ci		spin_lock_irq(&dev->power.lock);
22762306a36Sopenharmony_ci		enabled = dev->power.memalloc_noio;
22862306a36Sopenharmony_ci		dev->power.memalloc_noio = enable;
22962306a36Sopenharmony_ci		spin_unlock_irq(&dev->power.lock);
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci		/*
23262306a36Sopenharmony_ci		 * not need to enable ancestors any more if the device
23362306a36Sopenharmony_ci		 * has been enabled.
23462306a36Sopenharmony_ci		 */
23562306a36Sopenharmony_ci		if (enabled && enable)
23662306a36Sopenharmony_ci			break;
23762306a36Sopenharmony_ci
23862306a36Sopenharmony_ci		dev = dev->parent;
23962306a36Sopenharmony_ci
24062306a36Sopenharmony_ci		/*
24162306a36Sopenharmony_ci		 * clear flag of the parent device only if all the
24262306a36Sopenharmony_ci		 * children don't set the flag because ancestor's
24362306a36Sopenharmony_ci		 * flag was set by any one of the descendants.
24462306a36Sopenharmony_ci		 */
24562306a36Sopenharmony_ci		if (!dev || (!enable &&
24662306a36Sopenharmony_ci		    device_for_each_child(dev, NULL, dev_memalloc_noio)))
24762306a36Sopenharmony_ci			break;
24862306a36Sopenharmony_ci	}
24962306a36Sopenharmony_ci	mutex_unlock(&dev_hotplug_mutex);
25062306a36Sopenharmony_ci}
25162306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_runtime_set_memalloc_noio);
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci/**
25462306a36Sopenharmony_ci * rpm_check_suspend_allowed - Test whether a device may be suspended.
25562306a36Sopenharmony_ci * @dev: Device to test.
25662306a36Sopenharmony_ci */
25762306a36Sopenharmony_cistatic int rpm_check_suspend_allowed(struct device *dev)
25862306a36Sopenharmony_ci{
25962306a36Sopenharmony_ci	int retval = 0;
26062306a36Sopenharmony_ci
26162306a36Sopenharmony_ci	if (dev->power.runtime_error)
26262306a36Sopenharmony_ci		retval = -EINVAL;
26362306a36Sopenharmony_ci	else if (dev->power.disable_depth > 0)
26462306a36Sopenharmony_ci		retval = -EACCES;
26562306a36Sopenharmony_ci	else if (atomic_read(&dev->power.usage_count))
26662306a36Sopenharmony_ci		retval = -EAGAIN;
26762306a36Sopenharmony_ci	else if (!dev->power.ignore_children && atomic_read(&dev->power.child_count))
26862306a36Sopenharmony_ci		retval = -EBUSY;
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	/* Pending resume requests take precedence over suspends. */
27162306a36Sopenharmony_ci	else if ((dev->power.deferred_resume &&
27262306a36Sopenharmony_ci	    dev->power.runtime_status == RPM_SUSPENDING) ||
27362306a36Sopenharmony_ci	    (dev->power.request_pending && dev->power.request == RPM_REQ_RESUME))
27462306a36Sopenharmony_ci		retval = -EAGAIN;
27562306a36Sopenharmony_ci	else if (__dev_pm_qos_resume_latency(dev) == 0)
27662306a36Sopenharmony_ci		retval = -EPERM;
27762306a36Sopenharmony_ci	else if (dev->power.runtime_status == RPM_SUSPENDED)
27862306a36Sopenharmony_ci		retval = 1;
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	return retval;
28162306a36Sopenharmony_ci}
28262306a36Sopenharmony_ci
28362306a36Sopenharmony_cistatic int rpm_get_suppliers(struct device *dev)
28462306a36Sopenharmony_ci{
28562306a36Sopenharmony_ci	struct device_link *link;
28662306a36Sopenharmony_ci
28762306a36Sopenharmony_ci	list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
28862306a36Sopenharmony_ci				device_links_read_lock_held()) {
28962306a36Sopenharmony_ci		int retval;
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci		if (!(link->flags & DL_FLAG_PM_RUNTIME))
29262306a36Sopenharmony_ci			continue;
29362306a36Sopenharmony_ci
29462306a36Sopenharmony_ci		retval = pm_runtime_get_sync(link->supplier);
29562306a36Sopenharmony_ci		/* Ignore suppliers with disabled runtime PM. */
29662306a36Sopenharmony_ci		if (retval < 0 && retval != -EACCES) {
29762306a36Sopenharmony_ci			pm_runtime_put_noidle(link->supplier);
29862306a36Sopenharmony_ci			return retval;
29962306a36Sopenharmony_ci		}
30062306a36Sopenharmony_ci		refcount_inc(&link->rpm_active);
30162306a36Sopenharmony_ci	}
30262306a36Sopenharmony_ci	return 0;
30362306a36Sopenharmony_ci}
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci/**
30662306a36Sopenharmony_ci * pm_runtime_release_supplier - Drop references to device link's supplier.
30762306a36Sopenharmony_ci * @link: Target device link.
30862306a36Sopenharmony_ci *
30962306a36Sopenharmony_ci * Drop all runtime PM references associated with @link to its supplier device.
31062306a36Sopenharmony_ci */
31162306a36Sopenharmony_civoid pm_runtime_release_supplier(struct device_link *link)
31262306a36Sopenharmony_ci{
31362306a36Sopenharmony_ci	struct device *supplier = link->supplier;
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	/*
31662306a36Sopenharmony_ci	 * The additional power.usage_count check is a safety net in case
31762306a36Sopenharmony_ci	 * the rpm_active refcount becomes saturated, in which case
31862306a36Sopenharmony_ci	 * refcount_dec_not_one() would return true forever, but it is not
31962306a36Sopenharmony_ci	 * strictly necessary.
32062306a36Sopenharmony_ci	 */
32162306a36Sopenharmony_ci	while (refcount_dec_not_one(&link->rpm_active) &&
32262306a36Sopenharmony_ci	       atomic_read(&supplier->power.usage_count) > 0)
32362306a36Sopenharmony_ci		pm_runtime_put_noidle(supplier);
32462306a36Sopenharmony_ci}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_cistatic void __rpm_put_suppliers(struct device *dev, bool try_to_suspend)
32762306a36Sopenharmony_ci{
32862306a36Sopenharmony_ci	struct device_link *link;
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
33162306a36Sopenharmony_ci				device_links_read_lock_held()) {
33262306a36Sopenharmony_ci		pm_runtime_release_supplier(link);
33362306a36Sopenharmony_ci		if (try_to_suspend)
33462306a36Sopenharmony_ci			pm_request_idle(link->supplier);
33562306a36Sopenharmony_ci	}
33662306a36Sopenharmony_ci}
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_cistatic void rpm_put_suppliers(struct device *dev)
33962306a36Sopenharmony_ci{
34062306a36Sopenharmony_ci	__rpm_put_suppliers(dev, true);
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_cistatic void rpm_suspend_suppliers(struct device *dev)
34462306a36Sopenharmony_ci{
34562306a36Sopenharmony_ci	struct device_link *link;
34662306a36Sopenharmony_ci	int idx = device_links_read_lock();
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
34962306a36Sopenharmony_ci				device_links_read_lock_held())
35062306a36Sopenharmony_ci		pm_request_idle(link->supplier);
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	device_links_read_unlock(idx);
35362306a36Sopenharmony_ci}
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci/**
35662306a36Sopenharmony_ci * __rpm_callback - Run a given runtime PM callback for a given device.
35762306a36Sopenharmony_ci * @cb: Runtime PM callback to run.
35862306a36Sopenharmony_ci * @dev: Device to run the callback for.
35962306a36Sopenharmony_ci */
36062306a36Sopenharmony_cistatic int __rpm_callback(int (*cb)(struct device *), struct device *dev)
36162306a36Sopenharmony_ci	__releases(&dev->power.lock) __acquires(&dev->power.lock)
36262306a36Sopenharmony_ci{
36362306a36Sopenharmony_ci	int retval = 0, idx;
36462306a36Sopenharmony_ci	bool use_links = dev->power.links_count > 0;
36562306a36Sopenharmony_ci
36662306a36Sopenharmony_ci	if (dev->power.irq_safe) {
36762306a36Sopenharmony_ci		spin_unlock(&dev->power.lock);
36862306a36Sopenharmony_ci	} else {
36962306a36Sopenharmony_ci		spin_unlock_irq(&dev->power.lock);
37062306a36Sopenharmony_ci
37162306a36Sopenharmony_ci		/*
37262306a36Sopenharmony_ci		 * Resume suppliers if necessary.
37362306a36Sopenharmony_ci		 *
37462306a36Sopenharmony_ci		 * The device's runtime PM status cannot change until this
37562306a36Sopenharmony_ci		 * routine returns, so it is safe to read the status outside of
37662306a36Sopenharmony_ci		 * the lock.
37762306a36Sopenharmony_ci		 */
37862306a36Sopenharmony_ci		if (use_links && dev->power.runtime_status == RPM_RESUMING) {
37962306a36Sopenharmony_ci			idx = device_links_read_lock();
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci			retval = rpm_get_suppliers(dev);
38262306a36Sopenharmony_ci			if (retval) {
38362306a36Sopenharmony_ci				rpm_put_suppliers(dev);
38462306a36Sopenharmony_ci				goto fail;
38562306a36Sopenharmony_ci			}
38662306a36Sopenharmony_ci
38762306a36Sopenharmony_ci			device_links_read_unlock(idx);
38862306a36Sopenharmony_ci		}
38962306a36Sopenharmony_ci	}
39062306a36Sopenharmony_ci
39162306a36Sopenharmony_ci	if (cb)
39262306a36Sopenharmony_ci		retval = cb(dev);
39362306a36Sopenharmony_ci
39462306a36Sopenharmony_ci	if (dev->power.irq_safe) {
39562306a36Sopenharmony_ci		spin_lock(&dev->power.lock);
39662306a36Sopenharmony_ci	} else {
39762306a36Sopenharmony_ci		/*
39862306a36Sopenharmony_ci		 * If the device is suspending and the callback has returned
39962306a36Sopenharmony_ci		 * success, drop the usage counters of the suppliers that have
40062306a36Sopenharmony_ci		 * been reference counted on its resume.
40162306a36Sopenharmony_ci		 *
40262306a36Sopenharmony_ci		 * Do that if resume fails too.
40362306a36Sopenharmony_ci		 */
40462306a36Sopenharmony_ci		if (use_links &&
40562306a36Sopenharmony_ci		    ((dev->power.runtime_status == RPM_SUSPENDING && !retval) ||
40662306a36Sopenharmony_ci		    (dev->power.runtime_status == RPM_RESUMING && retval))) {
40762306a36Sopenharmony_ci			idx = device_links_read_lock();
40862306a36Sopenharmony_ci
40962306a36Sopenharmony_ci			__rpm_put_suppliers(dev, false);
41062306a36Sopenharmony_ci
41162306a36Sopenharmony_cifail:
41262306a36Sopenharmony_ci			device_links_read_unlock(idx);
41362306a36Sopenharmony_ci		}
41462306a36Sopenharmony_ci
41562306a36Sopenharmony_ci		spin_lock_irq(&dev->power.lock);
41662306a36Sopenharmony_ci	}
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_ci	return retval;
41962306a36Sopenharmony_ci}
42062306a36Sopenharmony_ci
42162306a36Sopenharmony_ci/**
42262306a36Sopenharmony_ci * rpm_callback - Run a given runtime PM callback for a given device.
42362306a36Sopenharmony_ci * @cb: Runtime PM callback to run.
42462306a36Sopenharmony_ci * @dev: Device to run the callback for.
42562306a36Sopenharmony_ci */
42662306a36Sopenharmony_cistatic int rpm_callback(int (*cb)(struct device *), struct device *dev)
42762306a36Sopenharmony_ci{
42862306a36Sopenharmony_ci	int retval;
42962306a36Sopenharmony_ci
43062306a36Sopenharmony_ci	if (dev->power.memalloc_noio) {
43162306a36Sopenharmony_ci		unsigned int noio_flag;
43262306a36Sopenharmony_ci
43362306a36Sopenharmony_ci		/*
43462306a36Sopenharmony_ci		 * Deadlock might be caused if memory allocation with
43562306a36Sopenharmony_ci		 * GFP_KERNEL happens inside runtime_suspend and
43662306a36Sopenharmony_ci		 * runtime_resume callbacks of one block device's
43762306a36Sopenharmony_ci		 * ancestor or the block device itself. Network
43862306a36Sopenharmony_ci		 * device might be thought as part of iSCSI block
43962306a36Sopenharmony_ci		 * device, so network device and its ancestor should
44062306a36Sopenharmony_ci		 * be marked as memalloc_noio too.
44162306a36Sopenharmony_ci		 */
44262306a36Sopenharmony_ci		noio_flag = memalloc_noio_save();
44362306a36Sopenharmony_ci		retval = __rpm_callback(cb, dev);
44462306a36Sopenharmony_ci		memalloc_noio_restore(noio_flag);
44562306a36Sopenharmony_ci	} else {
44662306a36Sopenharmony_ci		retval = __rpm_callback(cb, dev);
44762306a36Sopenharmony_ci	}
44862306a36Sopenharmony_ci
44962306a36Sopenharmony_ci	dev->power.runtime_error = retval;
45062306a36Sopenharmony_ci	return retval != -EACCES ? retval : -EIO;
45162306a36Sopenharmony_ci}
45262306a36Sopenharmony_ci
45362306a36Sopenharmony_ci/**
45462306a36Sopenharmony_ci * rpm_idle - Notify device bus type if the device can be suspended.
45562306a36Sopenharmony_ci * @dev: Device to notify the bus type about.
45662306a36Sopenharmony_ci * @rpmflags: Flag bits.
45762306a36Sopenharmony_ci *
45862306a36Sopenharmony_ci * Check if the device's runtime PM status allows it to be suspended.  If
45962306a36Sopenharmony_ci * another idle notification has been started earlier, return immediately.  If
46062306a36Sopenharmony_ci * the RPM_ASYNC flag is set then queue an idle-notification request; otherwise
46162306a36Sopenharmony_ci * run the ->runtime_idle() callback directly. If the ->runtime_idle callback
46262306a36Sopenharmony_ci * doesn't exist or if it returns 0, call rpm_suspend with the RPM_AUTO flag.
46362306a36Sopenharmony_ci *
46462306a36Sopenharmony_ci * This function must be called under dev->power.lock with interrupts disabled.
46562306a36Sopenharmony_ci */
46662306a36Sopenharmony_cistatic int rpm_idle(struct device *dev, int rpmflags)
46762306a36Sopenharmony_ci{
46862306a36Sopenharmony_ci	int (*callback)(struct device *);
46962306a36Sopenharmony_ci	int retval;
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_ci	trace_rpm_idle(dev, rpmflags);
47262306a36Sopenharmony_ci	retval = rpm_check_suspend_allowed(dev);
47362306a36Sopenharmony_ci	if (retval < 0)
47462306a36Sopenharmony_ci		;	/* Conditions are wrong. */
47562306a36Sopenharmony_ci
47662306a36Sopenharmony_ci	/* Idle notifications are allowed only in the RPM_ACTIVE state. */
47762306a36Sopenharmony_ci	else if (dev->power.runtime_status != RPM_ACTIVE)
47862306a36Sopenharmony_ci		retval = -EAGAIN;
47962306a36Sopenharmony_ci
48062306a36Sopenharmony_ci	/*
48162306a36Sopenharmony_ci	 * Any pending request other than an idle notification takes
48262306a36Sopenharmony_ci	 * precedence over us, except that the timer may be running.
48362306a36Sopenharmony_ci	 */
48462306a36Sopenharmony_ci	else if (dev->power.request_pending &&
48562306a36Sopenharmony_ci	    dev->power.request > RPM_REQ_IDLE)
48662306a36Sopenharmony_ci		retval = -EAGAIN;
48762306a36Sopenharmony_ci
48862306a36Sopenharmony_ci	/* Act as though RPM_NOWAIT is always set. */
48962306a36Sopenharmony_ci	else if (dev->power.idle_notification)
49062306a36Sopenharmony_ci		retval = -EINPROGRESS;
49162306a36Sopenharmony_ci
49262306a36Sopenharmony_ci	if (retval)
49362306a36Sopenharmony_ci		goto out;
49462306a36Sopenharmony_ci
49562306a36Sopenharmony_ci	/* Pending requests need to be canceled. */
49662306a36Sopenharmony_ci	dev->power.request = RPM_REQ_NONE;
49762306a36Sopenharmony_ci
49862306a36Sopenharmony_ci	callback = RPM_GET_CALLBACK(dev, runtime_idle);
49962306a36Sopenharmony_ci
50062306a36Sopenharmony_ci	/* If no callback assume success. */
50162306a36Sopenharmony_ci	if (!callback || dev->power.no_callbacks)
50262306a36Sopenharmony_ci		goto out;
50362306a36Sopenharmony_ci
50462306a36Sopenharmony_ci	/* Carry out an asynchronous or a synchronous idle notification. */
50562306a36Sopenharmony_ci	if (rpmflags & RPM_ASYNC) {
50662306a36Sopenharmony_ci		dev->power.request = RPM_REQ_IDLE;
50762306a36Sopenharmony_ci		if (!dev->power.request_pending) {
50862306a36Sopenharmony_ci			dev->power.request_pending = true;
50962306a36Sopenharmony_ci			queue_work(pm_wq, &dev->power.work);
51062306a36Sopenharmony_ci		}
51162306a36Sopenharmony_ci		trace_rpm_return_int(dev, _THIS_IP_, 0);
51262306a36Sopenharmony_ci		return 0;
51362306a36Sopenharmony_ci	}
51462306a36Sopenharmony_ci
51562306a36Sopenharmony_ci	dev->power.idle_notification = true;
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_ci	if (dev->power.irq_safe)
51862306a36Sopenharmony_ci		spin_unlock(&dev->power.lock);
51962306a36Sopenharmony_ci	else
52062306a36Sopenharmony_ci		spin_unlock_irq(&dev->power.lock);
52162306a36Sopenharmony_ci
52262306a36Sopenharmony_ci	retval = callback(dev);
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ci	if (dev->power.irq_safe)
52562306a36Sopenharmony_ci		spin_lock(&dev->power.lock);
52662306a36Sopenharmony_ci	else
52762306a36Sopenharmony_ci		spin_lock_irq(&dev->power.lock);
52862306a36Sopenharmony_ci
52962306a36Sopenharmony_ci	dev->power.idle_notification = false;
53062306a36Sopenharmony_ci	wake_up_all(&dev->power.wait_queue);
53162306a36Sopenharmony_ci
53262306a36Sopenharmony_ci out:
53362306a36Sopenharmony_ci	trace_rpm_return_int(dev, _THIS_IP_, retval);
53462306a36Sopenharmony_ci	return retval ? retval : rpm_suspend(dev, rpmflags | RPM_AUTO);
53562306a36Sopenharmony_ci}
53662306a36Sopenharmony_ci
53762306a36Sopenharmony_ci/**
53862306a36Sopenharmony_ci * rpm_suspend - Carry out runtime suspend of given device.
53962306a36Sopenharmony_ci * @dev: Device to suspend.
54062306a36Sopenharmony_ci * @rpmflags: Flag bits.
54162306a36Sopenharmony_ci *
54262306a36Sopenharmony_ci * Check if the device's runtime PM status allows it to be suspended.
54362306a36Sopenharmony_ci * Cancel a pending idle notification, autosuspend or suspend. If
54462306a36Sopenharmony_ci * another suspend has been started earlier, either return immediately
54562306a36Sopenharmony_ci * or wait for it to finish, depending on the RPM_NOWAIT and RPM_ASYNC
54662306a36Sopenharmony_ci * flags. If the RPM_ASYNC flag is set then queue a suspend request;
54762306a36Sopenharmony_ci * otherwise run the ->runtime_suspend() callback directly. When
54862306a36Sopenharmony_ci * ->runtime_suspend succeeded, if a deferred resume was requested while
54962306a36Sopenharmony_ci * the callback was running then carry it out, otherwise send an idle
55062306a36Sopenharmony_ci * notification for its parent (if the suspend succeeded and both
55162306a36Sopenharmony_ci * ignore_children of parent->power and irq_safe of dev->power are not set).
55262306a36Sopenharmony_ci * If ->runtime_suspend failed with -EAGAIN or -EBUSY, and if the RPM_AUTO
55362306a36Sopenharmony_ci * flag is set and the next autosuspend-delay expiration time is in the
55462306a36Sopenharmony_ci * future, schedule another autosuspend attempt.
55562306a36Sopenharmony_ci *
55662306a36Sopenharmony_ci * This function must be called under dev->power.lock with interrupts disabled.
55762306a36Sopenharmony_ci */
55862306a36Sopenharmony_cistatic int rpm_suspend(struct device *dev, int rpmflags)
55962306a36Sopenharmony_ci	__releases(&dev->power.lock) __acquires(&dev->power.lock)
56062306a36Sopenharmony_ci{
56162306a36Sopenharmony_ci	int (*callback)(struct device *);
56262306a36Sopenharmony_ci	struct device *parent = NULL;
56362306a36Sopenharmony_ci	int retval;
56462306a36Sopenharmony_ci
56562306a36Sopenharmony_ci	trace_rpm_suspend(dev, rpmflags);
56662306a36Sopenharmony_ci
56762306a36Sopenharmony_ci repeat:
56862306a36Sopenharmony_ci	retval = rpm_check_suspend_allowed(dev);
56962306a36Sopenharmony_ci	if (retval < 0)
57062306a36Sopenharmony_ci		goto out;	/* Conditions are wrong. */
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	/* Synchronous suspends are not allowed in the RPM_RESUMING state. */
57362306a36Sopenharmony_ci	if (dev->power.runtime_status == RPM_RESUMING && !(rpmflags & RPM_ASYNC))
57462306a36Sopenharmony_ci		retval = -EAGAIN;
57562306a36Sopenharmony_ci
57662306a36Sopenharmony_ci	if (retval)
57762306a36Sopenharmony_ci		goto out;
57862306a36Sopenharmony_ci
57962306a36Sopenharmony_ci	/* If the autosuspend_delay time hasn't expired yet, reschedule. */
58062306a36Sopenharmony_ci	if ((rpmflags & RPM_AUTO) && dev->power.runtime_status != RPM_SUSPENDING) {
58162306a36Sopenharmony_ci		u64 expires = pm_runtime_autosuspend_expiration(dev);
58262306a36Sopenharmony_ci
58362306a36Sopenharmony_ci		if (expires != 0) {
58462306a36Sopenharmony_ci			/* Pending requests need to be canceled. */
58562306a36Sopenharmony_ci			dev->power.request = RPM_REQ_NONE;
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci			/*
58862306a36Sopenharmony_ci			 * Optimization: If the timer is already running and is
58962306a36Sopenharmony_ci			 * set to expire at or before the autosuspend delay,
59062306a36Sopenharmony_ci			 * avoid the overhead of resetting it.  Just let it
59162306a36Sopenharmony_ci			 * expire; pm_suspend_timer_fn() will take care of the
59262306a36Sopenharmony_ci			 * rest.
59362306a36Sopenharmony_ci			 */
59462306a36Sopenharmony_ci			if (!(dev->power.timer_expires &&
59562306a36Sopenharmony_ci			    dev->power.timer_expires <= expires)) {
59662306a36Sopenharmony_ci				/*
59762306a36Sopenharmony_ci				 * We add a slack of 25% to gather wakeups
59862306a36Sopenharmony_ci				 * without sacrificing the granularity.
59962306a36Sopenharmony_ci				 */
60062306a36Sopenharmony_ci				u64 slack = (u64)READ_ONCE(dev->power.autosuspend_delay) *
60162306a36Sopenharmony_ci						    (NSEC_PER_MSEC >> 2);
60262306a36Sopenharmony_ci
60362306a36Sopenharmony_ci				dev->power.timer_expires = expires;
60462306a36Sopenharmony_ci				hrtimer_start_range_ns(&dev->power.suspend_timer,
60562306a36Sopenharmony_ci						       ns_to_ktime(expires),
60662306a36Sopenharmony_ci						       slack,
60762306a36Sopenharmony_ci						       HRTIMER_MODE_ABS);
60862306a36Sopenharmony_ci			}
60962306a36Sopenharmony_ci			dev->power.timer_autosuspends = 1;
61062306a36Sopenharmony_ci			goto out;
61162306a36Sopenharmony_ci		}
61262306a36Sopenharmony_ci	}
61362306a36Sopenharmony_ci
61462306a36Sopenharmony_ci	/* Other scheduled or pending requests need to be canceled. */
61562306a36Sopenharmony_ci	pm_runtime_cancel_pending(dev);
61662306a36Sopenharmony_ci
61762306a36Sopenharmony_ci	if (dev->power.runtime_status == RPM_SUSPENDING) {
61862306a36Sopenharmony_ci		DEFINE_WAIT(wait);
61962306a36Sopenharmony_ci
62062306a36Sopenharmony_ci		if (rpmflags & (RPM_ASYNC | RPM_NOWAIT)) {
62162306a36Sopenharmony_ci			retval = -EINPROGRESS;
62262306a36Sopenharmony_ci			goto out;
62362306a36Sopenharmony_ci		}
62462306a36Sopenharmony_ci
62562306a36Sopenharmony_ci		if (dev->power.irq_safe) {
62662306a36Sopenharmony_ci			spin_unlock(&dev->power.lock);
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci			cpu_relax();
62962306a36Sopenharmony_ci
63062306a36Sopenharmony_ci			spin_lock(&dev->power.lock);
63162306a36Sopenharmony_ci			goto repeat;
63262306a36Sopenharmony_ci		}
63362306a36Sopenharmony_ci
63462306a36Sopenharmony_ci		/* Wait for the other suspend running in parallel with us. */
63562306a36Sopenharmony_ci		for (;;) {
63662306a36Sopenharmony_ci			prepare_to_wait(&dev->power.wait_queue, &wait,
63762306a36Sopenharmony_ci					TASK_UNINTERRUPTIBLE);
63862306a36Sopenharmony_ci			if (dev->power.runtime_status != RPM_SUSPENDING)
63962306a36Sopenharmony_ci				break;
64062306a36Sopenharmony_ci
64162306a36Sopenharmony_ci			spin_unlock_irq(&dev->power.lock);
64262306a36Sopenharmony_ci
64362306a36Sopenharmony_ci			schedule();
64462306a36Sopenharmony_ci
64562306a36Sopenharmony_ci			spin_lock_irq(&dev->power.lock);
64662306a36Sopenharmony_ci		}
64762306a36Sopenharmony_ci		finish_wait(&dev->power.wait_queue, &wait);
64862306a36Sopenharmony_ci		goto repeat;
64962306a36Sopenharmony_ci	}
65062306a36Sopenharmony_ci
65162306a36Sopenharmony_ci	if (dev->power.no_callbacks)
65262306a36Sopenharmony_ci		goto no_callback;	/* Assume success. */
65362306a36Sopenharmony_ci
65462306a36Sopenharmony_ci	/* Carry out an asynchronous or a synchronous suspend. */
65562306a36Sopenharmony_ci	if (rpmflags & RPM_ASYNC) {
65662306a36Sopenharmony_ci		dev->power.request = (rpmflags & RPM_AUTO) ?
65762306a36Sopenharmony_ci		    RPM_REQ_AUTOSUSPEND : RPM_REQ_SUSPEND;
65862306a36Sopenharmony_ci		if (!dev->power.request_pending) {
65962306a36Sopenharmony_ci			dev->power.request_pending = true;
66062306a36Sopenharmony_ci			queue_work(pm_wq, &dev->power.work);
66162306a36Sopenharmony_ci		}
66262306a36Sopenharmony_ci		goto out;
66362306a36Sopenharmony_ci	}
66462306a36Sopenharmony_ci
66562306a36Sopenharmony_ci	__update_runtime_status(dev, RPM_SUSPENDING);
66662306a36Sopenharmony_ci
66762306a36Sopenharmony_ci	callback = RPM_GET_CALLBACK(dev, runtime_suspend);
66862306a36Sopenharmony_ci
66962306a36Sopenharmony_ci	dev_pm_enable_wake_irq_check(dev, true);
67062306a36Sopenharmony_ci	retval = rpm_callback(callback, dev);
67162306a36Sopenharmony_ci	if (retval)
67262306a36Sopenharmony_ci		goto fail;
67362306a36Sopenharmony_ci
67462306a36Sopenharmony_ci	dev_pm_enable_wake_irq_complete(dev);
67562306a36Sopenharmony_ci
67662306a36Sopenharmony_ci no_callback:
67762306a36Sopenharmony_ci	__update_runtime_status(dev, RPM_SUSPENDED);
67862306a36Sopenharmony_ci	pm_runtime_deactivate_timer(dev);
67962306a36Sopenharmony_ci
68062306a36Sopenharmony_ci	if (dev->parent) {
68162306a36Sopenharmony_ci		parent = dev->parent;
68262306a36Sopenharmony_ci		atomic_add_unless(&parent->power.child_count, -1, 0);
68362306a36Sopenharmony_ci	}
68462306a36Sopenharmony_ci	wake_up_all(&dev->power.wait_queue);
68562306a36Sopenharmony_ci
68662306a36Sopenharmony_ci	if (dev->power.deferred_resume) {
68762306a36Sopenharmony_ci		dev->power.deferred_resume = false;
68862306a36Sopenharmony_ci		rpm_resume(dev, 0);
68962306a36Sopenharmony_ci		retval = -EAGAIN;
69062306a36Sopenharmony_ci		goto out;
69162306a36Sopenharmony_ci	}
69262306a36Sopenharmony_ci
69362306a36Sopenharmony_ci	if (dev->power.irq_safe)
69462306a36Sopenharmony_ci		goto out;
69562306a36Sopenharmony_ci
69662306a36Sopenharmony_ci	/* Maybe the parent is now able to suspend. */
69762306a36Sopenharmony_ci	if (parent && !parent->power.ignore_children) {
69862306a36Sopenharmony_ci		spin_unlock(&dev->power.lock);
69962306a36Sopenharmony_ci
70062306a36Sopenharmony_ci		spin_lock(&parent->power.lock);
70162306a36Sopenharmony_ci		rpm_idle(parent, RPM_ASYNC);
70262306a36Sopenharmony_ci		spin_unlock(&parent->power.lock);
70362306a36Sopenharmony_ci
70462306a36Sopenharmony_ci		spin_lock(&dev->power.lock);
70562306a36Sopenharmony_ci	}
70662306a36Sopenharmony_ci	/* Maybe the suppliers are now able to suspend. */
70762306a36Sopenharmony_ci	if (dev->power.links_count > 0) {
70862306a36Sopenharmony_ci		spin_unlock_irq(&dev->power.lock);
70962306a36Sopenharmony_ci
71062306a36Sopenharmony_ci		rpm_suspend_suppliers(dev);
71162306a36Sopenharmony_ci
71262306a36Sopenharmony_ci		spin_lock_irq(&dev->power.lock);
71362306a36Sopenharmony_ci	}
71462306a36Sopenharmony_ci
71562306a36Sopenharmony_ci out:
71662306a36Sopenharmony_ci	trace_rpm_return_int(dev, _THIS_IP_, retval);
71762306a36Sopenharmony_ci
71862306a36Sopenharmony_ci	return retval;
71962306a36Sopenharmony_ci
72062306a36Sopenharmony_ci fail:
72162306a36Sopenharmony_ci	dev_pm_disable_wake_irq_check(dev, true);
72262306a36Sopenharmony_ci	__update_runtime_status(dev, RPM_ACTIVE);
72362306a36Sopenharmony_ci	dev->power.deferred_resume = false;
72462306a36Sopenharmony_ci	wake_up_all(&dev->power.wait_queue);
72562306a36Sopenharmony_ci
72662306a36Sopenharmony_ci	if (retval == -EAGAIN || retval == -EBUSY) {
72762306a36Sopenharmony_ci		dev->power.runtime_error = 0;
72862306a36Sopenharmony_ci
72962306a36Sopenharmony_ci		/*
73062306a36Sopenharmony_ci		 * If the callback routine failed an autosuspend, and
73162306a36Sopenharmony_ci		 * if the last_busy time has been updated so that there
73262306a36Sopenharmony_ci		 * is a new autosuspend expiration time, automatically
73362306a36Sopenharmony_ci		 * reschedule another autosuspend.
73462306a36Sopenharmony_ci		 */
73562306a36Sopenharmony_ci		if ((rpmflags & RPM_AUTO) &&
73662306a36Sopenharmony_ci		    pm_runtime_autosuspend_expiration(dev) != 0)
73762306a36Sopenharmony_ci			goto repeat;
73862306a36Sopenharmony_ci	} else {
73962306a36Sopenharmony_ci		pm_runtime_cancel_pending(dev);
74062306a36Sopenharmony_ci	}
74162306a36Sopenharmony_ci	goto out;
74262306a36Sopenharmony_ci}
74362306a36Sopenharmony_ci
74462306a36Sopenharmony_ci/**
74562306a36Sopenharmony_ci * rpm_resume - Carry out runtime resume of given device.
74662306a36Sopenharmony_ci * @dev: Device to resume.
74762306a36Sopenharmony_ci * @rpmflags: Flag bits.
74862306a36Sopenharmony_ci *
74962306a36Sopenharmony_ci * Check if the device's runtime PM status allows it to be resumed.  Cancel
75062306a36Sopenharmony_ci * any scheduled or pending requests.  If another resume has been started
75162306a36Sopenharmony_ci * earlier, either return immediately or wait for it to finish, depending on the
75262306a36Sopenharmony_ci * RPM_NOWAIT and RPM_ASYNC flags.  Similarly, if there's a suspend running in
75362306a36Sopenharmony_ci * parallel with this function, either tell the other process to resume after
75462306a36Sopenharmony_ci * suspending (deferred_resume) or wait for it to finish.  If the RPM_ASYNC
75562306a36Sopenharmony_ci * flag is set then queue a resume request; otherwise run the
75662306a36Sopenharmony_ci * ->runtime_resume() callback directly.  Queue an idle notification for the
75762306a36Sopenharmony_ci * device if the resume succeeded.
75862306a36Sopenharmony_ci *
75962306a36Sopenharmony_ci * This function must be called under dev->power.lock with interrupts disabled.
76062306a36Sopenharmony_ci */
76162306a36Sopenharmony_cistatic int rpm_resume(struct device *dev, int rpmflags)
76262306a36Sopenharmony_ci	__releases(&dev->power.lock) __acquires(&dev->power.lock)
76362306a36Sopenharmony_ci{
76462306a36Sopenharmony_ci	int (*callback)(struct device *);
76562306a36Sopenharmony_ci	struct device *parent = NULL;
76662306a36Sopenharmony_ci	int retval = 0;
76762306a36Sopenharmony_ci
76862306a36Sopenharmony_ci	trace_rpm_resume(dev, rpmflags);
76962306a36Sopenharmony_ci
77062306a36Sopenharmony_ci repeat:
77162306a36Sopenharmony_ci	if (dev->power.runtime_error) {
77262306a36Sopenharmony_ci		retval = -EINVAL;
77362306a36Sopenharmony_ci	} else if (dev->power.disable_depth > 0) {
77462306a36Sopenharmony_ci		if (dev->power.runtime_status == RPM_ACTIVE &&
77562306a36Sopenharmony_ci		    dev->power.last_status == RPM_ACTIVE)
77662306a36Sopenharmony_ci			retval = 1;
77762306a36Sopenharmony_ci		else
77862306a36Sopenharmony_ci			retval = -EACCES;
77962306a36Sopenharmony_ci	}
78062306a36Sopenharmony_ci	if (retval)
78162306a36Sopenharmony_ci		goto out;
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci	/*
78462306a36Sopenharmony_ci	 * Other scheduled or pending requests need to be canceled.  Small
78562306a36Sopenharmony_ci	 * optimization: If an autosuspend timer is running, leave it running
78662306a36Sopenharmony_ci	 * rather than cancelling it now only to restart it again in the near
78762306a36Sopenharmony_ci	 * future.
78862306a36Sopenharmony_ci	 */
78962306a36Sopenharmony_ci	dev->power.request = RPM_REQ_NONE;
79062306a36Sopenharmony_ci	if (!dev->power.timer_autosuspends)
79162306a36Sopenharmony_ci		pm_runtime_deactivate_timer(dev);
79262306a36Sopenharmony_ci
79362306a36Sopenharmony_ci	if (dev->power.runtime_status == RPM_ACTIVE) {
79462306a36Sopenharmony_ci		retval = 1;
79562306a36Sopenharmony_ci		goto out;
79662306a36Sopenharmony_ci	}
79762306a36Sopenharmony_ci
79862306a36Sopenharmony_ci	if (dev->power.runtime_status == RPM_RESUMING ||
79962306a36Sopenharmony_ci	    dev->power.runtime_status == RPM_SUSPENDING) {
80062306a36Sopenharmony_ci		DEFINE_WAIT(wait);
80162306a36Sopenharmony_ci
80262306a36Sopenharmony_ci		if (rpmflags & (RPM_ASYNC | RPM_NOWAIT)) {
80362306a36Sopenharmony_ci			if (dev->power.runtime_status == RPM_SUSPENDING) {
80462306a36Sopenharmony_ci				dev->power.deferred_resume = true;
80562306a36Sopenharmony_ci				if (rpmflags & RPM_NOWAIT)
80662306a36Sopenharmony_ci					retval = -EINPROGRESS;
80762306a36Sopenharmony_ci			} else {
80862306a36Sopenharmony_ci				retval = -EINPROGRESS;
80962306a36Sopenharmony_ci			}
81062306a36Sopenharmony_ci			goto out;
81162306a36Sopenharmony_ci		}
81262306a36Sopenharmony_ci
81362306a36Sopenharmony_ci		if (dev->power.irq_safe) {
81462306a36Sopenharmony_ci			spin_unlock(&dev->power.lock);
81562306a36Sopenharmony_ci
81662306a36Sopenharmony_ci			cpu_relax();
81762306a36Sopenharmony_ci
81862306a36Sopenharmony_ci			spin_lock(&dev->power.lock);
81962306a36Sopenharmony_ci			goto repeat;
82062306a36Sopenharmony_ci		}
82162306a36Sopenharmony_ci
82262306a36Sopenharmony_ci		/* Wait for the operation carried out in parallel with us. */
82362306a36Sopenharmony_ci		for (;;) {
82462306a36Sopenharmony_ci			prepare_to_wait(&dev->power.wait_queue, &wait,
82562306a36Sopenharmony_ci					TASK_UNINTERRUPTIBLE);
82662306a36Sopenharmony_ci			if (dev->power.runtime_status != RPM_RESUMING &&
82762306a36Sopenharmony_ci			    dev->power.runtime_status != RPM_SUSPENDING)
82862306a36Sopenharmony_ci				break;
82962306a36Sopenharmony_ci
83062306a36Sopenharmony_ci			spin_unlock_irq(&dev->power.lock);
83162306a36Sopenharmony_ci
83262306a36Sopenharmony_ci			schedule();
83362306a36Sopenharmony_ci
83462306a36Sopenharmony_ci			spin_lock_irq(&dev->power.lock);
83562306a36Sopenharmony_ci		}
83662306a36Sopenharmony_ci		finish_wait(&dev->power.wait_queue, &wait);
83762306a36Sopenharmony_ci		goto repeat;
83862306a36Sopenharmony_ci	}
83962306a36Sopenharmony_ci
84062306a36Sopenharmony_ci	/*
84162306a36Sopenharmony_ci	 * See if we can skip waking up the parent.  This is safe only if
84262306a36Sopenharmony_ci	 * power.no_callbacks is set, because otherwise we don't know whether
84362306a36Sopenharmony_ci	 * the resume will actually succeed.
84462306a36Sopenharmony_ci	 */
84562306a36Sopenharmony_ci	if (dev->power.no_callbacks && !parent && dev->parent) {
84662306a36Sopenharmony_ci		spin_lock_nested(&dev->parent->power.lock, SINGLE_DEPTH_NESTING);
84762306a36Sopenharmony_ci		if (dev->parent->power.disable_depth > 0 ||
84862306a36Sopenharmony_ci		    dev->parent->power.ignore_children ||
84962306a36Sopenharmony_ci		    dev->parent->power.runtime_status == RPM_ACTIVE) {
85062306a36Sopenharmony_ci			atomic_inc(&dev->parent->power.child_count);
85162306a36Sopenharmony_ci			spin_unlock(&dev->parent->power.lock);
85262306a36Sopenharmony_ci			retval = 1;
85362306a36Sopenharmony_ci			goto no_callback;	/* Assume success. */
85462306a36Sopenharmony_ci		}
85562306a36Sopenharmony_ci		spin_unlock(&dev->parent->power.lock);
85662306a36Sopenharmony_ci	}
85762306a36Sopenharmony_ci
85862306a36Sopenharmony_ci	/* Carry out an asynchronous or a synchronous resume. */
85962306a36Sopenharmony_ci	if (rpmflags & RPM_ASYNC) {
86062306a36Sopenharmony_ci		dev->power.request = RPM_REQ_RESUME;
86162306a36Sopenharmony_ci		if (!dev->power.request_pending) {
86262306a36Sopenharmony_ci			dev->power.request_pending = true;
86362306a36Sopenharmony_ci			queue_work(pm_wq, &dev->power.work);
86462306a36Sopenharmony_ci		}
86562306a36Sopenharmony_ci		retval = 0;
86662306a36Sopenharmony_ci		goto out;
86762306a36Sopenharmony_ci	}
86862306a36Sopenharmony_ci
86962306a36Sopenharmony_ci	if (!parent && dev->parent) {
87062306a36Sopenharmony_ci		/*
87162306a36Sopenharmony_ci		 * Increment the parent's usage counter and resume it if
87262306a36Sopenharmony_ci		 * necessary.  Not needed if dev is irq-safe; then the
87362306a36Sopenharmony_ci		 * parent is permanently resumed.
87462306a36Sopenharmony_ci		 */
87562306a36Sopenharmony_ci		parent = dev->parent;
87662306a36Sopenharmony_ci		if (dev->power.irq_safe)
87762306a36Sopenharmony_ci			goto skip_parent;
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci		spin_unlock(&dev->power.lock);
88062306a36Sopenharmony_ci
88162306a36Sopenharmony_ci		pm_runtime_get_noresume(parent);
88262306a36Sopenharmony_ci
88362306a36Sopenharmony_ci		spin_lock(&parent->power.lock);
88462306a36Sopenharmony_ci		/*
88562306a36Sopenharmony_ci		 * Resume the parent if it has runtime PM enabled and not been
88662306a36Sopenharmony_ci		 * set to ignore its children.
88762306a36Sopenharmony_ci		 */
88862306a36Sopenharmony_ci		if (!parent->power.disable_depth &&
88962306a36Sopenharmony_ci		    !parent->power.ignore_children) {
89062306a36Sopenharmony_ci			rpm_resume(parent, 0);
89162306a36Sopenharmony_ci			if (parent->power.runtime_status != RPM_ACTIVE)
89262306a36Sopenharmony_ci				retval = -EBUSY;
89362306a36Sopenharmony_ci		}
89462306a36Sopenharmony_ci		spin_unlock(&parent->power.lock);
89562306a36Sopenharmony_ci
89662306a36Sopenharmony_ci		spin_lock(&dev->power.lock);
89762306a36Sopenharmony_ci		if (retval)
89862306a36Sopenharmony_ci			goto out;
89962306a36Sopenharmony_ci
90062306a36Sopenharmony_ci		goto repeat;
90162306a36Sopenharmony_ci	}
90262306a36Sopenharmony_ci skip_parent:
90362306a36Sopenharmony_ci
90462306a36Sopenharmony_ci	if (dev->power.no_callbacks)
90562306a36Sopenharmony_ci		goto no_callback;	/* Assume success. */
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci	__update_runtime_status(dev, RPM_RESUMING);
90862306a36Sopenharmony_ci
90962306a36Sopenharmony_ci	callback = RPM_GET_CALLBACK(dev, runtime_resume);
91062306a36Sopenharmony_ci
91162306a36Sopenharmony_ci	dev_pm_disable_wake_irq_check(dev, false);
91262306a36Sopenharmony_ci	retval = rpm_callback(callback, dev);
91362306a36Sopenharmony_ci	if (retval) {
91462306a36Sopenharmony_ci		__update_runtime_status(dev, RPM_SUSPENDED);
91562306a36Sopenharmony_ci		pm_runtime_cancel_pending(dev);
91662306a36Sopenharmony_ci		dev_pm_enable_wake_irq_check(dev, false);
91762306a36Sopenharmony_ci	} else {
91862306a36Sopenharmony_ci no_callback:
91962306a36Sopenharmony_ci		__update_runtime_status(dev, RPM_ACTIVE);
92062306a36Sopenharmony_ci		pm_runtime_mark_last_busy(dev);
92162306a36Sopenharmony_ci		if (parent)
92262306a36Sopenharmony_ci			atomic_inc(&parent->power.child_count);
92362306a36Sopenharmony_ci	}
92462306a36Sopenharmony_ci	wake_up_all(&dev->power.wait_queue);
92562306a36Sopenharmony_ci
92662306a36Sopenharmony_ci	if (retval >= 0)
92762306a36Sopenharmony_ci		rpm_idle(dev, RPM_ASYNC);
92862306a36Sopenharmony_ci
92962306a36Sopenharmony_ci out:
93062306a36Sopenharmony_ci	if (parent && !dev->power.irq_safe) {
93162306a36Sopenharmony_ci		spin_unlock_irq(&dev->power.lock);
93262306a36Sopenharmony_ci
93362306a36Sopenharmony_ci		pm_runtime_put(parent);
93462306a36Sopenharmony_ci
93562306a36Sopenharmony_ci		spin_lock_irq(&dev->power.lock);
93662306a36Sopenharmony_ci	}
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_ci	trace_rpm_return_int(dev, _THIS_IP_, retval);
93962306a36Sopenharmony_ci
94062306a36Sopenharmony_ci	return retval;
94162306a36Sopenharmony_ci}
94262306a36Sopenharmony_ci
94362306a36Sopenharmony_ci/**
94462306a36Sopenharmony_ci * pm_runtime_work - Universal runtime PM work function.
94562306a36Sopenharmony_ci * @work: Work structure used for scheduling the execution of this function.
94662306a36Sopenharmony_ci *
94762306a36Sopenharmony_ci * Use @work to get the device object the work is to be done for, determine what
94862306a36Sopenharmony_ci * is to be done and execute the appropriate runtime PM function.
94962306a36Sopenharmony_ci */
95062306a36Sopenharmony_cistatic void pm_runtime_work(struct work_struct *work)
95162306a36Sopenharmony_ci{
95262306a36Sopenharmony_ci	struct device *dev = container_of(work, struct device, power.work);
95362306a36Sopenharmony_ci	enum rpm_request req;
95462306a36Sopenharmony_ci
95562306a36Sopenharmony_ci	spin_lock_irq(&dev->power.lock);
95662306a36Sopenharmony_ci
95762306a36Sopenharmony_ci	if (!dev->power.request_pending)
95862306a36Sopenharmony_ci		goto out;
95962306a36Sopenharmony_ci
96062306a36Sopenharmony_ci	req = dev->power.request;
96162306a36Sopenharmony_ci	dev->power.request = RPM_REQ_NONE;
96262306a36Sopenharmony_ci	dev->power.request_pending = false;
96362306a36Sopenharmony_ci
96462306a36Sopenharmony_ci	switch (req) {
96562306a36Sopenharmony_ci	case RPM_REQ_NONE:
96662306a36Sopenharmony_ci		break;
96762306a36Sopenharmony_ci	case RPM_REQ_IDLE:
96862306a36Sopenharmony_ci		rpm_idle(dev, RPM_NOWAIT);
96962306a36Sopenharmony_ci		break;
97062306a36Sopenharmony_ci	case RPM_REQ_SUSPEND:
97162306a36Sopenharmony_ci		rpm_suspend(dev, RPM_NOWAIT);
97262306a36Sopenharmony_ci		break;
97362306a36Sopenharmony_ci	case RPM_REQ_AUTOSUSPEND:
97462306a36Sopenharmony_ci		rpm_suspend(dev, RPM_NOWAIT | RPM_AUTO);
97562306a36Sopenharmony_ci		break;
97662306a36Sopenharmony_ci	case RPM_REQ_RESUME:
97762306a36Sopenharmony_ci		rpm_resume(dev, RPM_NOWAIT);
97862306a36Sopenharmony_ci		break;
97962306a36Sopenharmony_ci	}
98062306a36Sopenharmony_ci
98162306a36Sopenharmony_ci out:
98262306a36Sopenharmony_ci	spin_unlock_irq(&dev->power.lock);
98362306a36Sopenharmony_ci}
98462306a36Sopenharmony_ci
98562306a36Sopenharmony_ci/**
98662306a36Sopenharmony_ci * pm_suspend_timer_fn - Timer function for pm_schedule_suspend().
98762306a36Sopenharmony_ci * @timer: hrtimer used by pm_schedule_suspend().
98862306a36Sopenharmony_ci *
98962306a36Sopenharmony_ci * Check if the time is right and queue a suspend request.
99062306a36Sopenharmony_ci */
99162306a36Sopenharmony_cistatic enum hrtimer_restart  pm_suspend_timer_fn(struct hrtimer *timer)
99262306a36Sopenharmony_ci{
99362306a36Sopenharmony_ci	struct device *dev = container_of(timer, struct device, power.suspend_timer);
99462306a36Sopenharmony_ci	unsigned long flags;
99562306a36Sopenharmony_ci	u64 expires;
99662306a36Sopenharmony_ci
99762306a36Sopenharmony_ci	spin_lock_irqsave(&dev->power.lock, flags);
99862306a36Sopenharmony_ci
99962306a36Sopenharmony_ci	expires = dev->power.timer_expires;
100062306a36Sopenharmony_ci	/*
100162306a36Sopenharmony_ci	 * If 'expires' is after the current time, we've been called
100262306a36Sopenharmony_ci	 * too early.
100362306a36Sopenharmony_ci	 */
100462306a36Sopenharmony_ci	if (expires > 0 && expires < ktime_get_mono_fast_ns()) {
100562306a36Sopenharmony_ci		dev->power.timer_expires = 0;
100662306a36Sopenharmony_ci		rpm_suspend(dev, dev->power.timer_autosuspends ?
100762306a36Sopenharmony_ci		    (RPM_ASYNC | RPM_AUTO) : RPM_ASYNC);
100862306a36Sopenharmony_ci	}
100962306a36Sopenharmony_ci
101062306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->power.lock, flags);
101162306a36Sopenharmony_ci
101262306a36Sopenharmony_ci	return HRTIMER_NORESTART;
101362306a36Sopenharmony_ci}
101462306a36Sopenharmony_ci
101562306a36Sopenharmony_ci/**
101662306a36Sopenharmony_ci * pm_schedule_suspend - Set up a timer to submit a suspend request in future.
101762306a36Sopenharmony_ci * @dev: Device to suspend.
101862306a36Sopenharmony_ci * @delay: Time to wait before submitting a suspend request, in milliseconds.
101962306a36Sopenharmony_ci */
102062306a36Sopenharmony_ciint pm_schedule_suspend(struct device *dev, unsigned int delay)
102162306a36Sopenharmony_ci{
102262306a36Sopenharmony_ci	unsigned long flags;
102362306a36Sopenharmony_ci	u64 expires;
102462306a36Sopenharmony_ci	int retval;
102562306a36Sopenharmony_ci
102662306a36Sopenharmony_ci	spin_lock_irqsave(&dev->power.lock, flags);
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci	if (!delay) {
102962306a36Sopenharmony_ci		retval = rpm_suspend(dev, RPM_ASYNC);
103062306a36Sopenharmony_ci		goto out;
103162306a36Sopenharmony_ci	}
103262306a36Sopenharmony_ci
103362306a36Sopenharmony_ci	retval = rpm_check_suspend_allowed(dev);
103462306a36Sopenharmony_ci	if (retval)
103562306a36Sopenharmony_ci		goto out;
103662306a36Sopenharmony_ci
103762306a36Sopenharmony_ci	/* Other scheduled or pending requests need to be canceled. */
103862306a36Sopenharmony_ci	pm_runtime_cancel_pending(dev);
103962306a36Sopenharmony_ci
104062306a36Sopenharmony_ci	expires = ktime_get_mono_fast_ns() + (u64)delay * NSEC_PER_MSEC;
104162306a36Sopenharmony_ci	dev->power.timer_expires = expires;
104262306a36Sopenharmony_ci	dev->power.timer_autosuspends = 0;
104362306a36Sopenharmony_ci	hrtimer_start(&dev->power.suspend_timer, expires, HRTIMER_MODE_ABS);
104462306a36Sopenharmony_ci
104562306a36Sopenharmony_ci out:
104662306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->power.lock, flags);
104762306a36Sopenharmony_ci
104862306a36Sopenharmony_ci	return retval;
104962306a36Sopenharmony_ci}
105062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_schedule_suspend);
105162306a36Sopenharmony_ci
105262306a36Sopenharmony_cistatic int rpm_drop_usage_count(struct device *dev)
105362306a36Sopenharmony_ci{
105462306a36Sopenharmony_ci	int ret;
105562306a36Sopenharmony_ci
105662306a36Sopenharmony_ci	ret = atomic_sub_return(1, &dev->power.usage_count);
105762306a36Sopenharmony_ci	if (ret >= 0)
105862306a36Sopenharmony_ci		return ret;
105962306a36Sopenharmony_ci
106062306a36Sopenharmony_ci	/*
106162306a36Sopenharmony_ci	 * Because rpm_resume() does not check the usage counter, it will resume
106262306a36Sopenharmony_ci	 * the device even if the usage counter is 0 or negative, so it is
106362306a36Sopenharmony_ci	 * sufficient to increment the usage counter here to reverse the change
106462306a36Sopenharmony_ci	 * made above.
106562306a36Sopenharmony_ci	 */
106662306a36Sopenharmony_ci	atomic_inc(&dev->power.usage_count);
106762306a36Sopenharmony_ci	dev_warn(dev, "Runtime PM usage count underflow!\n");
106862306a36Sopenharmony_ci	return -EINVAL;
106962306a36Sopenharmony_ci}
107062306a36Sopenharmony_ci
107162306a36Sopenharmony_ci/**
107262306a36Sopenharmony_ci * __pm_runtime_idle - Entry point for runtime idle operations.
107362306a36Sopenharmony_ci * @dev: Device to send idle notification for.
107462306a36Sopenharmony_ci * @rpmflags: Flag bits.
107562306a36Sopenharmony_ci *
107662306a36Sopenharmony_ci * If the RPM_GET_PUT flag is set, decrement the device's usage count and
107762306a36Sopenharmony_ci * return immediately if it is larger than zero (if it becomes negative, log a
107862306a36Sopenharmony_ci * warning, increment it, and return an error).  Then carry out an idle
107962306a36Sopenharmony_ci * notification, either synchronous or asynchronous.
108062306a36Sopenharmony_ci *
108162306a36Sopenharmony_ci * This routine may be called in atomic context if the RPM_ASYNC flag is set,
108262306a36Sopenharmony_ci * or if pm_runtime_irq_safe() has been called.
108362306a36Sopenharmony_ci */
108462306a36Sopenharmony_ciint __pm_runtime_idle(struct device *dev, int rpmflags)
108562306a36Sopenharmony_ci{
108662306a36Sopenharmony_ci	unsigned long flags;
108762306a36Sopenharmony_ci	int retval;
108862306a36Sopenharmony_ci
108962306a36Sopenharmony_ci	if (rpmflags & RPM_GET_PUT) {
109062306a36Sopenharmony_ci		retval = rpm_drop_usage_count(dev);
109162306a36Sopenharmony_ci		if (retval < 0) {
109262306a36Sopenharmony_ci			return retval;
109362306a36Sopenharmony_ci		} else if (retval > 0) {
109462306a36Sopenharmony_ci			trace_rpm_usage(dev, rpmflags);
109562306a36Sopenharmony_ci			return 0;
109662306a36Sopenharmony_ci		}
109762306a36Sopenharmony_ci	}
109862306a36Sopenharmony_ci
109962306a36Sopenharmony_ci	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
110062306a36Sopenharmony_ci
110162306a36Sopenharmony_ci	spin_lock_irqsave(&dev->power.lock, flags);
110262306a36Sopenharmony_ci	retval = rpm_idle(dev, rpmflags);
110362306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->power.lock, flags);
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	return retval;
110662306a36Sopenharmony_ci}
110762306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__pm_runtime_idle);
110862306a36Sopenharmony_ci
110962306a36Sopenharmony_ci/**
111062306a36Sopenharmony_ci * __pm_runtime_suspend - Entry point for runtime put/suspend operations.
111162306a36Sopenharmony_ci * @dev: Device to suspend.
111262306a36Sopenharmony_ci * @rpmflags: Flag bits.
111362306a36Sopenharmony_ci *
111462306a36Sopenharmony_ci * If the RPM_GET_PUT flag is set, decrement the device's usage count and
111562306a36Sopenharmony_ci * return immediately if it is larger than zero (if it becomes negative, log a
111662306a36Sopenharmony_ci * warning, increment it, and return an error).  Then carry out a suspend,
111762306a36Sopenharmony_ci * either synchronous or asynchronous.
111862306a36Sopenharmony_ci *
111962306a36Sopenharmony_ci * This routine may be called in atomic context if the RPM_ASYNC flag is set,
112062306a36Sopenharmony_ci * or if pm_runtime_irq_safe() has been called.
112162306a36Sopenharmony_ci */
112262306a36Sopenharmony_ciint __pm_runtime_suspend(struct device *dev, int rpmflags)
112362306a36Sopenharmony_ci{
112462306a36Sopenharmony_ci	unsigned long flags;
112562306a36Sopenharmony_ci	int retval;
112662306a36Sopenharmony_ci
112762306a36Sopenharmony_ci	if (rpmflags & RPM_GET_PUT) {
112862306a36Sopenharmony_ci		retval = rpm_drop_usage_count(dev);
112962306a36Sopenharmony_ci		if (retval < 0) {
113062306a36Sopenharmony_ci			return retval;
113162306a36Sopenharmony_ci		} else if (retval > 0) {
113262306a36Sopenharmony_ci			trace_rpm_usage(dev, rpmflags);
113362306a36Sopenharmony_ci			return 0;
113462306a36Sopenharmony_ci		}
113562306a36Sopenharmony_ci	}
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe);
113862306a36Sopenharmony_ci
113962306a36Sopenharmony_ci	spin_lock_irqsave(&dev->power.lock, flags);
114062306a36Sopenharmony_ci	retval = rpm_suspend(dev, rpmflags);
114162306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->power.lock, flags);
114262306a36Sopenharmony_ci
114362306a36Sopenharmony_ci	return retval;
114462306a36Sopenharmony_ci}
114562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__pm_runtime_suspend);
114662306a36Sopenharmony_ci
114762306a36Sopenharmony_ci/**
114862306a36Sopenharmony_ci * __pm_runtime_resume - Entry point for runtime resume operations.
114962306a36Sopenharmony_ci * @dev: Device to resume.
115062306a36Sopenharmony_ci * @rpmflags: Flag bits.
115162306a36Sopenharmony_ci *
115262306a36Sopenharmony_ci * If the RPM_GET_PUT flag is set, increment the device's usage count.  Then
115362306a36Sopenharmony_ci * carry out a resume, either synchronous or asynchronous.
115462306a36Sopenharmony_ci *
115562306a36Sopenharmony_ci * This routine may be called in atomic context if the RPM_ASYNC flag is set,
115662306a36Sopenharmony_ci * or if pm_runtime_irq_safe() has been called.
115762306a36Sopenharmony_ci */
115862306a36Sopenharmony_ciint __pm_runtime_resume(struct device *dev, int rpmflags)
115962306a36Sopenharmony_ci{
116062306a36Sopenharmony_ci	unsigned long flags;
116162306a36Sopenharmony_ci	int retval;
116262306a36Sopenharmony_ci
116362306a36Sopenharmony_ci	might_sleep_if(!(rpmflags & RPM_ASYNC) && !dev->power.irq_safe &&
116462306a36Sopenharmony_ci			dev->power.runtime_status != RPM_ACTIVE);
116562306a36Sopenharmony_ci
116662306a36Sopenharmony_ci	if (rpmflags & RPM_GET_PUT)
116762306a36Sopenharmony_ci		atomic_inc(&dev->power.usage_count);
116862306a36Sopenharmony_ci
116962306a36Sopenharmony_ci	spin_lock_irqsave(&dev->power.lock, flags);
117062306a36Sopenharmony_ci	retval = rpm_resume(dev, rpmflags);
117162306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->power.lock, flags);
117262306a36Sopenharmony_ci
117362306a36Sopenharmony_ci	return retval;
117462306a36Sopenharmony_ci}
117562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__pm_runtime_resume);
117662306a36Sopenharmony_ci
117762306a36Sopenharmony_ci/**
117862306a36Sopenharmony_ci * pm_runtime_get_if_active - Conditionally bump up device usage counter.
117962306a36Sopenharmony_ci * @dev: Device to handle.
118062306a36Sopenharmony_ci * @ign_usage_count: Whether or not to look at the current usage counter value.
118162306a36Sopenharmony_ci *
118262306a36Sopenharmony_ci * Return -EINVAL if runtime PM is disabled for @dev.
118362306a36Sopenharmony_ci *
118462306a36Sopenharmony_ci * Otherwise, if the runtime PM status of @dev is %RPM_ACTIVE and either
118562306a36Sopenharmony_ci * @ign_usage_count is %true or the runtime PM usage counter of @dev is not
118662306a36Sopenharmony_ci * zero, increment the usage counter of @dev and return 1. Otherwise, return 0
118762306a36Sopenharmony_ci * without changing the usage counter.
118862306a36Sopenharmony_ci *
118962306a36Sopenharmony_ci * If @ign_usage_count is %true, this function can be used to prevent suspending
119062306a36Sopenharmony_ci * the device when its runtime PM status is %RPM_ACTIVE.
119162306a36Sopenharmony_ci *
119262306a36Sopenharmony_ci * If @ign_usage_count is %false, this function can be used to prevent
119362306a36Sopenharmony_ci * suspending the device when both its runtime PM status is %RPM_ACTIVE and its
119462306a36Sopenharmony_ci * runtime PM usage counter is not zero.
119562306a36Sopenharmony_ci *
119662306a36Sopenharmony_ci * The caller is responsible for decrementing the runtime PM usage counter of
119762306a36Sopenharmony_ci * @dev after this function has returned a positive value for it.
119862306a36Sopenharmony_ci */
119962306a36Sopenharmony_ciint pm_runtime_get_if_active(struct device *dev, bool ign_usage_count)
120062306a36Sopenharmony_ci{
120162306a36Sopenharmony_ci	unsigned long flags;
120262306a36Sopenharmony_ci	int retval;
120362306a36Sopenharmony_ci
120462306a36Sopenharmony_ci	spin_lock_irqsave(&dev->power.lock, flags);
120562306a36Sopenharmony_ci	if (dev->power.disable_depth > 0) {
120662306a36Sopenharmony_ci		retval = -EINVAL;
120762306a36Sopenharmony_ci	} else if (dev->power.runtime_status != RPM_ACTIVE) {
120862306a36Sopenharmony_ci		retval = 0;
120962306a36Sopenharmony_ci	} else if (ign_usage_count) {
121062306a36Sopenharmony_ci		retval = 1;
121162306a36Sopenharmony_ci		atomic_inc(&dev->power.usage_count);
121262306a36Sopenharmony_ci	} else {
121362306a36Sopenharmony_ci		retval = atomic_inc_not_zero(&dev->power.usage_count);
121462306a36Sopenharmony_ci	}
121562306a36Sopenharmony_ci	trace_rpm_usage(dev, 0);
121662306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->power.lock, flags);
121762306a36Sopenharmony_ci
121862306a36Sopenharmony_ci	return retval;
121962306a36Sopenharmony_ci}
122062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_runtime_get_if_active);
122162306a36Sopenharmony_ci
122262306a36Sopenharmony_ci/**
122362306a36Sopenharmony_ci * __pm_runtime_set_status - Set runtime PM status of a device.
122462306a36Sopenharmony_ci * @dev: Device to handle.
122562306a36Sopenharmony_ci * @status: New runtime PM status of the device.
122662306a36Sopenharmony_ci *
122762306a36Sopenharmony_ci * If runtime PM of the device is disabled or its power.runtime_error field is
122862306a36Sopenharmony_ci * different from zero, the status may be changed either to RPM_ACTIVE, or to
122962306a36Sopenharmony_ci * RPM_SUSPENDED, as long as that reflects the actual state of the device.
123062306a36Sopenharmony_ci * However, if the device has a parent and the parent is not active, and the
123162306a36Sopenharmony_ci * parent's power.ignore_children flag is unset, the device's status cannot be
123262306a36Sopenharmony_ci * set to RPM_ACTIVE, so -EBUSY is returned in that case.
123362306a36Sopenharmony_ci *
123462306a36Sopenharmony_ci * If successful, __pm_runtime_set_status() clears the power.runtime_error field
123562306a36Sopenharmony_ci * and the device parent's counter of unsuspended children is modified to
123662306a36Sopenharmony_ci * reflect the new status.  If the new status is RPM_SUSPENDED, an idle
123762306a36Sopenharmony_ci * notification request for the parent is submitted.
123862306a36Sopenharmony_ci *
123962306a36Sopenharmony_ci * If @dev has any suppliers (as reflected by device links to them), and @status
124062306a36Sopenharmony_ci * is RPM_ACTIVE, they will be activated upfront and if the activation of one
124162306a36Sopenharmony_ci * of them fails, the status of @dev will be changed to RPM_SUSPENDED (instead
124262306a36Sopenharmony_ci * of the @status value) and the suppliers will be deacticated on exit.  The
124362306a36Sopenharmony_ci * error returned by the failing supplier activation will be returned in that
124462306a36Sopenharmony_ci * case.
124562306a36Sopenharmony_ci */
124662306a36Sopenharmony_ciint __pm_runtime_set_status(struct device *dev, unsigned int status)
124762306a36Sopenharmony_ci{
124862306a36Sopenharmony_ci	struct device *parent = dev->parent;
124962306a36Sopenharmony_ci	bool notify_parent = false;
125062306a36Sopenharmony_ci	unsigned long flags;
125162306a36Sopenharmony_ci	int error = 0;
125262306a36Sopenharmony_ci
125362306a36Sopenharmony_ci	if (status != RPM_ACTIVE && status != RPM_SUSPENDED)
125462306a36Sopenharmony_ci		return -EINVAL;
125562306a36Sopenharmony_ci
125662306a36Sopenharmony_ci	spin_lock_irqsave(&dev->power.lock, flags);
125762306a36Sopenharmony_ci
125862306a36Sopenharmony_ci	/*
125962306a36Sopenharmony_ci	 * Prevent PM-runtime from being enabled for the device or return an
126062306a36Sopenharmony_ci	 * error if it is enabled already and working.
126162306a36Sopenharmony_ci	 */
126262306a36Sopenharmony_ci	if (dev->power.runtime_error || dev->power.disable_depth)
126362306a36Sopenharmony_ci		dev->power.disable_depth++;
126462306a36Sopenharmony_ci	else
126562306a36Sopenharmony_ci		error = -EAGAIN;
126662306a36Sopenharmony_ci
126762306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->power.lock, flags);
126862306a36Sopenharmony_ci
126962306a36Sopenharmony_ci	if (error)
127062306a36Sopenharmony_ci		return error;
127162306a36Sopenharmony_ci
127262306a36Sopenharmony_ci	/*
127362306a36Sopenharmony_ci	 * If the new status is RPM_ACTIVE, the suppliers can be activated
127462306a36Sopenharmony_ci	 * upfront regardless of the current status, because next time
127562306a36Sopenharmony_ci	 * rpm_put_suppliers() runs, the rpm_active refcounts of the links
127662306a36Sopenharmony_ci	 * involved will be dropped down to one anyway.
127762306a36Sopenharmony_ci	 */
127862306a36Sopenharmony_ci	if (status == RPM_ACTIVE) {
127962306a36Sopenharmony_ci		int idx = device_links_read_lock();
128062306a36Sopenharmony_ci
128162306a36Sopenharmony_ci		error = rpm_get_suppliers(dev);
128262306a36Sopenharmony_ci		if (error)
128362306a36Sopenharmony_ci			status = RPM_SUSPENDED;
128462306a36Sopenharmony_ci
128562306a36Sopenharmony_ci		device_links_read_unlock(idx);
128662306a36Sopenharmony_ci	}
128762306a36Sopenharmony_ci
128862306a36Sopenharmony_ci	spin_lock_irqsave(&dev->power.lock, flags);
128962306a36Sopenharmony_ci
129062306a36Sopenharmony_ci	if (dev->power.runtime_status == status || !parent)
129162306a36Sopenharmony_ci		goto out_set;
129262306a36Sopenharmony_ci
129362306a36Sopenharmony_ci	if (status == RPM_SUSPENDED) {
129462306a36Sopenharmony_ci		atomic_add_unless(&parent->power.child_count, -1, 0);
129562306a36Sopenharmony_ci		notify_parent = !parent->power.ignore_children;
129662306a36Sopenharmony_ci	} else {
129762306a36Sopenharmony_ci		spin_lock_nested(&parent->power.lock, SINGLE_DEPTH_NESTING);
129862306a36Sopenharmony_ci
129962306a36Sopenharmony_ci		/*
130062306a36Sopenharmony_ci		 * It is invalid to put an active child under a parent that is
130162306a36Sopenharmony_ci		 * not active, has runtime PM enabled and the
130262306a36Sopenharmony_ci		 * 'power.ignore_children' flag unset.
130362306a36Sopenharmony_ci		 */
130462306a36Sopenharmony_ci		if (!parent->power.disable_depth &&
130562306a36Sopenharmony_ci		    !parent->power.ignore_children &&
130662306a36Sopenharmony_ci		    parent->power.runtime_status != RPM_ACTIVE) {
130762306a36Sopenharmony_ci			dev_err(dev, "runtime PM trying to activate child device %s but parent (%s) is not active\n",
130862306a36Sopenharmony_ci				dev_name(dev),
130962306a36Sopenharmony_ci				dev_name(parent));
131062306a36Sopenharmony_ci			error = -EBUSY;
131162306a36Sopenharmony_ci		} else if (dev->power.runtime_status == RPM_SUSPENDED) {
131262306a36Sopenharmony_ci			atomic_inc(&parent->power.child_count);
131362306a36Sopenharmony_ci		}
131462306a36Sopenharmony_ci
131562306a36Sopenharmony_ci		spin_unlock(&parent->power.lock);
131662306a36Sopenharmony_ci
131762306a36Sopenharmony_ci		if (error) {
131862306a36Sopenharmony_ci			status = RPM_SUSPENDED;
131962306a36Sopenharmony_ci			goto out;
132062306a36Sopenharmony_ci		}
132162306a36Sopenharmony_ci	}
132262306a36Sopenharmony_ci
132362306a36Sopenharmony_ci out_set:
132462306a36Sopenharmony_ci	__update_runtime_status(dev, status);
132562306a36Sopenharmony_ci	if (!error)
132662306a36Sopenharmony_ci		dev->power.runtime_error = 0;
132762306a36Sopenharmony_ci
132862306a36Sopenharmony_ci out:
132962306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->power.lock, flags);
133062306a36Sopenharmony_ci
133162306a36Sopenharmony_ci	if (notify_parent)
133262306a36Sopenharmony_ci		pm_request_idle(parent);
133362306a36Sopenharmony_ci
133462306a36Sopenharmony_ci	if (status == RPM_SUSPENDED) {
133562306a36Sopenharmony_ci		int idx = device_links_read_lock();
133662306a36Sopenharmony_ci
133762306a36Sopenharmony_ci		rpm_put_suppliers(dev);
133862306a36Sopenharmony_ci
133962306a36Sopenharmony_ci		device_links_read_unlock(idx);
134062306a36Sopenharmony_ci	}
134162306a36Sopenharmony_ci
134262306a36Sopenharmony_ci	pm_runtime_enable(dev);
134362306a36Sopenharmony_ci
134462306a36Sopenharmony_ci	return error;
134562306a36Sopenharmony_ci}
134662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__pm_runtime_set_status);
134762306a36Sopenharmony_ci
134862306a36Sopenharmony_ci/**
134962306a36Sopenharmony_ci * __pm_runtime_barrier - Cancel pending requests and wait for completions.
135062306a36Sopenharmony_ci * @dev: Device to handle.
135162306a36Sopenharmony_ci *
135262306a36Sopenharmony_ci * Flush all pending requests for the device from pm_wq and wait for all
135362306a36Sopenharmony_ci * runtime PM operations involving the device in progress to complete.
135462306a36Sopenharmony_ci *
135562306a36Sopenharmony_ci * Should be called under dev->power.lock with interrupts disabled.
135662306a36Sopenharmony_ci */
135762306a36Sopenharmony_cistatic void __pm_runtime_barrier(struct device *dev)
135862306a36Sopenharmony_ci{
135962306a36Sopenharmony_ci	pm_runtime_deactivate_timer(dev);
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci	if (dev->power.request_pending) {
136262306a36Sopenharmony_ci		dev->power.request = RPM_REQ_NONE;
136362306a36Sopenharmony_ci		spin_unlock_irq(&dev->power.lock);
136462306a36Sopenharmony_ci
136562306a36Sopenharmony_ci		cancel_work_sync(&dev->power.work);
136662306a36Sopenharmony_ci
136762306a36Sopenharmony_ci		spin_lock_irq(&dev->power.lock);
136862306a36Sopenharmony_ci		dev->power.request_pending = false;
136962306a36Sopenharmony_ci	}
137062306a36Sopenharmony_ci
137162306a36Sopenharmony_ci	if (dev->power.runtime_status == RPM_SUSPENDING ||
137262306a36Sopenharmony_ci	    dev->power.runtime_status == RPM_RESUMING ||
137362306a36Sopenharmony_ci	    dev->power.idle_notification) {
137462306a36Sopenharmony_ci		DEFINE_WAIT(wait);
137562306a36Sopenharmony_ci
137662306a36Sopenharmony_ci		/* Suspend, wake-up or idle notification in progress. */
137762306a36Sopenharmony_ci		for (;;) {
137862306a36Sopenharmony_ci			prepare_to_wait(&dev->power.wait_queue, &wait,
137962306a36Sopenharmony_ci					TASK_UNINTERRUPTIBLE);
138062306a36Sopenharmony_ci			if (dev->power.runtime_status != RPM_SUSPENDING
138162306a36Sopenharmony_ci			    && dev->power.runtime_status != RPM_RESUMING
138262306a36Sopenharmony_ci			    && !dev->power.idle_notification)
138362306a36Sopenharmony_ci				break;
138462306a36Sopenharmony_ci			spin_unlock_irq(&dev->power.lock);
138562306a36Sopenharmony_ci
138662306a36Sopenharmony_ci			schedule();
138762306a36Sopenharmony_ci
138862306a36Sopenharmony_ci			spin_lock_irq(&dev->power.lock);
138962306a36Sopenharmony_ci		}
139062306a36Sopenharmony_ci		finish_wait(&dev->power.wait_queue, &wait);
139162306a36Sopenharmony_ci	}
139262306a36Sopenharmony_ci}
139362306a36Sopenharmony_ci
139462306a36Sopenharmony_ci/**
139562306a36Sopenharmony_ci * pm_runtime_barrier - Flush pending requests and wait for completions.
139662306a36Sopenharmony_ci * @dev: Device to handle.
139762306a36Sopenharmony_ci *
139862306a36Sopenharmony_ci * Prevent the device from being suspended by incrementing its usage counter and
139962306a36Sopenharmony_ci * if there's a pending resume request for the device, wake the device up.
140062306a36Sopenharmony_ci * Next, make sure that all pending requests for the device have been flushed
140162306a36Sopenharmony_ci * from pm_wq and wait for all runtime PM operations involving the device in
140262306a36Sopenharmony_ci * progress to complete.
140362306a36Sopenharmony_ci *
140462306a36Sopenharmony_ci * Return value:
140562306a36Sopenharmony_ci * 1, if there was a resume request pending and the device had to be woken up,
140662306a36Sopenharmony_ci * 0, otherwise
140762306a36Sopenharmony_ci */
140862306a36Sopenharmony_ciint pm_runtime_barrier(struct device *dev)
140962306a36Sopenharmony_ci{
141062306a36Sopenharmony_ci	int retval = 0;
141162306a36Sopenharmony_ci
141262306a36Sopenharmony_ci	pm_runtime_get_noresume(dev);
141362306a36Sopenharmony_ci	spin_lock_irq(&dev->power.lock);
141462306a36Sopenharmony_ci
141562306a36Sopenharmony_ci	if (dev->power.request_pending
141662306a36Sopenharmony_ci	    && dev->power.request == RPM_REQ_RESUME) {
141762306a36Sopenharmony_ci		rpm_resume(dev, 0);
141862306a36Sopenharmony_ci		retval = 1;
141962306a36Sopenharmony_ci	}
142062306a36Sopenharmony_ci
142162306a36Sopenharmony_ci	__pm_runtime_barrier(dev);
142262306a36Sopenharmony_ci
142362306a36Sopenharmony_ci	spin_unlock_irq(&dev->power.lock);
142462306a36Sopenharmony_ci	pm_runtime_put_noidle(dev);
142562306a36Sopenharmony_ci
142662306a36Sopenharmony_ci	return retval;
142762306a36Sopenharmony_ci}
142862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_runtime_barrier);
142962306a36Sopenharmony_ci
143062306a36Sopenharmony_ci/**
143162306a36Sopenharmony_ci * __pm_runtime_disable - Disable runtime PM of a device.
143262306a36Sopenharmony_ci * @dev: Device to handle.
143362306a36Sopenharmony_ci * @check_resume: If set, check if there's a resume request for the device.
143462306a36Sopenharmony_ci *
143562306a36Sopenharmony_ci * Increment power.disable_depth for the device and if it was zero previously,
143662306a36Sopenharmony_ci * cancel all pending runtime PM requests for the device and wait for all
143762306a36Sopenharmony_ci * operations in progress to complete.  The device can be either active or
143862306a36Sopenharmony_ci * suspended after its runtime PM has been disabled.
143962306a36Sopenharmony_ci *
144062306a36Sopenharmony_ci * If @check_resume is set and there's a resume request pending when
144162306a36Sopenharmony_ci * __pm_runtime_disable() is called and power.disable_depth is zero, the
144262306a36Sopenharmony_ci * function will wake up the device before disabling its runtime PM.
144362306a36Sopenharmony_ci */
144462306a36Sopenharmony_civoid __pm_runtime_disable(struct device *dev, bool check_resume)
144562306a36Sopenharmony_ci{
144662306a36Sopenharmony_ci	spin_lock_irq(&dev->power.lock);
144762306a36Sopenharmony_ci
144862306a36Sopenharmony_ci	if (dev->power.disable_depth > 0) {
144962306a36Sopenharmony_ci		dev->power.disable_depth++;
145062306a36Sopenharmony_ci		goto out;
145162306a36Sopenharmony_ci	}
145262306a36Sopenharmony_ci
145362306a36Sopenharmony_ci	/*
145462306a36Sopenharmony_ci	 * Wake up the device if there's a resume request pending, because that
145562306a36Sopenharmony_ci	 * means there probably is some I/O to process and disabling runtime PM
145662306a36Sopenharmony_ci	 * shouldn't prevent the device from processing the I/O.
145762306a36Sopenharmony_ci	 */
145862306a36Sopenharmony_ci	if (check_resume && dev->power.request_pending &&
145962306a36Sopenharmony_ci	    dev->power.request == RPM_REQ_RESUME) {
146062306a36Sopenharmony_ci		/*
146162306a36Sopenharmony_ci		 * Prevent suspends and idle notifications from being carried
146262306a36Sopenharmony_ci		 * out after we have woken up the device.
146362306a36Sopenharmony_ci		 */
146462306a36Sopenharmony_ci		pm_runtime_get_noresume(dev);
146562306a36Sopenharmony_ci
146662306a36Sopenharmony_ci		rpm_resume(dev, 0);
146762306a36Sopenharmony_ci
146862306a36Sopenharmony_ci		pm_runtime_put_noidle(dev);
146962306a36Sopenharmony_ci	}
147062306a36Sopenharmony_ci
147162306a36Sopenharmony_ci	/* Update time accounting before disabling PM-runtime. */
147262306a36Sopenharmony_ci	update_pm_runtime_accounting(dev);
147362306a36Sopenharmony_ci
147462306a36Sopenharmony_ci	if (!dev->power.disable_depth++) {
147562306a36Sopenharmony_ci		__pm_runtime_barrier(dev);
147662306a36Sopenharmony_ci		dev->power.last_status = dev->power.runtime_status;
147762306a36Sopenharmony_ci	}
147862306a36Sopenharmony_ci
147962306a36Sopenharmony_ci out:
148062306a36Sopenharmony_ci	spin_unlock_irq(&dev->power.lock);
148162306a36Sopenharmony_ci}
148262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__pm_runtime_disable);
148362306a36Sopenharmony_ci
148462306a36Sopenharmony_ci/**
148562306a36Sopenharmony_ci * pm_runtime_enable - Enable runtime PM of a device.
148662306a36Sopenharmony_ci * @dev: Device to handle.
148762306a36Sopenharmony_ci */
148862306a36Sopenharmony_civoid pm_runtime_enable(struct device *dev)
148962306a36Sopenharmony_ci{
149062306a36Sopenharmony_ci	unsigned long flags;
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci	spin_lock_irqsave(&dev->power.lock, flags);
149362306a36Sopenharmony_ci
149462306a36Sopenharmony_ci	if (!dev->power.disable_depth) {
149562306a36Sopenharmony_ci		dev_warn(dev, "Unbalanced %s!\n", __func__);
149662306a36Sopenharmony_ci		goto out;
149762306a36Sopenharmony_ci	}
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_ci	if (--dev->power.disable_depth > 0)
150062306a36Sopenharmony_ci		goto out;
150162306a36Sopenharmony_ci
150262306a36Sopenharmony_ci	dev->power.last_status = RPM_INVALID;
150362306a36Sopenharmony_ci	dev->power.accounting_timestamp = ktime_get_mono_fast_ns();
150462306a36Sopenharmony_ci
150562306a36Sopenharmony_ci	if (dev->power.runtime_status == RPM_SUSPENDED &&
150662306a36Sopenharmony_ci	    !dev->power.ignore_children &&
150762306a36Sopenharmony_ci	    atomic_read(&dev->power.child_count) > 0)
150862306a36Sopenharmony_ci		dev_warn(dev, "Enabling runtime PM for inactive device with active children\n");
150962306a36Sopenharmony_ci
151062306a36Sopenharmony_ciout:
151162306a36Sopenharmony_ci	spin_unlock_irqrestore(&dev->power.lock, flags);
151262306a36Sopenharmony_ci}
151362306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_runtime_enable);
151462306a36Sopenharmony_ci
151562306a36Sopenharmony_cistatic void pm_runtime_disable_action(void *data)
151662306a36Sopenharmony_ci{
151762306a36Sopenharmony_ci	pm_runtime_dont_use_autosuspend(data);
151862306a36Sopenharmony_ci	pm_runtime_disable(data);
151962306a36Sopenharmony_ci}
152062306a36Sopenharmony_ci
152162306a36Sopenharmony_ci/**
152262306a36Sopenharmony_ci * devm_pm_runtime_enable - devres-enabled version of pm_runtime_enable.
152362306a36Sopenharmony_ci *
152462306a36Sopenharmony_ci * NOTE: this will also handle calling pm_runtime_dont_use_autosuspend() for
152562306a36Sopenharmony_ci * you at driver exit time if needed.
152662306a36Sopenharmony_ci *
152762306a36Sopenharmony_ci * @dev: Device to handle.
152862306a36Sopenharmony_ci */
152962306a36Sopenharmony_ciint devm_pm_runtime_enable(struct device *dev)
153062306a36Sopenharmony_ci{
153162306a36Sopenharmony_ci	pm_runtime_enable(dev);
153262306a36Sopenharmony_ci
153362306a36Sopenharmony_ci	return devm_add_action_or_reset(dev, pm_runtime_disable_action, dev);
153462306a36Sopenharmony_ci}
153562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(devm_pm_runtime_enable);
153662306a36Sopenharmony_ci
153762306a36Sopenharmony_ci/**
153862306a36Sopenharmony_ci * pm_runtime_forbid - Block runtime PM of a device.
153962306a36Sopenharmony_ci * @dev: Device to handle.
154062306a36Sopenharmony_ci *
154162306a36Sopenharmony_ci * Increase the device's usage count and clear its power.runtime_auto flag,
154262306a36Sopenharmony_ci * so that it cannot be suspended at run time until pm_runtime_allow() is called
154362306a36Sopenharmony_ci * for it.
154462306a36Sopenharmony_ci */
154562306a36Sopenharmony_civoid pm_runtime_forbid(struct device *dev)
154662306a36Sopenharmony_ci{
154762306a36Sopenharmony_ci	spin_lock_irq(&dev->power.lock);
154862306a36Sopenharmony_ci	if (!dev->power.runtime_auto)
154962306a36Sopenharmony_ci		goto out;
155062306a36Sopenharmony_ci
155162306a36Sopenharmony_ci	dev->power.runtime_auto = false;
155262306a36Sopenharmony_ci	atomic_inc(&dev->power.usage_count);
155362306a36Sopenharmony_ci	rpm_resume(dev, 0);
155462306a36Sopenharmony_ci
155562306a36Sopenharmony_ci out:
155662306a36Sopenharmony_ci	spin_unlock_irq(&dev->power.lock);
155762306a36Sopenharmony_ci}
155862306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_runtime_forbid);
155962306a36Sopenharmony_ci
156062306a36Sopenharmony_ci/**
156162306a36Sopenharmony_ci * pm_runtime_allow - Unblock runtime PM of a device.
156262306a36Sopenharmony_ci * @dev: Device to handle.
156362306a36Sopenharmony_ci *
156462306a36Sopenharmony_ci * Decrease the device's usage count and set its power.runtime_auto flag.
156562306a36Sopenharmony_ci */
156662306a36Sopenharmony_civoid pm_runtime_allow(struct device *dev)
156762306a36Sopenharmony_ci{
156862306a36Sopenharmony_ci	int ret;
156962306a36Sopenharmony_ci
157062306a36Sopenharmony_ci	spin_lock_irq(&dev->power.lock);
157162306a36Sopenharmony_ci	if (dev->power.runtime_auto)
157262306a36Sopenharmony_ci		goto out;
157362306a36Sopenharmony_ci
157462306a36Sopenharmony_ci	dev->power.runtime_auto = true;
157562306a36Sopenharmony_ci	ret = rpm_drop_usage_count(dev);
157662306a36Sopenharmony_ci	if (ret == 0)
157762306a36Sopenharmony_ci		rpm_idle(dev, RPM_AUTO | RPM_ASYNC);
157862306a36Sopenharmony_ci	else if (ret > 0)
157962306a36Sopenharmony_ci		trace_rpm_usage(dev, RPM_AUTO | RPM_ASYNC);
158062306a36Sopenharmony_ci
158162306a36Sopenharmony_ci out:
158262306a36Sopenharmony_ci	spin_unlock_irq(&dev->power.lock);
158362306a36Sopenharmony_ci}
158462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_runtime_allow);
158562306a36Sopenharmony_ci
158662306a36Sopenharmony_ci/**
158762306a36Sopenharmony_ci * pm_runtime_no_callbacks - Ignore runtime PM callbacks for a device.
158862306a36Sopenharmony_ci * @dev: Device to handle.
158962306a36Sopenharmony_ci *
159062306a36Sopenharmony_ci * Set the power.no_callbacks flag, which tells the PM core that this
159162306a36Sopenharmony_ci * device is power-managed through its parent and has no runtime PM
159262306a36Sopenharmony_ci * callbacks of its own.  The runtime sysfs attributes will be removed.
159362306a36Sopenharmony_ci */
159462306a36Sopenharmony_civoid pm_runtime_no_callbacks(struct device *dev)
159562306a36Sopenharmony_ci{
159662306a36Sopenharmony_ci	spin_lock_irq(&dev->power.lock);
159762306a36Sopenharmony_ci	dev->power.no_callbacks = 1;
159862306a36Sopenharmony_ci	spin_unlock_irq(&dev->power.lock);
159962306a36Sopenharmony_ci	if (device_is_registered(dev))
160062306a36Sopenharmony_ci		rpm_sysfs_remove(dev);
160162306a36Sopenharmony_ci}
160262306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_runtime_no_callbacks);
160362306a36Sopenharmony_ci
160462306a36Sopenharmony_ci/**
160562306a36Sopenharmony_ci * pm_runtime_irq_safe - Leave interrupts disabled during callbacks.
160662306a36Sopenharmony_ci * @dev: Device to handle
160762306a36Sopenharmony_ci *
160862306a36Sopenharmony_ci * Set the power.irq_safe flag, which tells the PM core that the
160962306a36Sopenharmony_ci * ->runtime_suspend() and ->runtime_resume() callbacks for this device should
161062306a36Sopenharmony_ci * always be invoked with the spinlock held and interrupts disabled.  It also
161162306a36Sopenharmony_ci * causes the parent's usage counter to be permanently incremented, preventing
161262306a36Sopenharmony_ci * the parent from runtime suspending -- otherwise an irq-safe child might have
161362306a36Sopenharmony_ci * to wait for a non-irq-safe parent.
161462306a36Sopenharmony_ci */
161562306a36Sopenharmony_civoid pm_runtime_irq_safe(struct device *dev)
161662306a36Sopenharmony_ci{
161762306a36Sopenharmony_ci	if (dev->parent)
161862306a36Sopenharmony_ci		pm_runtime_get_sync(dev->parent);
161962306a36Sopenharmony_ci
162062306a36Sopenharmony_ci	spin_lock_irq(&dev->power.lock);
162162306a36Sopenharmony_ci	dev->power.irq_safe = 1;
162262306a36Sopenharmony_ci	spin_unlock_irq(&dev->power.lock);
162362306a36Sopenharmony_ci}
162462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_runtime_irq_safe);
162562306a36Sopenharmony_ci
162662306a36Sopenharmony_ci/**
162762306a36Sopenharmony_ci * update_autosuspend - Handle a change to a device's autosuspend settings.
162862306a36Sopenharmony_ci * @dev: Device to handle.
162962306a36Sopenharmony_ci * @old_delay: The former autosuspend_delay value.
163062306a36Sopenharmony_ci * @old_use: The former use_autosuspend value.
163162306a36Sopenharmony_ci *
163262306a36Sopenharmony_ci * Prevent runtime suspend if the new delay is negative and use_autosuspend is
163362306a36Sopenharmony_ci * set; otherwise allow it.  Send an idle notification if suspends are allowed.
163462306a36Sopenharmony_ci *
163562306a36Sopenharmony_ci * This function must be called under dev->power.lock with interrupts disabled.
163662306a36Sopenharmony_ci */
163762306a36Sopenharmony_cistatic void update_autosuspend(struct device *dev, int old_delay, int old_use)
163862306a36Sopenharmony_ci{
163962306a36Sopenharmony_ci	int delay = dev->power.autosuspend_delay;
164062306a36Sopenharmony_ci
164162306a36Sopenharmony_ci	/* Should runtime suspend be prevented now? */
164262306a36Sopenharmony_ci	if (dev->power.use_autosuspend && delay < 0) {
164362306a36Sopenharmony_ci
164462306a36Sopenharmony_ci		/* If it used to be allowed then prevent it. */
164562306a36Sopenharmony_ci		if (!old_use || old_delay >= 0) {
164662306a36Sopenharmony_ci			atomic_inc(&dev->power.usage_count);
164762306a36Sopenharmony_ci			rpm_resume(dev, 0);
164862306a36Sopenharmony_ci		} else {
164962306a36Sopenharmony_ci			trace_rpm_usage(dev, 0);
165062306a36Sopenharmony_ci		}
165162306a36Sopenharmony_ci	}
165262306a36Sopenharmony_ci
165362306a36Sopenharmony_ci	/* Runtime suspend should be allowed now. */
165462306a36Sopenharmony_ci	else {
165562306a36Sopenharmony_ci
165662306a36Sopenharmony_ci		/* If it used to be prevented then allow it. */
165762306a36Sopenharmony_ci		if (old_use && old_delay < 0)
165862306a36Sopenharmony_ci			atomic_dec(&dev->power.usage_count);
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_ci		/* Maybe we can autosuspend now. */
166162306a36Sopenharmony_ci		rpm_idle(dev, RPM_AUTO);
166262306a36Sopenharmony_ci	}
166362306a36Sopenharmony_ci}
166462306a36Sopenharmony_ci
166562306a36Sopenharmony_ci/**
166662306a36Sopenharmony_ci * pm_runtime_set_autosuspend_delay - Set a device's autosuspend_delay value.
166762306a36Sopenharmony_ci * @dev: Device to handle.
166862306a36Sopenharmony_ci * @delay: Value of the new delay in milliseconds.
166962306a36Sopenharmony_ci *
167062306a36Sopenharmony_ci * Set the device's power.autosuspend_delay value.  If it changes to negative
167162306a36Sopenharmony_ci * and the power.use_autosuspend flag is set, prevent runtime suspends.  If it
167262306a36Sopenharmony_ci * changes the other way, allow runtime suspends.
167362306a36Sopenharmony_ci */
167462306a36Sopenharmony_civoid pm_runtime_set_autosuspend_delay(struct device *dev, int delay)
167562306a36Sopenharmony_ci{
167662306a36Sopenharmony_ci	int old_delay, old_use;
167762306a36Sopenharmony_ci
167862306a36Sopenharmony_ci	spin_lock_irq(&dev->power.lock);
167962306a36Sopenharmony_ci	old_delay = dev->power.autosuspend_delay;
168062306a36Sopenharmony_ci	old_use = dev->power.use_autosuspend;
168162306a36Sopenharmony_ci	dev->power.autosuspend_delay = delay;
168262306a36Sopenharmony_ci	update_autosuspend(dev, old_delay, old_use);
168362306a36Sopenharmony_ci	spin_unlock_irq(&dev->power.lock);
168462306a36Sopenharmony_ci}
168562306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_runtime_set_autosuspend_delay);
168662306a36Sopenharmony_ci
168762306a36Sopenharmony_ci/**
168862306a36Sopenharmony_ci * __pm_runtime_use_autosuspend - Set a device's use_autosuspend flag.
168962306a36Sopenharmony_ci * @dev: Device to handle.
169062306a36Sopenharmony_ci * @use: New value for use_autosuspend.
169162306a36Sopenharmony_ci *
169262306a36Sopenharmony_ci * Set the device's power.use_autosuspend flag, and allow or prevent runtime
169362306a36Sopenharmony_ci * suspends as needed.
169462306a36Sopenharmony_ci */
169562306a36Sopenharmony_civoid __pm_runtime_use_autosuspend(struct device *dev, bool use)
169662306a36Sopenharmony_ci{
169762306a36Sopenharmony_ci	int old_delay, old_use;
169862306a36Sopenharmony_ci
169962306a36Sopenharmony_ci	spin_lock_irq(&dev->power.lock);
170062306a36Sopenharmony_ci	old_delay = dev->power.autosuspend_delay;
170162306a36Sopenharmony_ci	old_use = dev->power.use_autosuspend;
170262306a36Sopenharmony_ci	dev->power.use_autosuspend = use;
170362306a36Sopenharmony_ci	update_autosuspend(dev, old_delay, old_use);
170462306a36Sopenharmony_ci	spin_unlock_irq(&dev->power.lock);
170562306a36Sopenharmony_ci}
170662306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(__pm_runtime_use_autosuspend);
170762306a36Sopenharmony_ci
170862306a36Sopenharmony_ci/**
170962306a36Sopenharmony_ci * pm_runtime_init - Initialize runtime PM fields in given device object.
171062306a36Sopenharmony_ci * @dev: Device object to initialize.
171162306a36Sopenharmony_ci */
171262306a36Sopenharmony_civoid pm_runtime_init(struct device *dev)
171362306a36Sopenharmony_ci{
171462306a36Sopenharmony_ci	dev->power.runtime_status = RPM_SUSPENDED;
171562306a36Sopenharmony_ci	dev->power.last_status = RPM_INVALID;
171662306a36Sopenharmony_ci	dev->power.idle_notification = false;
171762306a36Sopenharmony_ci
171862306a36Sopenharmony_ci	dev->power.disable_depth = 1;
171962306a36Sopenharmony_ci	atomic_set(&dev->power.usage_count, 0);
172062306a36Sopenharmony_ci
172162306a36Sopenharmony_ci	dev->power.runtime_error = 0;
172262306a36Sopenharmony_ci
172362306a36Sopenharmony_ci	atomic_set(&dev->power.child_count, 0);
172462306a36Sopenharmony_ci	pm_suspend_ignore_children(dev, false);
172562306a36Sopenharmony_ci	dev->power.runtime_auto = true;
172662306a36Sopenharmony_ci
172762306a36Sopenharmony_ci	dev->power.request_pending = false;
172862306a36Sopenharmony_ci	dev->power.request = RPM_REQ_NONE;
172962306a36Sopenharmony_ci	dev->power.deferred_resume = false;
173062306a36Sopenharmony_ci	dev->power.needs_force_resume = 0;
173162306a36Sopenharmony_ci	INIT_WORK(&dev->power.work, pm_runtime_work);
173262306a36Sopenharmony_ci
173362306a36Sopenharmony_ci	dev->power.timer_expires = 0;
173462306a36Sopenharmony_ci	hrtimer_init(&dev->power.suspend_timer, CLOCK_MONOTONIC, HRTIMER_MODE_ABS);
173562306a36Sopenharmony_ci	dev->power.suspend_timer.function = pm_suspend_timer_fn;
173662306a36Sopenharmony_ci
173762306a36Sopenharmony_ci	init_waitqueue_head(&dev->power.wait_queue);
173862306a36Sopenharmony_ci}
173962306a36Sopenharmony_ci
174062306a36Sopenharmony_ci/**
174162306a36Sopenharmony_ci * pm_runtime_reinit - Re-initialize runtime PM fields in given device object.
174262306a36Sopenharmony_ci * @dev: Device object to re-initialize.
174362306a36Sopenharmony_ci */
174462306a36Sopenharmony_civoid pm_runtime_reinit(struct device *dev)
174562306a36Sopenharmony_ci{
174662306a36Sopenharmony_ci	if (!pm_runtime_enabled(dev)) {
174762306a36Sopenharmony_ci		if (dev->power.runtime_status == RPM_ACTIVE)
174862306a36Sopenharmony_ci			pm_runtime_set_suspended(dev);
174962306a36Sopenharmony_ci		if (dev->power.irq_safe) {
175062306a36Sopenharmony_ci			spin_lock_irq(&dev->power.lock);
175162306a36Sopenharmony_ci			dev->power.irq_safe = 0;
175262306a36Sopenharmony_ci			spin_unlock_irq(&dev->power.lock);
175362306a36Sopenharmony_ci			if (dev->parent)
175462306a36Sopenharmony_ci				pm_runtime_put(dev->parent);
175562306a36Sopenharmony_ci		}
175662306a36Sopenharmony_ci	}
175762306a36Sopenharmony_ci}
175862306a36Sopenharmony_ci
175962306a36Sopenharmony_ci/**
176062306a36Sopenharmony_ci * pm_runtime_remove - Prepare for removing a device from device hierarchy.
176162306a36Sopenharmony_ci * @dev: Device object being removed from device hierarchy.
176262306a36Sopenharmony_ci */
176362306a36Sopenharmony_civoid pm_runtime_remove(struct device *dev)
176462306a36Sopenharmony_ci{
176562306a36Sopenharmony_ci	__pm_runtime_disable(dev, false);
176662306a36Sopenharmony_ci	pm_runtime_reinit(dev);
176762306a36Sopenharmony_ci}
176862306a36Sopenharmony_ci
176962306a36Sopenharmony_ci/**
177062306a36Sopenharmony_ci * pm_runtime_get_suppliers - Resume and reference-count supplier devices.
177162306a36Sopenharmony_ci * @dev: Consumer device.
177262306a36Sopenharmony_ci */
177362306a36Sopenharmony_civoid pm_runtime_get_suppliers(struct device *dev)
177462306a36Sopenharmony_ci{
177562306a36Sopenharmony_ci	struct device_link *link;
177662306a36Sopenharmony_ci	int idx;
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci	idx = device_links_read_lock();
177962306a36Sopenharmony_ci
178062306a36Sopenharmony_ci	list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
178162306a36Sopenharmony_ci				device_links_read_lock_held())
178262306a36Sopenharmony_ci		if (link->flags & DL_FLAG_PM_RUNTIME) {
178362306a36Sopenharmony_ci			link->supplier_preactivated = true;
178462306a36Sopenharmony_ci			pm_runtime_get_sync(link->supplier);
178562306a36Sopenharmony_ci		}
178662306a36Sopenharmony_ci
178762306a36Sopenharmony_ci	device_links_read_unlock(idx);
178862306a36Sopenharmony_ci}
178962306a36Sopenharmony_ci
179062306a36Sopenharmony_ci/**
179162306a36Sopenharmony_ci * pm_runtime_put_suppliers - Drop references to supplier devices.
179262306a36Sopenharmony_ci * @dev: Consumer device.
179362306a36Sopenharmony_ci */
179462306a36Sopenharmony_civoid pm_runtime_put_suppliers(struct device *dev)
179562306a36Sopenharmony_ci{
179662306a36Sopenharmony_ci	struct device_link *link;
179762306a36Sopenharmony_ci	int idx;
179862306a36Sopenharmony_ci
179962306a36Sopenharmony_ci	idx = device_links_read_lock();
180062306a36Sopenharmony_ci
180162306a36Sopenharmony_ci	list_for_each_entry_rcu(link, &dev->links.suppliers, c_node,
180262306a36Sopenharmony_ci				device_links_read_lock_held())
180362306a36Sopenharmony_ci		if (link->supplier_preactivated) {
180462306a36Sopenharmony_ci			link->supplier_preactivated = false;
180562306a36Sopenharmony_ci			pm_runtime_put(link->supplier);
180662306a36Sopenharmony_ci		}
180762306a36Sopenharmony_ci
180862306a36Sopenharmony_ci	device_links_read_unlock(idx);
180962306a36Sopenharmony_ci}
181062306a36Sopenharmony_ci
181162306a36Sopenharmony_civoid pm_runtime_new_link(struct device *dev)
181262306a36Sopenharmony_ci{
181362306a36Sopenharmony_ci	spin_lock_irq(&dev->power.lock);
181462306a36Sopenharmony_ci	dev->power.links_count++;
181562306a36Sopenharmony_ci	spin_unlock_irq(&dev->power.lock);
181662306a36Sopenharmony_ci}
181762306a36Sopenharmony_ci
181862306a36Sopenharmony_cistatic void pm_runtime_drop_link_count(struct device *dev)
181962306a36Sopenharmony_ci{
182062306a36Sopenharmony_ci	spin_lock_irq(&dev->power.lock);
182162306a36Sopenharmony_ci	WARN_ON(dev->power.links_count == 0);
182262306a36Sopenharmony_ci	dev->power.links_count--;
182362306a36Sopenharmony_ci	spin_unlock_irq(&dev->power.lock);
182462306a36Sopenharmony_ci}
182562306a36Sopenharmony_ci
182662306a36Sopenharmony_ci/**
182762306a36Sopenharmony_ci * pm_runtime_drop_link - Prepare for device link removal.
182862306a36Sopenharmony_ci * @link: Device link going away.
182962306a36Sopenharmony_ci *
183062306a36Sopenharmony_ci * Drop the link count of the consumer end of @link and decrement the supplier
183162306a36Sopenharmony_ci * device's runtime PM usage counter as many times as needed to drop all of the
183262306a36Sopenharmony_ci * PM runtime reference to it from the consumer.
183362306a36Sopenharmony_ci */
183462306a36Sopenharmony_civoid pm_runtime_drop_link(struct device_link *link)
183562306a36Sopenharmony_ci{
183662306a36Sopenharmony_ci	if (!(link->flags & DL_FLAG_PM_RUNTIME))
183762306a36Sopenharmony_ci		return;
183862306a36Sopenharmony_ci
183962306a36Sopenharmony_ci	pm_runtime_drop_link_count(link->consumer);
184062306a36Sopenharmony_ci	pm_runtime_release_supplier(link);
184162306a36Sopenharmony_ci	pm_request_idle(link->supplier);
184262306a36Sopenharmony_ci}
184362306a36Sopenharmony_ci
184462306a36Sopenharmony_cistatic bool pm_runtime_need_not_resume(struct device *dev)
184562306a36Sopenharmony_ci{
184662306a36Sopenharmony_ci	return atomic_read(&dev->power.usage_count) <= 1 &&
184762306a36Sopenharmony_ci		(atomic_read(&dev->power.child_count) == 0 ||
184862306a36Sopenharmony_ci		 dev->power.ignore_children);
184962306a36Sopenharmony_ci}
185062306a36Sopenharmony_ci
185162306a36Sopenharmony_ci/**
185262306a36Sopenharmony_ci * pm_runtime_force_suspend - Force a device into suspend state if needed.
185362306a36Sopenharmony_ci * @dev: Device to suspend.
185462306a36Sopenharmony_ci *
185562306a36Sopenharmony_ci * Disable runtime PM so we safely can check the device's runtime PM status and
185662306a36Sopenharmony_ci * if it is active, invoke its ->runtime_suspend callback to suspend it and
185762306a36Sopenharmony_ci * change its runtime PM status field to RPM_SUSPENDED.  Also, if the device's
185862306a36Sopenharmony_ci * usage and children counters don't indicate that the device was in use before
185962306a36Sopenharmony_ci * the system-wide transition under way, decrement its parent's children counter
186062306a36Sopenharmony_ci * (if there is a parent).  Keep runtime PM disabled to preserve the state
186162306a36Sopenharmony_ci * unless we encounter errors.
186262306a36Sopenharmony_ci *
186362306a36Sopenharmony_ci * Typically this function may be invoked from a system suspend callback to make
186462306a36Sopenharmony_ci * sure the device is put into low power state and it should only be used during
186562306a36Sopenharmony_ci * system-wide PM transitions to sleep states.  It assumes that the analogous
186662306a36Sopenharmony_ci * pm_runtime_force_resume() will be used to resume the device.
186762306a36Sopenharmony_ci *
186862306a36Sopenharmony_ci * Do not use with DPM_FLAG_SMART_SUSPEND as this can lead to an inconsistent
186962306a36Sopenharmony_ci * state where this function has called the ->runtime_suspend callback but the
187062306a36Sopenharmony_ci * PM core marks the driver as runtime active.
187162306a36Sopenharmony_ci */
187262306a36Sopenharmony_ciint pm_runtime_force_suspend(struct device *dev)
187362306a36Sopenharmony_ci{
187462306a36Sopenharmony_ci	int (*callback)(struct device *);
187562306a36Sopenharmony_ci	int ret;
187662306a36Sopenharmony_ci
187762306a36Sopenharmony_ci	pm_runtime_disable(dev);
187862306a36Sopenharmony_ci	if (pm_runtime_status_suspended(dev))
187962306a36Sopenharmony_ci		return 0;
188062306a36Sopenharmony_ci
188162306a36Sopenharmony_ci	callback = RPM_GET_CALLBACK(dev, runtime_suspend);
188262306a36Sopenharmony_ci
188362306a36Sopenharmony_ci	dev_pm_enable_wake_irq_check(dev, true);
188462306a36Sopenharmony_ci	ret = callback ? callback(dev) : 0;
188562306a36Sopenharmony_ci	if (ret)
188662306a36Sopenharmony_ci		goto err;
188762306a36Sopenharmony_ci
188862306a36Sopenharmony_ci	dev_pm_enable_wake_irq_complete(dev);
188962306a36Sopenharmony_ci
189062306a36Sopenharmony_ci	/*
189162306a36Sopenharmony_ci	 * If the device can stay in suspend after the system-wide transition
189262306a36Sopenharmony_ci	 * to the working state that will follow, drop the children counter of
189362306a36Sopenharmony_ci	 * its parent, but set its status to RPM_SUSPENDED anyway in case this
189462306a36Sopenharmony_ci	 * function will be called again for it in the meantime.
189562306a36Sopenharmony_ci	 */
189662306a36Sopenharmony_ci	if (pm_runtime_need_not_resume(dev)) {
189762306a36Sopenharmony_ci		pm_runtime_set_suspended(dev);
189862306a36Sopenharmony_ci	} else {
189962306a36Sopenharmony_ci		__update_runtime_status(dev, RPM_SUSPENDED);
190062306a36Sopenharmony_ci		dev->power.needs_force_resume = 1;
190162306a36Sopenharmony_ci	}
190262306a36Sopenharmony_ci
190362306a36Sopenharmony_ci	return 0;
190462306a36Sopenharmony_ci
190562306a36Sopenharmony_cierr:
190662306a36Sopenharmony_ci	dev_pm_disable_wake_irq_check(dev, true);
190762306a36Sopenharmony_ci	pm_runtime_enable(dev);
190862306a36Sopenharmony_ci	return ret;
190962306a36Sopenharmony_ci}
191062306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_runtime_force_suspend);
191162306a36Sopenharmony_ci
191262306a36Sopenharmony_ci/**
191362306a36Sopenharmony_ci * pm_runtime_force_resume - Force a device into resume state if needed.
191462306a36Sopenharmony_ci * @dev: Device to resume.
191562306a36Sopenharmony_ci *
191662306a36Sopenharmony_ci * Prior invoking this function we expect the user to have brought the device
191762306a36Sopenharmony_ci * into low power state by a call to pm_runtime_force_suspend(). Here we reverse
191862306a36Sopenharmony_ci * those actions and bring the device into full power, if it is expected to be
191962306a36Sopenharmony_ci * used on system resume.  In the other case, we defer the resume to be managed
192062306a36Sopenharmony_ci * via runtime PM.
192162306a36Sopenharmony_ci *
192262306a36Sopenharmony_ci * Typically this function may be invoked from a system resume callback.
192362306a36Sopenharmony_ci */
192462306a36Sopenharmony_ciint pm_runtime_force_resume(struct device *dev)
192562306a36Sopenharmony_ci{
192662306a36Sopenharmony_ci	int (*callback)(struct device *);
192762306a36Sopenharmony_ci	int ret = 0;
192862306a36Sopenharmony_ci
192962306a36Sopenharmony_ci	if (!pm_runtime_status_suspended(dev) || !dev->power.needs_force_resume)
193062306a36Sopenharmony_ci		goto out;
193162306a36Sopenharmony_ci
193262306a36Sopenharmony_ci	/*
193362306a36Sopenharmony_ci	 * The value of the parent's children counter is correct already, so
193462306a36Sopenharmony_ci	 * just update the status of the device.
193562306a36Sopenharmony_ci	 */
193662306a36Sopenharmony_ci	__update_runtime_status(dev, RPM_ACTIVE);
193762306a36Sopenharmony_ci
193862306a36Sopenharmony_ci	callback = RPM_GET_CALLBACK(dev, runtime_resume);
193962306a36Sopenharmony_ci
194062306a36Sopenharmony_ci	dev_pm_disable_wake_irq_check(dev, false);
194162306a36Sopenharmony_ci	ret = callback ? callback(dev) : 0;
194262306a36Sopenharmony_ci	if (ret) {
194362306a36Sopenharmony_ci		pm_runtime_set_suspended(dev);
194462306a36Sopenharmony_ci		dev_pm_enable_wake_irq_check(dev, false);
194562306a36Sopenharmony_ci		goto out;
194662306a36Sopenharmony_ci	}
194762306a36Sopenharmony_ci
194862306a36Sopenharmony_ci	pm_runtime_mark_last_busy(dev);
194962306a36Sopenharmony_ciout:
195062306a36Sopenharmony_ci	dev->power.needs_force_resume = 0;
195162306a36Sopenharmony_ci	pm_runtime_enable(dev);
195262306a36Sopenharmony_ci	return ret;
195362306a36Sopenharmony_ci}
195462306a36Sopenharmony_ciEXPORT_SYMBOL_GPL(pm_runtime_force_resume);
1955