blob: a690fd40026051453ba138d4919811b726b9789b [file] [log] [blame]
Linus Torvalds1da177e2005-04-16 15:20:36 -07001/*
2 * drivers/base/power/main.c - Where the driver meets power management.
3 *
4 * Copyright (c) 2003 Patrick Mochel
5 * Copyright (c) 2003 Open Source Development Lab
6 *
7 * This file is released under the GPLv2
8 *
9 *
10 * The driver model core calls device_pm_add() when a device is registered.
Uwe Kleine-Königb5950762010-11-01 15:38:34 -040011 * This will initialize the embedded device_pm_info object in the device
Linus Torvalds1da177e2005-04-16 15:20:36 -070012 * and add it to the list of power-controlled devices. sysfs entries for
13 * controlling device power management will also be added.
14 *
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020015 * A separate list is used for keeping track of power info, because the power
16 * domain dependencies may differ from the ancestral dependencies that the
17 * subsystem list maintains.
Linus Torvalds1da177e2005-04-16 15:20:36 -070018 */
19
Linus Torvalds1da177e2005-04-16 15:20:36 -070020#include <linux/device.h>
Paul Gortmaker1b6bc322011-05-27 07:12:15 -040021#include <linux/export.h>
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -070022#include <linux/mutex.h>
Alan Sterncd59abf2007-09-21 15:36:56 -040023#include <linux/pm.h>
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +020024#include <linux/pm_runtime.h>
Zhonghui Fu431d4522015-03-18 15:54:27 +010025#include <linux/pm-trace.h>
Tony Lindgren4990d4f2015-05-18 15:40:29 -070026#include <linux/pm_wakeirq.h>
Rafael J. Wysocki2ed8d2b2009-03-16 22:34:06 +010027#include <linux/interrupt.h>
Arjan van de Venf2511772009-12-13 20:29:01 +010028#include <linux/sched.h>
Ingo Molnarb17b0152017-02-08 18:51:35 +010029#include <linux/sched/debug.h>
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +010030#include <linux/async.h>
Rafael J. Wysocki1e75227e2010-12-03 22:58:05 +010031#include <linux/suspend.h>
Shuah Khan53644672013-07-26 13:30:20 -060032#include <trace/events/power.h>
Viresh Kumar2f0aea92014-03-04 11:00:26 +080033#include <linux/cpufreq.h>
Preeti U Murthy8651f972012-07-09 10:12:56 +020034#include <linux/cpuidle.h>
Benoit Goby70fea602013-10-17 10:48:46 -070035#include <linux/timer.h>
36
Alan Sterncd59abf2007-09-21 15:36:56 -040037#include "../base.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070038#include "power.h"
39
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +010040typedef int (*pm_callback_t)(struct device *);
41
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010042/*
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020043 * The entries in the dpm_list list are in a depth first order, simply
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010044 * because children are guaranteed to be discovered after parents, and
45 * are inserted at the back of the list on discovery.
46 *
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -080047 * Since device_pm_add() may be called with a device lock held,
48 * we must never try to acquire a device lock while holding
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010049 * dpm_list_mutex.
50 */
51
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020052LIST_HEAD(dpm_list);
Sachin Kamat7664e962012-07-17 22:38:08 +020053static LIST_HEAD(dpm_prepared_list);
54static LIST_HEAD(dpm_suspended_list);
55static LIST_HEAD(dpm_late_early_list);
56static LIST_HEAD(dpm_noirq_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -070057
ShuoX Liu2a77c462011-08-10 23:01:26 +020058struct suspend_stats suspend_stats;
Alan Sterncd59abf2007-09-21 15:36:56 -040059static DEFINE_MUTEX(dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +010060static pm_message_t pm_transition;
Linus Torvalds1da177e2005-04-16 15:20:36 -070061
Rafael J. Wysocki098dff72010-09-22 22:10:57 +020062static int async_error;
63
Krzysztof Kozlowski952856d2017-06-12 17:19:31 +020064static const char *pm_verb(int event)
Shuah Khan53644672013-07-26 13:30:20 -060065{
66 switch (event) {
67 case PM_EVENT_SUSPEND:
68 return "suspend";
69 case PM_EVENT_RESUME:
70 return "resume";
71 case PM_EVENT_FREEZE:
72 return "freeze";
73 case PM_EVENT_QUIESCE:
74 return "quiesce";
75 case PM_EVENT_HIBERNATE:
76 return "hibernate";
77 case PM_EVENT_THAW:
78 return "thaw";
79 case PM_EVENT_RESTORE:
80 return "restore";
81 case PM_EVENT_RECOVER:
82 return "recover";
83 default:
84 return "(unknown PM event)";
85 }
86}
87
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020088/**
Rafael J. Wysockie91c11b2012-08-06 01:44:28 +020089 * device_pm_sleep_init - Initialize system suspend-related device fields.
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +020090 * @dev: Device object being initialized.
91 */
Rafael J. Wysockie91c11b2012-08-06 01:44:28 +020092void device_pm_sleep_init(struct device *dev)
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +020093{
Alan Sternf76b168b2011-06-18 20:22:23 +020094 dev->power.is_prepared = false;
Alan Stern6d0e0e82011-06-18 22:42:09 +020095 dev->power.is_suspended = false;
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +080096 dev->power.is_noirq_suspended = false;
97 dev->power.is_late_suspended = false;
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +010098 init_completion(&dev->power.completion);
Colin Cross152e1d52010-09-03 01:24:07 +020099 complete_all(&dev->power.completion);
Rafael J. Wysocki074037e2010-09-22 22:09:10 +0200100 dev->power.wakeup = NULL;
Rafael J. Wysocki22110fa2011-04-26 11:33:09 +0200101 INIT_LIST_HEAD(&dev->power.entry);
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +0200102}
103
104/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200105 * device_pm_lock - Lock the list of active devices used by the PM core.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200106 */
107void device_pm_lock(void)
108{
109 mutex_lock(&dpm_list_mtx);
110}
111
112/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200113 * device_pm_unlock - Unlock the list of active devices used by the PM core.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200114 */
115void device_pm_unlock(void)
116{
117 mutex_unlock(&dpm_list_mtx);
118}
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100119
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100120/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200121 * device_pm_add - Add a device to the PM core's list of active devices.
122 * @dev: Device to add to the list.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100123 */
Alan Stern3b98aea2008-08-07 13:06:12 -0400124void device_pm_add(struct device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700125{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700126 pr_debug("PM: Adding info for %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100127 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
Tomeu Vizosoaa8e54b52016-01-07 16:46:14 +0100128 device_pm_check_callbacks(dev);
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700129 mutex_lock(&dpm_list_mtx);
Alan Sternf76b168b2011-06-18 20:22:23 +0200130 if (dev->parent && dev->parent->power.is_prepared)
Rafael J. Wysockib64959e2010-12-16 17:11:45 +0100131 dev_warn(dev, "parent %s should not be sleeping\n",
132 dev_name(dev->parent));
Alan Stern3b98aea2008-08-07 13:06:12 -0400133 list_add_tail(&dev->power.entry, &dpm_list);
Rafael J. Wysocki9ed98952016-10-30 17:32:16 +0100134 dev->power.in_dpm_list = true;
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200135 mutex_unlock(&dpm_list_mtx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136}
137
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100138/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200139 * device_pm_remove - Remove a device from the PM core's list of active devices.
140 * @dev: Device to be removed from the list.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100141 */
Rafael J. Wysocki9cddad72007-06-13 15:53:34 +0200142void device_pm_remove(struct device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143{
144 pr_debug("PM: Removing info for %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100145 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100146 complete_all(&dev->power.completion);
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700147 mutex_lock(&dpm_list_mtx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 list_del_init(&dev->power.entry);
Rafael J. Wysocki9ed98952016-10-30 17:32:16 +0100149 dev->power.in_dpm_list = false;
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700150 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki074037e2010-09-22 22:09:10 +0200151 device_wakeup_disable(dev);
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +0200152 pm_runtime_remove(dev);
Tomeu Vizosoaa8e54b52016-01-07 16:46:14 +0100153 device_pm_check_callbacks(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100154}
155
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200156/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200157 * device_pm_move_before - Move device in the PM core's list of active devices.
158 * @deva: Device to move in dpm_list.
159 * @devb: Device @deva should come before.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100160 */
161void device_pm_move_before(struct device *deva, struct device *devb)
162{
163 pr_debug("PM: Moving %s:%s before %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100164 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
165 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
Cornelia Huckffa6a702009-03-04 12:44:00 +0100166 /* Delete deva from dpm_list and reinsert before devb. */
167 list_move_tail(&deva->power.entry, &devb->power.entry);
168}
169
170/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200171 * device_pm_move_after - Move device in the PM core's list of active devices.
172 * @deva: Device to move in dpm_list.
173 * @devb: Device @deva should come after.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100174 */
175void device_pm_move_after(struct device *deva, struct device *devb)
176{
177 pr_debug("PM: Moving %s:%s after %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100178 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
179 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
Cornelia Huckffa6a702009-03-04 12:44:00 +0100180 /* Delete deva from dpm_list and reinsert after devb. */
181 list_move(&deva->power.entry, &devb->power.entry);
182}
183
184/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200185 * device_pm_move_last - Move device to end of the PM core's list of devices.
186 * @dev: Device to move in dpm_list.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100187 */
188void device_pm_move_last(struct device *dev)
189{
190 pr_debug("PM: Moving %s:%s to end of list\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100191 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
Cornelia Huckffa6a702009-03-04 12:44:00 +0100192 list_move_tail(&dev->power.entry, &dpm_list);
193}
194
Bjorn Helgaas7f817ba2018-04-26 16:36:41 -0500195static ktime_t initcall_debug_start(struct device *dev, void *cb)
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100196{
Bjorn Helgaas143711f2018-04-26 16:36:34 -0500197 if (!pm_print_times_enabled)
198 return 0;
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100199
Bjorn Helgaas7f817ba2018-04-26 16:36:41 -0500200 dev_info(dev, "calling %pF @ %i, parent: %s\n", cb,
201 task_pid_nr(current),
202 dev->parent ? dev_name(dev->parent) : "none");
Bjorn Helgaas143711f2018-04-26 16:36:34 -0500203 return ktime_get();
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100204}
205
206static void initcall_debug_report(struct device *dev, ktime_t calltime,
Bjorn Helgaas7f817ba2018-04-26 16:36:41 -0500207 void *cb, int error)
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100208{
Shuah Khan53644672013-07-26 13:30:20 -0600209 ktime_t rettime;
210 s64 nsecs;
211
Bjorn Helgaas143711f2018-04-26 16:36:34 -0500212 if (!pm_print_times_enabled)
213 return;
214
Shuah Khan53644672013-07-26 13:30:20 -0600215 rettime = ktime_get();
216 nsecs = (s64) ktime_to_ns(ktime_sub(rettime, calltime));
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100217
Bjorn Helgaas7f817ba2018-04-26 16:36:41 -0500218 dev_info(dev, "%pF returned %d after %Ld usecs\n", cb, error,
219 (unsigned long long)nsecs >> 10);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100220}
221
Cornelia Huckffa6a702009-03-04 12:44:00 +0100222/**
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100223 * dpm_wait - Wait for a PM operation to complete.
224 * @dev: Device to wait for.
225 * @async: If unset, wait only if the device's power.async_suspend flag is set.
226 */
227static void dpm_wait(struct device *dev, bool async)
228{
229 if (!dev)
230 return;
231
Rafael J. Wysocki0e06b4a2010-01-23 22:25:15 +0100232 if (async || (pm_async_enabled && dev->power.async_suspend))
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100233 wait_for_completion(&dev->power.completion);
234}
235
236static int dpm_wait_fn(struct device *dev, void *async_ptr)
237{
238 dpm_wait(dev, *((bool *)async_ptr));
239 return 0;
240}
241
242static void dpm_wait_for_children(struct device *dev, bool async)
243{
244 device_for_each_child(dev, &async, dpm_wait_fn);
245}
246
Rafael J. Wysocki8c73b422016-10-30 17:28:49 +0100247static void dpm_wait_for_suppliers(struct device *dev, bool async)
248{
249 struct device_link *link;
250 int idx;
251
252 idx = device_links_read_lock();
253
254 /*
255 * If the supplier goes away right after we've checked the link to it,
256 * we'll wait for its completion to change the state, but that's fine,
257 * because the only things that will block as a result are the SRCU
258 * callbacks freeing the link objects for the links in the list we're
259 * walking.
260 */
261 list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
262 if (READ_ONCE(link->status) != DL_STATE_DORMANT)
263 dpm_wait(link->supplier, async);
264
265 device_links_read_unlock(idx);
266}
267
268static void dpm_wait_for_superior(struct device *dev, bool async)
269{
270 dpm_wait(dev->parent, async);
271 dpm_wait_for_suppliers(dev, async);
272}
273
274static void dpm_wait_for_consumers(struct device *dev, bool async)
275{
276 struct device_link *link;
277 int idx;
278
279 idx = device_links_read_lock();
280
281 /*
282 * The status of a device link can only be changed from "dormant" by a
283 * probe, but that cannot happen during system suspend/resume. In
284 * theory it can change to "dormant" at that time, but then it is
285 * reasonable to wait for the target device anyway (eg. if it goes
286 * away, it's better to wait for it to go away completely and then
287 * continue instead of trying to continue in parallel with its
288 * unregistration).
289 */
290 list_for_each_entry_rcu(link, &dev->links.consumers, s_node)
291 if (READ_ONCE(link->status) != DL_STATE_DORMANT)
292 dpm_wait(link->consumer, async);
293
294 device_links_read_unlock(idx);
295}
296
297static void dpm_wait_for_subordinate(struct device *dev, bool async)
298{
299 dpm_wait_for_children(dev, async);
300 dpm_wait_for_consumers(dev, async);
301}
302
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100303/**
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100304 * pm_op - Return the PM operation appropriate for given PM event.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200305 * @ops: PM operations to choose from.
306 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200307 */
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100308static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200309{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200310 switch (state.event) {
311#ifdef CONFIG_SUSPEND
312 case PM_EVENT_SUSPEND:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100313 return ops->suspend;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200314 case PM_EVENT_RESUME:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100315 return ops->resume;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200316#endif /* CONFIG_SUSPEND */
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200317#ifdef CONFIG_HIBERNATE_CALLBACKS
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200318 case PM_EVENT_FREEZE:
319 case PM_EVENT_QUIESCE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100320 return ops->freeze;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200321 case PM_EVENT_HIBERNATE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100322 return ops->poweroff;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200323 case PM_EVENT_THAW:
324 case PM_EVENT_RECOVER:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100325 return ops->thaw;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200326 break;
327 case PM_EVENT_RESTORE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100328 return ops->restore;
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200329#endif /* CONFIG_HIBERNATE_CALLBACKS */
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200330 }
Arjan van de Venf2511772009-12-13 20:29:01 +0100331
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100332 return NULL;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200333}
334
335/**
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100336 * pm_late_early_op - Return the PM operation appropriate for given PM event.
337 * @ops: PM operations to choose from.
338 * @state: PM transition of the system being carried out.
339 *
340 * Runtime PM is disabled for @dev while this function is being executed.
341 */
342static pm_callback_t pm_late_early_op(const struct dev_pm_ops *ops,
343 pm_message_t state)
344{
345 switch (state.event) {
346#ifdef CONFIG_SUSPEND
347 case PM_EVENT_SUSPEND:
348 return ops->suspend_late;
349 case PM_EVENT_RESUME:
350 return ops->resume_early;
351#endif /* CONFIG_SUSPEND */
352#ifdef CONFIG_HIBERNATE_CALLBACKS
353 case PM_EVENT_FREEZE:
354 case PM_EVENT_QUIESCE:
355 return ops->freeze_late;
356 case PM_EVENT_HIBERNATE:
357 return ops->poweroff_late;
358 case PM_EVENT_THAW:
359 case PM_EVENT_RECOVER:
360 return ops->thaw_early;
361 case PM_EVENT_RESTORE:
362 return ops->restore_early;
363#endif /* CONFIG_HIBERNATE_CALLBACKS */
364 }
365
366 return NULL;
367}
368
369/**
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100370 * pm_noirq_op - Return the PM operation appropriate for given PM event.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200371 * @ops: PM operations to choose from.
372 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200373 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200374 * The driver of @dev will not receive interrupts while this function is being
375 * executed.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200376 */
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100377static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200378{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200379 switch (state.event) {
380#ifdef CONFIG_SUSPEND
381 case PM_EVENT_SUSPEND:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100382 return ops->suspend_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200383 case PM_EVENT_RESUME:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100384 return ops->resume_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200385#endif /* CONFIG_SUSPEND */
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200386#ifdef CONFIG_HIBERNATE_CALLBACKS
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200387 case PM_EVENT_FREEZE:
388 case PM_EVENT_QUIESCE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100389 return ops->freeze_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200390 case PM_EVENT_HIBERNATE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100391 return ops->poweroff_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200392 case PM_EVENT_THAW:
393 case PM_EVENT_RECOVER:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100394 return ops->thaw_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200395 case PM_EVENT_RESTORE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100396 return ops->restore_noirq;
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200397#endif /* CONFIG_HIBERNATE_CALLBACKS */
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200398 }
Arjan van de Venf2511772009-12-13 20:29:01 +0100399
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100400 return NULL;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200401}
402
Krzysztof Kozlowskie3771fa2017-06-12 17:19:32 +0200403static void pm_dev_dbg(struct device *dev, pm_message_t state, const char *info)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200404{
405 dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event),
406 ((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ?
407 ", may wakeup" : "");
408}
409
Krzysztof Kozlowskie3771fa2017-06-12 17:19:32 +0200410static void pm_dev_err(struct device *dev, pm_message_t state, const char *info,
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200411 int error)
412{
413 printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100414 dev_name(dev), pm_verb(state.event), info, error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200415}
416
Rafael J. Wysocki48059c092017-07-21 02:10:22 +0200417static void dpm_show_time(ktime_t starttime, pm_message_t state, int error,
Krzysztof Kozlowskie3771fa2017-06-12 17:19:32 +0200418 const char *info)
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100419{
420 ktime_t calltime;
Kevin Cernekee0702d9ee2010-09-20 22:32:10 +0200421 u64 usecs64;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100422 int usecs;
423
424 calltime = ktime_get();
425 usecs64 = ktime_to_ns(ktime_sub(calltime, starttime));
426 do_div(usecs64, NSEC_PER_USEC);
427 usecs = usecs64;
428 if (usecs == 0)
429 usecs = 1;
Rafael J. Wysocki8d8b2442017-07-19 02:38:44 +0200430
Rafael J. Wysocki48059c092017-07-21 02:10:22 +0200431 pm_pr_dbg("%s%s%s of devices %s after %ld.%03ld msecs\n",
Rafael J. Wysocki8d8b2442017-07-19 02:38:44 +0200432 info ?: "", info ? " " : "", pm_verb(state.event),
Rafael J. Wysocki48059c092017-07-21 02:10:22 +0200433 error ? "aborted" : "complete",
Rafael J. Wysocki8d8b2442017-07-19 02:38:44 +0200434 usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100435}
436
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100437static int dpm_run_callback(pm_callback_t cb, struct device *dev,
Krzysztof Kozlowskie3771fa2017-06-12 17:19:32 +0200438 pm_message_t state, const char *info)
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100439{
440 ktime_t calltime;
441 int error;
442
443 if (!cb)
444 return 0;
445
Bjorn Helgaas7f817ba2018-04-26 16:36:41 -0500446 calltime = initcall_debug_start(dev, cb);
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100447
448 pm_dev_dbg(dev, state, info);
Todd E Brandte8bca472014-06-10 07:31:22 -0700449 trace_device_pm_callback_start(dev, info, state.event);
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100450 error = cb(dev);
Todd E Brandte8bca472014-06-10 07:31:22 -0700451 trace_device_pm_callback_end(dev, error);
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100452 suspend_report_result(cb, error);
453
Bjorn Helgaas7f817ba2018-04-26 16:36:41 -0500454 initcall_debug_report(dev, calltime, cb, error);
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100455
456 return error;
457}
458
Benoit Goby70fea602013-10-17 10:48:46 -0700459#ifdef CONFIG_DPM_WATCHDOG
460struct dpm_watchdog {
461 struct device *dev;
462 struct task_struct *tsk;
463 struct timer_list timer;
464};
465
466#define DECLARE_DPM_WATCHDOG_ON_STACK(wd) \
467 struct dpm_watchdog wd
468
469/**
470 * dpm_watchdog_handler - Driver suspend / resume watchdog handler.
471 * @data: Watchdog object address.
472 *
473 * Called when a driver has timed out suspending or resuming.
474 * There's not much we can do here to recover so panic() to
475 * capture a crash-dump in pstore.
476 */
Kees Cook9c6c2732017-10-04 16:26:57 -0700477static void dpm_watchdog_handler(struct timer_list *t)
Benoit Goby70fea602013-10-17 10:48:46 -0700478{
Kees Cook9c6c2732017-10-04 16:26:57 -0700479 struct dpm_watchdog *wd = from_timer(wd, t, timer);
Benoit Goby70fea602013-10-17 10:48:46 -0700480
481 dev_emerg(wd->dev, "**** DPM device timeout ****\n");
482 show_stack(wd->tsk, NULL);
483 panic("%s %s: unrecoverable failure\n",
484 dev_driver_string(wd->dev), dev_name(wd->dev));
485}
486
487/**
488 * dpm_watchdog_set - Enable pm watchdog for given device.
489 * @wd: Watchdog. Must be allocated on the stack.
490 * @dev: Device to handle.
491 */
492static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev)
493{
494 struct timer_list *timer = &wd->timer;
495
496 wd->dev = dev;
497 wd->tsk = current;
498
Kees Cook9c6c2732017-10-04 16:26:57 -0700499 timer_setup_on_stack(timer, dpm_watchdog_handler, 0);
Benoit Goby70fea602013-10-17 10:48:46 -0700500 /* use same timeout value for both suspend and resume */
501 timer->expires = jiffies + HZ * CONFIG_DPM_WATCHDOG_TIMEOUT;
Benoit Goby70fea602013-10-17 10:48:46 -0700502 add_timer(timer);
503}
504
505/**
506 * dpm_watchdog_clear - Disable suspend/resume watchdog.
507 * @wd: Watchdog to disable.
508 */
509static void dpm_watchdog_clear(struct dpm_watchdog *wd)
510{
511 struct timer_list *timer = &wd->timer;
512
513 del_timer_sync(timer);
514 destroy_timer_on_stack(timer);
515}
516#else
517#define DECLARE_DPM_WATCHDOG_ON_STACK(wd)
518#define dpm_watchdog_set(x, y)
519#define dpm_watchdog_clear(x)
520#endif
521
Alan Sterncd59abf2007-09-21 15:36:56 -0400522/*------------------------- Resume routines -------------------------*/
523
524/**
Rafael J. Wysocki34879722017-12-07 02:41:18 +0100525 * dev_pm_skip_next_resume_phases - Skip next system resume phases for device.
526 * @dev: Target device.
527 *
528 * Make the core skip the "early resume" and "resume" phases for @dev.
529 *
530 * This function can be called by middle-layer code during the "noirq" phase of
531 * system resume if necessary, but not by device drivers.
532 */
533void dev_pm_skip_next_resume_phases(struct device *dev)
534{
535 dev->power.is_late_suspended = false;
536 dev->power.is_suspended = false;
537}
538
539/**
Rafael J. Wysocki75e94642017-12-10 01:00:45 +0100540 * suspend_event - Return a "suspend" message for given "resume" one.
541 * @resume_msg: PM message representing a system-wide resume transition.
542 */
543static pm_message_t suspend_event(pm_message_t resume_msg)
544{
545 switch (resume_msg.event) {
546 case PM_EVENT_RESUME:
547 return PMSG_SUSPEND;
548 case PM_EVENT_THAW:
549 case PM_EVENT_RESTORE:
550 return PMSG_FREEZE;
551 case PM_EVENT_RECOVER:
552 return PMSG_HIBERNATE;
553 }
554 return PMSG_ON;
555}
556
557/**
Rafael J. Wysocki0d4b54c2017-11-18 15:31:49 +0100558 * dev_pm_may_skip_resume - System-wide device resume optimization check.
559 * @dev: Target device.
560 *
561 * Checks whether or not the device may be left in suspend after a system-wide
562 * transition to the working state.
563 */
564bool dev_pm_may_skip_resume(struct device *dev)
565{
566 return !dev->power.must_resume && pm_transition.event != PM_EVENT_RESTORE;
567}
568
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +0100569static pm_callback_t dpm_subsys_resume_noirq_cb(struct device *dev,
570 pm_message_t state,
571 const char **info_p)
Alan Sterncd59abf2007-09-21 15:36:56 -0400572{
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +0100573 pm_callback_t callback;
574 const char *info;
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800575
Rafael J. Wysocki564b9052011-06-23 01:52:55 +0200576 if (dev->pm_domain) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100577 info = "noirq power domain ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100578 callback = pm_noirq_op(&dev->pm_domain->ops, state);
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200579 } else if (dev->type && dev->type->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100580 info = "noirq type ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100581 callback = pm_noirq_op(dev->type->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100582 } else if (dev->class && dev->class->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100583 info = "noirq class ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100584 callback = pm_noirq_op(dev->class->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100585 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100586 info = "noirq bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100587 callback = pm_noirq_op(dev->bus->pm, state);
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +0100588 } else {
589 return NULL;
Dominik Brodowskie7176a32010-03-15 21:43:11 +0100590 }
591
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +0100592 if (info_p)
593 *info_p = info;
594
595 return callback;
596}
597
Rafael J. Wysocki75e94642017-12-10 01:00:45 +0100598static pm_callback_t dpm_subsys_suspend_noirq_cb(struct device *dev,
599 pm_message_t state,
600 const char **info_p);
601
602static pm_callback_t dpm_subsys_suspend_late_cb(struct device *dev,
603 pm_message_t state,
604 const char **info_p);
605
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +0100606/**
607 * device_resume_noirq - Execute a "noirq resume" callback for given device.
608 * @dev: Device to handle.
609 * @state: PM transition of the system being carried out.
610 * @async: If true, the device is being resumed asynchronously.
611 *
612 * The driver of @dev will not receive interrupts while this function is being
613 * executed.
614 */
615static int device_resume_noirq(struct device *dev, pm_message_t state, bool async)
616{
617 pm_callback_t callback;
618 const char *info;
Rafael J. Wysocki32bfa562017-12-10 01:02:13 +0100619 bool skip_resume;
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +0100620 int error = 0;
621
622 TRACE_DEVICE(dev);
623 TRACE_RESUME(0);
624
625 if (dev->power.syscore || dev->power.direct_complete)
626 goto Out;
627
628 if (!dev->power.is_noirq_suspended)
629 goto Out;
630
631 dpm_wait_for_superior(dev, async);
632
Rafael J. Wysocki32bfa562017-12-10 01:02:13 +0100633 skip_resume = dev_pm_may_skip_resume(dev);
634
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +0100635 callback = dpm_subsys_resume_noirq_cb(dev, state, &info);
Rafael J. Wysocki75e94642017-12-10 01:00:45 +0100636 if (callback)
637 goto Run;
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +0100638
Rafael J. Wysocki32bfa562017-12-10 01:02:13 +0100639 if (skip_resume)
640 goto Skip;
641
Rafael J. Wysocki75e94642017-12-10 01:00:45 +0100642 if (dev_pm_smart_suspend_and_suspended(dev)) {
643 pm_message_t suspend_msg = suspend_event(state);
644
645 /*
646 * If "freeze" callbacks have been skipped during a transition
647 * related to hibernation, the subsequent "thaw" callbacks must
648 * be skipped too or bad things may happen. Otherwise, resume
649 * callbacks are going to be run for the device, so its runtime
650 * PM status must be changed to reflect the new state after the
651 * transition under way.
652 */
653 if (!dpm_subsys_suspend_late_cb(dev, suspend_msg, NULL) &&
654 !dpm_subsys_suspend_noirq_cb(dev, suspend_msg, NULL)) {
655 if (state.event == PM_EVENT_THAW) {
Rafael J. Wysocki32bfa562017-12-10 01:02:13 +0100656 skip_resume = true;
Rafael J. Wysocki75e94642017-12-10 01:00:45 +0100657 goto Skip;
658 } else {
659 pm_runtime_set_active(dev);
660 }
661 }
662 }
663
664 if (dev->driver && dev->driver->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100665 info = "noirq driver ";
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100666 callback = pm_noirq_op(dev->driver->pm, state);
667 }
668
Rafael J. Wysocki75e94642017-12-10 01:00:45 +0100669Run:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100670 error = dpm_run_callback(callback, dev, state, info);
Rafael J. Wysocki75e94642017-12-10 01:00:45 +0100671
672Skip:
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800673 dev->power.is_noirq_suspended = false;
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100674
Rafael J. Wysocki32bfa562017-12-10 01:02:13 +0100675 if (skip_resume) {
Rafael J. Wysocki0d4b54c2017-11-18 15:31:49 +0100676 /*
677 * The device is going to be left in suspend, but it might not
678 * have been in runtime suspend before the system suspended, so
679 * its runtime PM status needs to be updated to avoid confusing
680 * the runtime PM framework when runtime PM is enabled for the
681 * device again.
682 */
683 pm_runtime_set_suspended(dev);
Rafael J. Wysocki34fb8f02017-12-10 00:56:50 +0100684 dev_pm_skip_next_resume_phases(dev);
Rafael J. Wysocki0d4b54c2017-11-18 15:31:49 +0100685 }
686
Rafael J. Wysocki75e94642017-12-10 01:00:45 +0100687Out:
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800688 complete_all(&dev->power.completion);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100689 TRACE_RESUME(error);
690 return error;
691}
692
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800693static bool is_async(struct device *dev)
694{
695 return dev->power.async_suspend && pm_async_enabled
696 && !pm_trace_is_enabled();
697}
698
699static void async_resume_noirq(void *data, async_cookie_t cookie)
700{
701 struct device *dev = (struct device *)data;
702 int error;
703
704 error = device_resume_noirq(dev, pm_transition, true);
705 if (error)
706 pm_dev_err(dev, pm_transition, " async", error);
707
708 put_device(dev);
709}
710
Rafael J. Wysocki786f41f2017-07-21 02:09:22 +0200711void dpm_noirq_resume_devices(pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100712{
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800713 struct device *dev;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100714 ktime_t starttime = ktime_get();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100715
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700716 trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, true);
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200717 mutex_lock(&dpm_list_mtx);
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800718 pm_transition = state;
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100719
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800720 /*
721 * Advanced the async threads upfront,
722 * in case the starting of async threads is
723 * delayed by non-async resuming devices.
724 */
725 list_for_each_entry(dev, &dpm_noirq_list, power.entry) {
726 reinit_completion(&dev->power.completion);
727 if (is_async(dev)) {
728 get_device(dev);
729 async_schedule(async_resume_noirq, dev);
730 }
731 }
732
733 while (!list_empty(&dpm_noirq_list)) {
734 dev = to_device(dpm_noirq_list.next);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100735 get_device(dev);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100736 list_move_tail(&dev->power.entry, &dpm_late_early_list);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100737 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100738
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800739 if (!is_async(dev)) {
740 int error;
741
742 error = device_resume_noirq(dev, state, false);
743 if (error) {
744 suspend_stats.failed_resume_noirq++;
745 dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
746 dpm_save_failed_dev(dev_name(dev));
747 pm_dev_err(dev, state, " noirq", error);
748 }
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100749 }
750
751 mutex_lock(&dpm_list_mtx);
752 put_device(dev);
753 }
754 mutex_unlock(&dpm_list_mtx);
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800755 async_synchronize_full();
Rafael J. Wysocki48059c092017-07-21 02:10:22 +0200756 dpm_show_time(starttime, state, 0, "noirq");
Rafael J. Wysocki786f41f2017-07-21 02:09:22 +0200757 trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, false);
758}
759
760void dpm_noirq_end(void)
761{
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100762 resume_device_irqs();
Tony Lindgren4990d4f2015-05-18 15:40:29 -0700763 device_wakeup_disarm_wake_irqs();
Preeti U Murthy8651f972012-07-09 10:12:56 +0200764 cpuidle_resume();
Rafael J. Wysocki786f41f2017-07-21 02:09:22 +0200765}
766
767/**
768 * dpm_resume_noirq - Execute "noirq resume" callbacks for all devices.
769 * @state: PM transition of the system being carried out.
770 *
771 * Invoke the "noirq" resume callbacks for all devices in dpm_noirq_list and
772 * allow device drivers' interrupt handlers to be called.
773 */
774void dpm_resume_noirq(pm_message_t state)
775{
776 dpm_noirq_resume_devices(state);
777 dpm_noirq_end();
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100778}
779
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +0100780static pm_callback_t dpm_subsys_resume_early_cb(struct device *dev,
781 pm_message_t state,
782 const char **info_p)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100783{
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +0100784 pm_callback_t callback;
785 const char *info;
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800786
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100787 if (dev->pm_domain) {
788 info = "early power domain ";
789 callback = pm_late_early_op(&dev->pm_domain->ops, state);
790 } else if (dev->type && dev->type->pm) {
791 info = "early type ";
792 callback = pm_late_early_op(dev->type->pm, state);
793 } else if (dev->class && dev->class->pm) {
794 info = "early class ";
795 callback = pm_late_early_op(dev->class->pm, state);
796 } else if (dev->bus && dev->bus->pm) {
797 info = "early bus ";
798 callback = pm_late_early_op(dev->bus->pm, state);
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +0100799 } else {
800 return NULL;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100801 }
802
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +0100803 if (info_p)
804 *info_p = info;
805
806 return callback;
807}
808
809/**
810 * device_resume_early - Execute an "early resume" callback for given device.
811 * @dev: Device to handle.
812 * @state: PM transition of the system being carried out.
813 * @async: If true, the device is being resumed asynchronously.
814 *
815 * Runtime PM is disabled for @dev while this function is being executed.
816 */
817static int device_resume_early(struct device *dev, pm_message_t state, bool async)
818{
819 pm_callback_t callback;
820 const char *info;
821 int error = 0;
822
823 TRACE_DEVICE(dev);
824 TRACE_RESUME(0);
825
826 if (dev->power.syscore || dev->power.direct_complete)
827 goto Out;
828
829 if (!dev->power.is_late_suspended)
830 goto Out;
831
832 dpm_wait_for_superior(dev, async);
833
834 callback = dpm_subsys_resume_early_cb(dev, state, &info);
835
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100836 if (!callback && dev->driver && dev->driver->pm) {
837 info = "early driver ";
838 callback = pm_late_early_op(dev->driver->pm, state);
839 }
840
841 error = dpm_run_callback(callback, dev, state, info);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800842 dev->power.is_late_suspended = false;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100843
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200844 Out:
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100845 TRACE_RESUME(error);
Rafael J. Wysocki9f6d8f62012-12-22 23:59:01 +0100846
847 pm_runtime_enable(dev);
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800848 complete_all(&dev->power.completion);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100849 return error;
850}
851
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800852static void async_resume_early(void *data, async_cookie_t cookie)
853{
854 struct device *dev = (struct device *)data;
855 int error;
856
857 error = device_resume_early(dev, pm_transition, true);
858 if (error)
859 pm_dev_err(dev, pm_transition, " async", error);
860
861 put_device(dev);
862}
863
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100864/**
865 * dpm_resume_early - Execute "early resume" callbacks for all devices.
866 * @state: PM transition of the system being carried out.
867 */
Rafael J. Wysocki2a8a8ce2014-09-30 02:21:34 +0200868void dpm_resume_early(pm_message_t state)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100869{
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800870 struct device *dev;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100871 ktime_t starttime = ktime_get();
872
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700873 trace_suspend_resume(TPS("dpm_resume_early"), state.event, true);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100874 mutex_lock(&dpm_list_mtx);
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800875 pm_transition = state;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100876
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800877 /*
878 * Advanced the async threads upfront,
879 * in case the starting of async threads is
880 * delayed by non-async resuming devices.
881 */
882 list_for_each_entry(dev, &dpm_late_early_list, power.entry) {
883 reinit_completion(&dev->power.completion);
884 if (is_async(dev)) {
885 get_device(dev);
886 async_schedule(async_resume_early, dev);
887 }
888 }
889
890 while (!list_empty(&dpm_late_early_list)) {
891 dev = to_device(dpm_late_early_list.next);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100892 get_device(dev);
893 list_move_tail(&dev->power.entry, &dpm_suspended_list);
894 mutex_unlock(&dpm_list_mtx);
895
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800896 if (!is_async(dev)) {
897 int error;
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100898
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800899 error = device_resume_early(dev, state, false);
900 if (error) {
901 suspend_stats.failed_resume_early++;
902 dpm_save_failed_step(SUSPEND_RESUME_EARLY);
903 dpm_save_failed_dev(dev_name(dev));
904 pm_dev_err(dev, state, " early", error);
905 }
906 }
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100907 mutex_lock(&dpm_list_mtx);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100908 put_device(dev);
909 }
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200910 mutex_unlock(&dpm_list_mtx);
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800911 async_synchronize_full();
Rafael J. Wysocki48059c092017-07-21 02:10:22 +0200912 dpm_show_time(starttime, state, 0, "early");
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700913 trace_suspend_resume(TPS("dpm_resume_early"), state.event, false);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100914}
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100915
916/**
917 * dpm_resume_start - Execute "noirq" and "early" device callbacks.
918 * @state: PM transition of the system being carried out.
919 */
920void dpm_resume_start(pm_message_t state)
921{
922 dpm_resume_noirq(state);
923 dpm_resume_early(state);
924}
925EXPORT_SYMBOL_GPL(dpm_resume_start);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100926
927/**
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100928 * device_resume - Execute "resume" callbacks for given device.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200929 * @dev: Device to handle.
930 * @state: PM transition of the system being carried out.
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100931 * @async: If true, the device is being resumed asynchronously.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100932 */
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100933static int device_resume(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100934{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100935 pm_callback_t callback = NULL;
Krzysztof Kozlowskie3771fa2017-06-12 17:19:32 +0200936 const char *info = NULL;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100937 int error = 0;
Benoit Goby70fea602013-10-17 10:48:46 -0700938 DECLARE_DPM_WATCHDOG_ON_STACK(wd);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100939
940 TRACE_DEVICE(dev);
941 TRACE_RESUME(0);
Alan Sterncd59abf2007-09-21 15:36:56 -0400942
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200943 if (dev->power.syscore)
944 goto Complete;
945
Rafael J. Wysockiaae45182014-05-16 02:46:50 +0200946 if (dev->power.direct_complete) {
947 /* Match the pm_runtime_disable() in __device_suspend(). */
948 pm_runtime_enable(dev);
949 goto Complete;
950 }
951
Rafael J. Wysocki8c73b422016-10-30 17:28:49 +0100952 dpm_wait_for_superior(dev, async);
Benoit Goby70fea602013-10-17 10:48:46 -0700953 dpm_watchdog_set(&wd, dev);
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800954 device_lock(dev);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100955
Alan Sternf76b168b2011-06-18 20:22:23 +0200956 /*
957 * This is a fib. But we'll allow new children to be added below
958 * a resumed device, even if the device hasn't been completed yet.
959 */
960 dev->power.is_prepared = false;
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100961
Alan Stern6d0e0e82011-06-18 22:42:09 +0200962 if (!dev->power.is_suspended)
963 goto Unlock;
964
Rafael J. Wysocki564b9052011-06-23 01:52:55 +0200965 if (dev->pm_domain) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100966 info = "power domain ";
967 callback = pm_op(&dev->pm_domain->ops, state);
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100968 goto Driver;
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +0100969 }
970
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100971 if (dev->type && dev->type->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100972 info = "type ";
973 callback = pm_op(dev->type->pm, state);
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100974 goto Driver;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100975 }
976
Rafael J. Wysockia380f2e2017-09-25 14:56:44 +0200977 if (dev->class && dev->class->pm) {
978 info = "class ";
979 callback = pm_op(dev->class->pm, state);
980 goto Driver;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100981 }
982
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200983 if (dev->bus) {
984 if (dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100985 info = "bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100986 callback = pm_op(dev->bus->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200987 } else if (dev->bus->resume) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100988 info = "legacy bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100989 callback = dev->bus->resume;
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100990 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200991 }
Alan Sterncd59abf2007-09-21 15:36:56 -0400992 }
993
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100994 Driver:
995 if (!callback && dev->driver && dev->driver->pm) {
996 info = "driver ";
997 callback = pm_op(dev->driver->pm, state);
998 }
999
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001000 End:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001001 error = dpm_run_callback(callback, dev, state, info);
Alan Stern6d0e0e82011-06-18 22:42:09 +02001002 dev->power.is_suspended = false;
1003
1004 Unlock:
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001005 device_unlock(dev);
Benoit Goby70fea602013-10-17 10:48:46 -07001006 dpm_watchdog_clear(&wd);
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001007
1008 Complete:
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001009 complete_all(&dev->power.completion);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +01001010
Alan Sterncd59abf2007-09-21 15:36:56 -04001011 TRACE_RESUME(error);
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001012
Alan Sterncd59abf2007-09-21 15:36:56 -04001013 return error;
1014}
1015
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001016static void async_resume(void *data, async_cookie_t cookie)
1017{
1018 struct device *dev = (struct device *)data;
1019 int error;
1020
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +01001021 error = device_resume(dev, pm_transition, true);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001022 if (error)
1023 pm_dev_err(dev, pm_transition, " async", error);
1024 put_device(dev);
1025}
1026
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001027/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001028 * dpm_resume - Execute "resume" callbacks for non-sysdev devices.
1029 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001030 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001031 * Execute the appropriate "resume" callback for all devices whose status
1032 * indicates that they are suspended.
Alan Sterncd59abf2007-09-21 15:36:56 -04001033 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001034void dpm_resume(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001035{
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +01001036 struct device *dev;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001037 ktime_t starttime = ktime_get();
Alan Sterncd59abf2007-09-21 15:36:56 -04001038
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001039 trace_suspend_resume(TPS("dpm_resume"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001040 might_sleep();
1041
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001042 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001043 pm_transition = state;
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001044 async_error = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001045
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001046 list_for_each_entry(dev, &dpm_suspended_list, power.entry) {
Wolfram Sang16735d02013-11-14 14:32:02 -08001047 reinit_completion(&dev->power.completion);
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +01001048 if (is_async(dev)) {
1049 get_device(dev);
1050 async_schedule(async_resume, dev);
1051 }
1052 }
1053
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001054 while (!list_empty(&dpm_suspended_list)) {
1055 dev = to_device(dpm_suspended_list.next);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001056 get_device(dev);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +01001057 if (!is_async(dev)) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001058 int error;
1059
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001060 mutex_unlock(&dpm_list_mtx);
1061
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +01001062 error = device_resume(dev, state, false);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001063 if (error) {
1064 suspend_stats.failed_resume++;
1065 dpm_save_failed_step(SUSPEND_RESUME);
1066 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001067 pm_dev_err(dev, state, "", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001068 }
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +01001069
1070 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001071 }
1072 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001073 list_move_tail(&dev->power.entry, &dpm_prepared_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001074 put_device(dev);
Alan Sterncd59abf2007-09-21 15:36:56 -04001075 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001076 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001077 async_synchronize_full();
Rafael J. Wysocki48059c092017-07-21 02:10:22 +02001078 dpm_show_time(starttime, state, 0, NULL);
Viresh Kumar2f0aea92014-03-04 11:00:26 +08001079
1080 cpufreq_resume();
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001081 trace_suspend_resume(TPS("dpm_resume"), state.event, false);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001082}
1083
1084/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001085 * device_complete - Complete a PM transition for given device.
1086 * @dev: Device to handle.
1087 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001088 */
Alan Sternd1616302009-05-24 22:05:42 +02001089static void device_complete(struct device *dev, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001090{
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001091 void (*callback)(struct device *) = NULL;
Krzysztof Kozlowskie3771fa2017-06-12 17:19:32 +02001092 const char *info = NULL;
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001093
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001094 if (dev->power.syscore)
1095 return;
1096
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001097 device_lock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001098
Rafael J. Wysocki564b9052011-06-23 01:52:55 +02001099 if (dev->pm_domain) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001100 info = "completing power domain ";
1101 callback = dev->pm_domain->ops.complete;
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001102 } else if (dev->type && dev->type->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001103 info = "completing type ";
1104 callback = dev->type->pm->complete;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001105 } else if (dev->class && dev->class->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001106 info = "completing class ";
1107 callback = dev->class->pm->complete;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001108 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001109 info = "completing bus ";
1110 callback = dev->bus->pm->complete;
1111 }
1112
1113 if (!callback && dev->driver && dev->driver->pm) {
1114 info = "completing driver ";
1115 callback = dev->driver->pm->complete;
1116 }
1117
1118 if (callback) {
1119 pm_dev_dbg(dev, state, info);
1120 callback(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001121 }
1122
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001123 device_unlock(dev);
Alan Stern88d26132012-09-19 21:59:02 +02001124
Ulf Hanssonaf939332013-04-12 09:41:06 +00001125 pm_runtime_put(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001126}
1127
1128/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001129 * dpm_complete - Complete a PM transition for all non-sysdev devices.
1130 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001131 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001132 * Execute the ->complete() callbacks for all devices whose PM status is not
1133 * DPM_ON (this allows new devices to be registered).
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001134 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001135void dpm_complete(pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001136{
1137 struct list_head list;
1138
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001139 trace_suspend_resume(TPS("dpm_complete"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001140 might_sleep();
1141
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001142 INIT_LIST_HEAD(&list);
1143 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001144 while (!list_empty(&dpm_prepared_list)) {
1145 struct device *dev = to_device(dpm_prepared_list.prev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001146
1147 get_device(dev);
Alan Sternf76b168b2011-06-18 20:22:23 +02001148 dev->power.is_prepared = false;
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +01001149 list_move(&dev->power.entry, &list);
1150 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001151
Todd E Brandt32e8d682015-05-28 12:55:53 -07001152 trace_device_pm_callback_start(dev, "", state.event);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +01001153 device_complete(dev, state);
Todd E Brandt32e8d682015-05-28 12:55:53 -07001154 trace_device_pm_callback_end(dev, 0);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001155
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +01001156 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001157 put_device(dev);
1158 }
1159 list_splice(&list, &dpm_list);
Alan Sterncd59abf2007-09-21 15:36:56 -04001160 mutex_unlock(&dpm_list_mtx);
Strashko, Grygorii013c0742015-11-10 11:42:34 +02001161
1162 /* Allow device probing and trigger re-probing of deferred devices */
1163 device_unblock_probing();
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001164 trace_suspend_resume(TPS("dpm_complete"), state.event, false);
Alan Sterncd59abf2007-09-21 15:36:56 -04001165}
1166
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001167/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001168 * dpm_resume_end - Execute "resume" callbacks and complete system transition.
1169 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -04001170 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001171 * Execute "resume" callbacks for all devices and complete the PM transition of
1172 * the system.
Alan Sterncd59abf2007-09-21 15:36:56 -04001173 */
Alan Sternd1616302009-05-24 22:05:42 +02001174void dpm_resume_end(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001175{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001176 dpm_resume(state);
1177 dpm_complete(state);
Alan Sterncd59abf2007-09-21 15:36:56 -04001178}
Alan Sternd1616302009-05-24 22:05:42 +02001179EXPORT_SYMBOL_GPL(dpm_resume_end);
Alan Sterncd59abf2007-09-21 15:36:56 -04001180
1181
Alan Sterncd59abf2007-09-21 15:36:56 -04001182/*------------------------- Suspend routines -------------------------*/
1183
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001184/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001185 * resume_event - Return a "resume" message for given "suspend" sleep state.
1186 * @sleep_state: PM message representing a sleep state.
1187 *
1188 * Return a PM message representing the resume event corresponding to given
1189 * sleep state.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001190 */
1191static pm_message_t resume_event(pm_message_t sleep_state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001192{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001193 switch (sleep_state.event) {
1194 case PM_EVENT_SUSPEND:
1195 return PMSG_RESUME;
1196 case PM_EVENT_FREEZE:
1197 case PM_EVENT_QUIESCE:
1198 return PMSG_RECOVER;
1199 case PM_EVENT_HIBERNATE:
1200 return PMSG_RESTORE;
Alan Sterncd59abf2007-09-21 15:36:56 -04001201 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001202 return PMSG_ON;
Alan Sterncd59abf2007-09-21 15:36:56 -04001203}
1204
Rafael J. Wysocki0d4b54c2017-11-18 15:31:49 +01001205static void dpm_superior_set_must_resume(struct device *dev)
1206{
1207 struct device_link *link;
1208 int idx;
1209
1210 if (dev->parent)
1211 dev->parent->power.must_resume = true;
1212
1213 idx = device_links_read_lock();
1214
1215 list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
1216 link->supplier->power.must_resume = true;
1217
1218 device_links_read_unlock(idx);
1219}
1220
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +01001221static pm_callback_t dpm_subsys_suspend_noirq_cb(struct device *dev,
1222 pm_message_t state,
1223 const char **info_p)
1224{
1225 pm_callback_t callback;
1226 const char *info;
1227
1228 if (dev->pm_domain) {
1229 info = "noirq power domain ";
1230 callback = pm_noirq_op(&dev->pm_domain->ops, state);
1231 } else if (dev->type && dev->type->pm) {
1232 info = "noirq type ";
1233 callback = pm_noirq_op(dev->type->pm, state);
1234 } else if (dev->class && dev->class->pm) {
1235 info = "noirq class ";
1236 callback = pm_noirq_op(dev->class->pm, state);
1237 } else if (dev->bus && dev->bus->pm) {
1238 info = "noirq bus ";
1239 callback = pm_noirq_op(dev->bus->pm, state);
1240 } else {
1241 return NULL;
1242 }
1243
1244 if (info_p)
1245 *info_p = info;
1246
1247 return callback;
1248}
1249
Rafael J. Wysocki32bfa562017-12-10 01:02:13 +01001250static bool device_must_resume(struct device *dev, pm_message_t state,
1251 bool no_subsys_suspend_noirq)
1252{
1253 pm_message_t resume_msg = resume_event(state);
1254
1255 /*
1256 * If all of the device driver's "noirq", "late" and "early" callbacks
1257 * are invoked directly by the core, the decision to allow the device to
1258 * stay in suspend can be based on its current runtime PM status and its
1259 * wakeup settings.
1260 */
1261 if (no_subsys_suspend_noirq &&
1262 !dpm_subsys_suspend_late_cb(dev, state, NULL) &&
1263 !dpm_subsys_resume_early_cb(dev, resume_msg, NULL) &&
1264 !dpm_subsys_resume_noirq_cb(dev, resume_msg, NULL))
1265 return !pm_runtime_status_suspended(dev) &&
1266 (resume_msg.event != PM_EVENT_RESUME ||
1267 (device_can_wakeup(dev) && !device_may_wakeup(dev)));
1268
1269 /*
1270 * The only safe strategy here is to require that if the device may not
1271 * be left in suspend, resume callbacks must be invoked for it.
1272 */
1273 return !dev->power.may_skip_resume;
1274}
1275
Alan Sterncd59abf2007-09-21 15:36:56 -04001276/**
Rafael J. Wysockib082ddd2017-10-13 15:25:39 +02001277 * __device_suspend_noirq - Execute a "noirq suspend" callback for given device.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001278 * @dev: Device to handle.
1279 * @state: PM transition of the system being carried out.
Randy Dunlap58c256a2014-07-27 16:17:15 -07001280 * @async: If true, the device is being suspended asynchronously.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001281 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001282 * The driver of @dev will not receive interrupts while this function is being
1283 * executed.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001284 */
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001285static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001286{
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +01001287 pm_callback_t callback;
1288 const char *info;
Rafael J. Wysocki32bfa562017-12-10 01:02:13 +01001289 bool no_subsys_cb = false;
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001290 int error = 0;
1291
Zhonghui Fu431d4522015-03-18 15:54:27 +01001292 TRACE_DEVICE(dev);
1293 TRACE_SUSPEND(0);
1294
Linus Torvalds098c3052016-12-13 11:42:18 -08001295 dpm_wait_for_subordinate(dev, async);
Brian Norris6f75c3f2016-11-09 17:21:08 -08001296
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001297 if (async_error)
1298 goto Complete;
1299
Rafael J. Wysocki9a3ebe32017-07-21 02:12:10 +02001300 if (pm_wakeup_pending()) {
1301 async_error = -EBUSY;
1302 goto Complete;
1303 }
1304
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001305 if (dev->power.syscore || dev->power.direct_complete)
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001306 goto Complete;
1307
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +01001308 callback = dpm_subsys_suspend_noirq_cb(dev, state, &info);
Rafael J. Wysocki75e94642017-12-10 01:00:45 +01001309 if (callback)
1310 goto Run;
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001311
Rafael J. Wysocki32bfa562017-12-10 01:02:13 +01001312 no_subsys_cb = !dpm_subsys_suspend_late_cb(dev, state, NULL);
1313
1314 if (dev_pm_smart_suspend_and_suspended(dev) && no_subsys_cb)
Rafael J. Wysocki75e94642017-12-10 01:00:45 +01001315 goto Skip;
1316
1317 if (dev->driver && dev->driver->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001318 info = "noirq driver ";
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001319 callback = pm_noirq_op(dev->driver->pm, state);
1320 }
1321
Rafael J. Wysocki75e94642017-12-10 01:00:45 +01001322Run:
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001323 error = dpm_run_callback(callback, dev, state, info);
Rafael J. Wysocki0d4b54c2017-11-18 15:31:49 +01001324 if (error) {
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001325 async_error = error;
Rafael J. Wysocki0d4b54c2017-11-18 15:31:49 +01001326 goto Complete;
1327 }
1328
Rafael J. Wysocki75e94642017-12-10 01:00:45 +01001329Skip:
Rafael J. Wysocki0d4b54c2017-11-18 15:31:49 +01001330 dev->power.is_noirq_suspended = true;
1331
1332 if (dev_pm_test_driver_flags(dev, DPM_FLAG_LEAVE_SUSPENDED)) {
Rafael J. Wysocki0d4b54c2017-11-18 15:31:49 +01001333 dev->power.must_resume = dev->power.must_resume ||
Rafael J. Wysocki32bfa562017-12-10 01:02:13 +01001334 atomic_read(&dev->power.usage_count) > 1 ||
1335 device_must_resume(dev, state, no_subsys_cb);
Rafael J. Wysocki0d4b54c2017-11-18 15:31:49 +01001336 } else {
1337 dev->power.must_resume = true;
1338 }
1339
1340 if (dev->power.must_resume)
1341 dpm_superior_set_must_resume(dev);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001342
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001343Complete:
1344 complete_all(&dev->power.completion);
Zhonghui Fu431d4522015-03-18 15:54:27 +01001345 TRACE_SUSPEND(error);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001346 return error;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001347}
1348
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001349static void async_suspend_noirq(void *data, async_cookie_t cookie)
1350{
1351 struct device *dev = (struct device *)data;
1352 int error;
1353
1354 error = __device_suspend_noirq(dev, pm_transition, true);
1355 if (error) {
1356 dpm_save_failed_dev(dev_name(dev));
1357 pm_dev_err(dev, pm_transition, " async", error);
1358 }
1359
1360 put_device(dev);
1361}
1362
1363static int device_suspend_noirq(struct device *dev)
1364{
1365 reinit_completion(&dev->power.completion);
1366
Zhonghui Fu431d4522015-03-18 15:54:27 +01001367 if (is_async(dev)) {
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001368 get_device(dev);
1369 async_schedule(async_suspend_noirq, dev);
1370 return 0;
1371 }
1372 return __device_suspend_noirq(dev, pm_transition, false);
1373}
1374
Rafael J. Wysocki786f41f2017-07-21 02:09:22 +02001375void dpm_noirq_begin(void)
1376{
1377 cpuidle_pause();
1378 device_wakeup_arm_wake_irqs();
1379 suspend_device_irqs();
1380}
1381
1382int dpm_noirq_suspend_devices(pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001383{
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001384 ktime_t starttime = ktime_get();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001385 int error = 0;
1386
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001387 trace_suspend_resume(TPS("dpm_suspend_noirq"), state.event, true);
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +02001388 mutex_lock(&dpm_list_mtx);
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001389 pm_transition = state;
1390 async_error = 0;
1391
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001392 while (!list_empty(&dpm_late_early_list)) {
1393 struct device *dev = to_device(dpm_late_early_list.prev);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001394
1395 get_device(dev);
1396 mutex_unlock(&dpm_list_mtx);
1397
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001398 error = device_suspend_noirq(dev);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001399
1400 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001401 if (error) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001402 pm_dev_err(dev, state, " noirq", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001403 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001404 put_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001405 break;
1406 }
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001407 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001408 list_move(&dev->power.entry, &dpm_noirq_list);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001409 put_device(dev);
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001410
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001411 if (async_error)
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001412 break;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001413 }
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +02001414 mutex_unlock(&dpm_list_mtx);
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001415 async_synchronize_full();
1416 if (!error)
1417 error = async_error;
1418
1419 if (error) {
1420 suspend_stats.failed_suspend_noirq++;
1421 dpm_save_failed_step(SUSPEND_SUSPEND_NOIRQ);
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001422 }
Rafael J. Wysocki48059c092017-07-21 02:10:22 +02001423 dpm_show_time(starttime, state, error, "noirq");
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001424 trace_suspend_resume(TPS("dpm_suspend_noirq"), state.event, false);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001425 return error;
1426}
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001427
1428/**
Rafael J. Wysocki786f41f2017-07-21 02:09:22 +02001429 * dpm_suspend_noirq - Execute "noirq suspend" callbacks for all devices.
1430 * @state: PM transition of the system being carried out.
1431 *
1432 * Prevent device drivers' interrupt handlers from being called and invoke
1433 * "noirq" suspend callbacks for all non-sysdev devices.
1434 */
1435int dpm_suspend_noirq(pm_message_t state)
1436{
1437 int ret;
1438
1439 dpm_noirq_begin();
1440 ret = dpm_noirq_suspend_devices(state);
1441 if (ret)
1442 dpm_resume_noirq(resume_event(state));
1443
1444 return ret;
1445}
1446
Ulf Hansson0a99d762018-01-09 10:03:40 +01001447static void dpm_propagate_wakeup_to_parent(struct device *dev)
1448{
1449 struct device *parent = dev->parent;
1450
1451 if (!parent)
1452 return;
1453
1454 spin_lock_irq(&parent->power.lock);
1455
1456 if (dev->power.wakeup_path && !parent->power.ignore_children)
1457 parent->power.wakeup_path = true;
1458
1459 spin_unlock_irq(&parent->power.lock);
1460}
1461
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +01001462static pm_callback_t dpm_subsys_suspend_late_cb(struct device *dev,
1463 pm_message_t state,
1464 const char **info_p)
1465{
1466 pm_callback_t callback;
1467 const char *info;
1468
1469 if (dev->pm_domain) {
1470 info = "late power domain ";
1471 callback = pm_late_early_op(&dev->pm_domain->ops, state);
1472 } else if (dev->type && dev->type->pm) {
1473 info = "late type ";
1474 callback = pm_late_early_op(dev->type->pm, state);
1475 } else if (dev->class && dev->class->pm) {
1476 info = "late class ";
1477 callback = pm_late_early_op(dev->class->pm, state);
1478 } else if (dev->bus && dev->bus->pm) {
1479 info = "late bus ";
1480 callback = pm_late_early_op(dev->bus->pm, state);
1481 } else {
1482 return NULL;
1483 }
1484
1485 if (info_p)
1486 *info_p = info;
1487
1488 return callback;
1489}
1490
Rafael J. Wysocki786f41f2017-07-21 02:09:22 +02001491/**
Rafael J. Wysockib082ddd2017-10-13 15:25:39 +02001492 * __device_suspend_late - Execute a "late suspend" callback for given device.
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001493 * @dev: Device to handle.
1494 * @state: PM transition of the system being carried out.
Randy Dunlap58c256a2014-07-27 16:17:15 -07001495 * @async: If true, the device is being suspended asynchronously.
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001496 *
1497 * Runtime PM is disabled for @dev while this function is being executed.
1498 */
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001499static int __device_suspend_late(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001500{
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +01001501 pm_callback_t callback;
1502 const char *info;
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001503 int error = 0;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001504
Zhonghui Fu431d4522015-03-18 15:54:27 +01001505 TRACE_DEVICE(dev);
1506 TRACE_SUSPEND(0);
1507
Rafael J. Wysocki9f6d8f62012-12-22 23:59:01 +01001508 __pm_runtime_disable(dev, false);
1509
Linus Torvalds098c3052016-12-13 11:42:18 -08001510 dpm_wait_for_subordinate(dev, async);
Brian Norris6f75c3f2016-11-09 17:21:08 -08001511
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001512 if (async_error)
1513 goto Complete;
1514
1515 if (pm_wakeup_pending()) {
1516 async_error = -EBUSY;
1517 goto Complete;
1518 }
1519
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001520 if (dev->power.syscore || dev->power.direct_complete)
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001521 goto Complete;
1522
Rafael J. Wysocki4fa30612017-12-10 00:58:18 +01001523 callback = dpm_subsys_suspend_late_cb(dev, state, &info);
Rafael J. Wysocki75e94642017-12-10 01:00:45 +01001524 if (callback)
1525 goto Run;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001526
Rafael J. Wysocki75e94642017-12-10 01:00:45 +01001527 if (dev_pm_smart_suspend_and_suspended(dev) &&
1528 !dpm_subsys_suspend_noirq_cb(dev, state, NULL))
1529 goto Skip;
1530
1531 if (dev->driver && dev->driver->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001532 info = "late driver ";
1533 callback = pm_late_early_op(dev->driver->pm, state);
1534 }
1535
Rafael J. Wysocki75e94642017-12-10 01:00:45 +01001536Run:
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001537 error = dpm_run_callback(callback, dev, state, info);
Rafael J. Wysocki75e94642017-12-10 01:00:45 +01001538 if (error) {
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001539 async_error = error;
Rafael J. Wysocki75e94642017-12-10 01:00:45 +01001540 goto Complete;
1541 }
Ulf Hansson0a99d762018-01-09 10:03:40 +01001542 dpm_propagate_wakeup_to_parent(dev);
Rafael J. Wysocki75e94642017-12-10 01:00:45 +01001543
1544Skip:
1545 dev->power.is_late_suspended = true;
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001546
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001547Complete:
Zhonghui Fu431d4522015-03-18 15:54:27 +01001548 TRACE_SUSPEND(error);
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001549 complete_all(&dev->power.completion);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001550 return error;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001551}
1552
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001553static void async_suspend_late(void *data, async_cookie_t cookie)
1554{
1555 struct device *dev = (struct device *)data;
1556 int error;
1557
1558 error = __device_suspend_late(dev, pm_transition, true);
1559 if (error) {
1560 dpm_save_failed_dev(dev_name(dev));
1561 pm_dev_err(dev, pm_transition, " async", error);
1562 }
1563 put_device(dev);
1564}
1565
1566static int device_suspend_late(struct device *dev)
1567{
1568 reinit_completion(&dev->power.completion);
1569
Zhonghui Fu431d4522015-03-18 15:54:27 +01001570 if (is_async(dev)) {
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001571 get_device(dev);
1572 async_schedule(async_suspend_late, dev);
1573 return 0;
1574 }
1575
1576 return __device_suspend_late(dev, pm_transition, false);
1577}
1578
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001579/**
1580 * dpm_suspend_late - Execute "late suspend" callbacks for all devices.
1581 * @state: PM transition of the system being carried out.
1582 */
Rafael J. Wysocki2a8a8ce2014-09-30 02:21:34 +02001583int dpm_suspend_late(pm_message_t state)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001584{
1585 ktime_t starttime = ktime_get();
1586 int error = 0;
1587
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001588 trace_suspend_resume(TPS("dpm_suspend_late"), state.event, true);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001589 mutex_lock(&dpm_list_mtx);
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001590 pm_transition = state;
1591 async_error = 0;
1592
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001593 while (!list_empty(&dpm_suspended_list)) {
1594 struct device *dev = to_device(dpm_suspended_list.prev);
1595
1596 get_device(dev);
1597 mutex_unlock(&dpm_list_mtx);
1598
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001599 error = device_suspend_late(dev);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001600
1601 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki3a17fb32016-05-20 23:09:49 +02001602 if (!list_empty(&dev->power.entry))
1603 list_move(&dev->power.entry, &dpm_late_early_list);
1604
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001605 if (error) {
1606 pm_dev_err(dev, state, " late", error);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001607 dpm_save_failed_dev(dev_name(dev));
1608 put_device(dev);
1609 break;
1610 }
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001611 put_device(dev);
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001612
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001613 if (async_error)
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001614 break;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001615 }
1616 mutex_unlock(&dpm_list_mtx);
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001617 async_synchronize_full();
Imre Deak246ef762014-10-24 20:29:09 +03001618 if (!error)
1619 error = async_error;
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001620 if (error) {
1621 suspend_stats.failed_suspend_late++;
1622 dpm_save_failed_step(SUSPEND_SUSPEND_LATE);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001623 dpm_resume_early(resume_event(state));
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001624 }
Rafael J. Wysocki48059c092017-07-21 02:10:22 +02001625 dpm_show_time(starttime, state, error, "late");
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001626 trace_suspend_resume(TPS("dpm_suspend_late"), state.event, false);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001627 return error;
1628}
1629
1630/**
1631 * dpm_suspend_end - Execute "late" and "noirq" device suspend callbacks.
1632 * @state: PM transition of the system being carried out.
1633 */
1634int dpm_suspend_end(pm_message_t state)
1635{
1636 int error = dpm_suspend_late(state);
Colin Cross064b0212012-07-19 10:38:06 +02001637 if (error)
1638 return error;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001639
Colin Cross064b0212012-07-19 10:38:06 +02001640 error = dpm_suspend_noirq(state);
1641 if (error) {
Feng Hong997a0312012-09-19 14:16:00 +02001642 dpm_resume_early(resume_event(state));
Colin Cross064b0212012-07-19 10:38:06 +02001643 return error;
1644 }
1645
1646 return 0;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001647}
1648EXPORT_SYMBOL_GPL(dpm_suspend_end);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001649
1650/**
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001651 * legacy_suspend - Execute a legacy (bus or class) suspend callback for device.
Randy Dunlap0a884222010-01-08 14:42:57 -08001652 * @dev: Device to suspend.
1653 * @state: PM transition of the system being carried out.
1654 * @cb: Suspend callback to execute.
Randy Dunlap58c256a2014-07-27 16:17:15 -07001655 * @info: string description of caller.
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001656 */
1657static int legacy_suspend(struct device *dev, pm_message_t state,
Shuah Khan53644672013-07-26 13:30:20 -06001658 int (*cb)(struct device *dev, pm_message_t state),
Krzysztof Kozlowskie3771fa2017-06-12 17:19:32 +02001659 const char *info)
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001660{
1661 int error;
1662 ktime_t calltime;
1663
Bjorn Helgaas7f817ba2018-04-26 16:36:41 -05001664 calltime = initcall_debug_start(dev, cb);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001665
Todd E Brandte8bca472014-06-10 07:31:22 -07001666 trace_device_pm_callback_start(dev, info, state.event);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001667 error = cb(dev, state);
Todd E Brandte8bca472014-06-10 07:31:22 -07001668 trace_device_pm_callback_end(dev, error);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001669 suspend_report_result(cb, error);
1670
Bjorn Helgaas7f817ba2018-04-26 16:36:41 -05001671 initcall_debug_report(dev, calltime, cb, error);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001672
1673 return error;
1674}
1675
Ulf Hanssonc23bd382018-01-09 10:03:39 +01001676static void dpm_clear_superiors_direct_complete(struct device *dev)
Rafael J. Wysocki8c73b422016-10-30 17:28:49 +01001677{
1678 struct device_link *link;
1679 int idx;
1680
Ulf Hanssonc23bd382018-01-09 10:03:39 +01001681 if (dev->parent) {
1682 spin_lock_irq(&dev->parent->power.lock);
1683 dev->parent->power.direct_complete = false;
1684 spin_unlock_irq(&dev->parent->power.lock);
1685 }
1686
Rafael J. Wysocki8c73b422016-10-30 17:28:49 +01001687 idx = device_links_read_lock();
1688
1689 list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) {
1690 spin_lock_irq(&link->supplier->power.lock);
1691 link->supplier->power.direct_complete = false;
1692 spin_unlock_irq(&link->supplier->power.lock);
1693 }
1694
1695 device_links_read_unlock(idx);
1696}
1697
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001698/**
Rafael J. Wysockib082ddd2017-10-13 15:25:39 +02001699 * __device_suspend - Execute "suspend" callbacks for given device.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001700 * @dev: Device to handle.
1701 * @state: PM transition of the system being carried out.
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001702 * @async: If true, the device is being suspended asynchronously.
Alan Sterncd59abf2007-09-21 15:36:56 -04001703 */
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001704static int __device_suspend(struct device *dev, pm_message_t state, bool async)
Alan Sterncd59abf2007-09-21 15:36:56 -04001705{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001706 pm_callback_t callback = NULL;
Krzysztof Kozlowskie3771fa2017-06-12 17:19:32 +02001707 const char *info = NULL;
Alan Sterncd59abf2007-09-21 15:36:56 -04001708 int error = 0;
Benoit Goby70fea602013-10-17 10:48:46 -07001709 DECLARE_DPM_WATCHDOG_ON_STACK(wd);
Alan Sterncd59abf2007-09-21 15:36:56 -04001710
Zhonghui Fu431d4522015-03-18 15:54:27 +01001711 TRACE_DEVICE(dev);
1712 TRACE_SUSPEND(0);
1713
Rafael J. Wysocki8c73b422016-10-30 17:28:49 +01001714 dpm_wait_for_subordinate(dev, async);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +01001715
Rafael J. Wysocki69e445a2018-10-04 11:08:12 +02001716 if (async_error) {
1717 dev->power.direct_complete = false;
Mandeep Singh Baines1f758b22012-06-24 23:31:09 +02001718 goto Complete;
Rafael J. Wysocki69e445a2018-10-04 11:08:12 +02001719 }
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001720
Alan Stern88d26132012-09-19 21:59:02 +02001721 /*
1722 * If a device configured to wake up the system from sleep states
1723 * has been suspended at run time and there's a resume request pending
1724 * for it, this is equivalent to the device signaling wakeup, so the
1725 * system suspend operation should be aborted.
1726 */
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001727 if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
1728 pm_wakeup_event(dev, 0);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001729
Rafael J. Wysockid83f9052010-12-03 23:14:26 +01001730 if (pm_wakeup_pending()) {
Rafael J. Wysocki69e445a2018-10-04 11:08:12 +02001731 dev->power.direct_complete = false;
Rafael J. Wysockid83f9052010-12-03 23:14:26 +01001732 async_error = -EBUSY;
Mandeep Singh Baines1f758b22012-06-24 23:31:09 +02001733 goto Complete;
Rafael J. Wysockid83f9052010-12-03 23:14:26 +01001734 }
1735
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001736 if (dev->power.syscore)
1737 goto Complete;
1738
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001739 if (dev->power.direct_complete) {
1740 if (pm_runtime_status_suspended(dev)) {
1741 pm_runtime_disable(dev);
Alan Stern019d8812015-07-15 14:40:06 +02001742 if (pm_runtime_status_suspended(dev))
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001743 goto Complete;
1744
1745 pm_runtime_enable(dev);
1746 }
1747 dev->power.direct_complete = false;
1748 }
1749
Rafael J. Wysocki0d4b54c2017-11-18 15:31:49 +01001750 dev->power.may_skip_resume = false;
1751 dev->power.must_resume = false;
1752
Benoit Goby70fea602013-10-17 10:48:46 -07001753 dpm_watchdog_set(&wd, dev);
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001754 device_lock(dev);
1755
Rafael J. Wysocki564b9052011-06-23 01:52:55 +02001756 if (dev->pm_domain) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001757 info = "power domain ";
1758 callback = pm_op(&dev->pm_domain->ops, state);
1759 goto Run;
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001760 }
1761
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001762 if (dev->type && dev->type->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001763 info = "type ";
1764 callback = pm_op(dev->type->pm, state);
1765 goto Run;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001766 }
1767
Rafael J. Wysockia380f2e2017-09-25 14:56:44 +02001768 if (dev->class && dev->class->pm) {
1769 info = "class ";
1770 callback = pm_op(dev->class->pm, state);
1771 goto Run;
Alan Sterncd59abf2007-09-21 15:36:56 -04001772 }
1773
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001774 if (dev->bus) {
1775 if (dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001776 info = "bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001777 callback = pm_op(dev->bus->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001778 } else if (dev->bus->suspend) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001779 pm_dev_dbg(dev, state, "legacy bus ");
Shuah Khan53644672013-07-26 13:30:20 -06001780 error = legacy_suspend(dev, state, dev->bus->suspend,
1781 "legacy bus ");
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001782 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001783 }
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001784 }
1785
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001786 Run:
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001787 if (!callback && dev->driver && dev->driver->pm) {
1788 info = "driver ";
1789 callback = pm_op(dev->driver->pm, state);
1790 }
1791
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001792 error = dpm_run_callback(callback, dev, state, info);
1793
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001794 End:
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001795 if (!error) {
1796 dev->power.is_suspended = true;
Ulf Hansson8512220c2018-01-02 17:08:50 +01001797 if (device_may_wakeup(dev))
1798 dev->power.wakeup_path = true;
1799
Ulf Hanssonc23bd382018-01-09 10:03:39 +01001800 dpm_propagate_wakeup_to_parent(dev);
1801 dpm_clear_superiors_direct_complete(dev);
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001802 }
Alan Stern6d0e0e82011-06-18 22:42:09 +02001803
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001804 device_unlock(dev);
Benoit Goby70fea602013-10-17 10:48:46 -07001805 dpm_watchdog_clear(&wd);
Mandeep Singh Baines1f758b22012-06-24 23:31:09 +02001806
1807 Complete:
Alan Stern88d26132012-09-19 21:59:02 +02001808 if (error)
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001809 async_error = error;
1810
Sahitya Tummala05a92622016-12-07 20:10:32 +05301811 complete_all(&dev->power.completion);
Zhonghui Fu431d4522015-03-18 15:54:27 +01001812 TRACE_SUSPEND(error);
Alan Sterncd59abf2007-09-21 15:36:56 -04001813 return error;
1814}
1815
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001816static void async_suspend(void *data, async_cookie_t cookie)
1817{
1818 struct device *dev = (struct device *)data;
1819 int error;
1820
1821 error = __device_suspend(dev, pm_transition, true);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001822 if (error) {
1823 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001824 pm_dev_err(dev, pm_transition, " async", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001825 }
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001826
1827 put_device(dev);
1828}
1829
1830static int device_suspend(struct device *dev)
1831{
Wolfram Sang16735d02013-11-14 14:32:02 -08001832 reinit_completion(&dev->power.completion);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001833
Zhonghui Fu431d4522015-03-18 15:54:27 +01001834 if (is_async(dev)) {
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001835 get_device(dev);
1836 async_schedule(async_suspend, dev);
1837 return 0;
1838 }
1839
1840 return __device_suspend(dev, pm_transition, false);
1841}
1842
Alan Sterncd59abf2007-09-21 15:36:56 -04001843/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001844 * dpm_suspend - Execute "suspend" callbacks for all non-sysdev devices.
1845 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -04001846 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001847int dpm_suspend(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001848{
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001849 ktime_t starttime = ktime_get();
Alan Sterncd59abf2007-09-21 15:36:56 -04001850 int error = 0;
1851
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001852 trace_suspend_resume(TPS("dpm_suspend"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001853 might_sleep();
1854
Viresh Kumar2f0aea92014-03-04 11:00:26 +08001855 cpufreq_suspend();
1856
Alan Sterncd59abf2007-09-21 15:36:56 -04001857 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001858 pm_transition = state;
1859 async_error = 0;
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001860 while (!list_empty(&dpm_prepared_list)) {
1861 struct device *dev = to_device(dpm_prepared_list.prev);
Alan Sterncd59abf2007-09-21 15:36:56 -04001862
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001863 get_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001864 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001865
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001866 error = device_suspend(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001867
Alan Stern1b3cbec2008-02-29 11:50:22 -05001868 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001869 if (error) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001870 pm_dev_err(dev, state, "", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001871 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001872 put_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001873 break;
1874 }
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +01001875 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001876 list_move(&dev->power.entry, &dpm_suspended_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001877 put_device(dev);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001878 if (async_error)
1879 break;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001880 }
1881 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001882 async_synchronize_full();
1883 if (!error)
1884 error = async_error;
ShuoX Liu2a77c462011-08-10 23:01:26 +02001885 if (error) {
1886 suspend_stats.failed_suspend++;
1887 dpm_save_failed_step(SUSPEND_SUSPEND);
Rafael J. Wysocki48059c092017-07-21 02:10:22 +02001888 }
1889 dpm_show_time(starttime, state, error, NULL);
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001890 trace_suspend_resume(TPS("dpm_suspend"), state.event, false);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001891 return error;
1892}
1893
1894/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001895 * device_prepare - Prepare a device for system power transition.
1896 * @dev: Device to handle.
1897 * @state: PM transition of the system being carried out.
1898 *
1899 * Execute the ->prepare() callback(s) for given device. No new children of the
1900 * device may be registered after this function has returned.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001901 */
Alan Sternd1616302009-05-24 22:05:42 +02001902static int device_prepare(struct device *dev, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001903{
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001904 int (*callback)(struct device *) = NULL;
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001905 int ret = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001906
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001907 if (dev->power.syscore)
1908 return 0;
1909
Rafael J. Wysocki0d4b54c2017-11-18 15:31:49 +01001910 WARN_ON(!pm_runtime_enabled(dev) &&
1911 dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND |
1912 DPM_FLAG_LEAVE_SUSPENDED));
Rafael J. Wysocki0eab11c92017-10-26 12:12:08 +02001913
Alan Stern88d26132012-09-19 21:59:02 +02001914 /*
1915 * If a device's parent goes into runtime suspend at the wrong time,
1916 * it won't be possible to resume the device. To prevent this we
1917 * block runtime suspend here, during the prepare phase, and allow
1918 * it again during the complete phase.
1919 */
1920 pm_runtime_get_noresume(dev);
1921
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001922 device_lock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001923
Ulf Hansson8512220c2018-01-02 17:08:50 +01001924 dev->power.wakeup_path = false;
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001925
Rafael J. Wysockic62ec462018-05-22 13:02:17 +02001926 if (dev->power.no_pm_callbacks)
Tomeu Vizosoaa8e54b52016-01-07 16:46:14 +01001927 goto unlock;
Tomeu Vizosoaa8e54b52016-01-07 16:46:14 +01001928
Thierry Redingfba1fbf2016-04-28 14:42:34 +02001929 if (dev->pm_domain)
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001930 callback = dev->pm_domain->ops.prepare;
Thierry Redingfba1fbf2016-04-28 14:42:34 +02001931 else if (dev->type && dev->type->pm)
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001932 callback = dev->type->pm->prepare;
Thierry Redingfba1fbf2016-04-28 14:42:34 +02001933 else if (dev->class && dev->class->pm)
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001934 callback = dev->class->pm->prepare;
Thierry Redingfba1fbf2016-04-28 14:42:34 +02001935 else if (dev->bus && dev->bus->pm)
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001936 callback = dev->bus->pm->prepare;
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001937
Thierry Redingfba1fbf2016-04-28 14:42:34 +02001938 if (!callback && dev->driver && dev->driver->pm)
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001939 callback = dev->driver->pm->prepare;
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001940
Todd E Brandt32e8d682015-05-28 12:55:53 -07001941 if (callback)
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001942 ret = callback(dev);
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001943
Tomeu Vizosoaa8e54b52016-01-07 16:46:14 +01001944unlock:
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001945 device_unlock(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001946
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001947 if (ret < 0) {
1948 suspend_report_result(callback, ret);
Ulf Hanssonaa1b9f12013-11-13 15:45:03 +01001949 pm_runtime_put(dev);
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001950 return ret;
1951 }
1952 /*
1953 * A positive return value from ->prepare() means "this device appears
1954 * to be runtime-suspended and its state is fine, so if it really is
1955 * runtime-suspended, you can leave it in that state provided that you
1956 * will do the same thing with all of its descendants". This only
1957 * applies to suspend transitions, however.
1958 */
1959 spin_lock_irq(&dev->power.lock);
Rafael J. Wysocki08810a412017-10-25 14:12:29 +02001960 dev->power.direct_complete = state.event == PM_EVENT_SUSPEND &&
Rafael J. Wysockic62ec462018-05-22 13:02:17 +02001961 ((pm_runtime_suspended(dev) && ret > 0) ||
1962 dev->power.no_pm_callbacks) &&
Rafael J. Wysocki08810a412017-10-25 14:12:29 +02001963 !dev_pm_test_driver_flags(dev, DPM_FLAG_NEVER_SKIP);
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001964 spin_unlock_irq(&dev->power.lock);
1965 return 0;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001966}
1967
1968/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001969 * dpm_prepare - Prepare all non-sysdev devices for a system PM transition.
1970 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -04001971 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001972 * Execute the ->prepare() callback(s) for all devices.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001973 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001974int dpm_prepare(pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001975{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001976 int error = 0;
1977
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001978 trace_suspend_resume(TPS("dpm_prepare"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001979 might_sleep();
1980
Strashko, Grygorii013c0742015-11-10 11:42:34 +02001981 /*
1982 * Give a chance for the known devices to complete their probes, before
1983 * disable probing of devices. This sync point is important at least
1984 * at boot time + hibernation restore.
1985 */
1986 wait_for_device_probe();
1987 /*
1988 * It is unsafe if probing of devices will happen during suspend or
1989 * hibernation and system behavior will be unpredictable in this case.
1990 * So, let's prohibit device's probing here and defer their probes
1991 * instead. The normal behavior will be restored in dpm_complete().
1992 */
1993 device_block_probing();
1994
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001995 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001996 while (!list_empty(&dpm_list)) {
1997 struct device *dev = to_device(dpm_list.next);
1998
1999 get_device(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02002000 mutex_unlock(&dpm_list_mtx);
2001
Todd E Brandt32e8d682015-05-28 12:55:53 -07002002 trace_device_pm_callback_start(dev, "", state.event);
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02002003 error = device_prepare(dev, state);
Todd E Brandt32e8d682015-05-28 12:55:53 -07002004 trace_device_pm_callback_end(dev, error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02002005
2006 mutex_lock(&dpm_list_mtx);
2007 if (error) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02002008 if (error == -EAGAIN) {
2009 put_device(dev);
Sebastian Ott886a7a32009-07-08 13:26:05 +02002010 error = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02002011 continue;
2012 }
Rafael J. Wysocki1e75227e2010-12-03 22:58:05 +01002013 printk(KERN_INFO "PM: Device %s not prepared "
2014 "for power transition: code %d\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +01002015 dev_name(dev), error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02002016 put_device(dev);
2017 break;
2018 }
Alan Sternf76b168b2011-06-18 20:22:23 +02002019 dev->power.is_prepared = true;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02002020 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01002021 list_move_tail(&dev->power.entry, &dpm_prepared_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02002022 put_device(dev);
2023 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02002024 mutex_unlock(&dpm_list_mtx);
Todd E Brandtbb3632c2014-06-06 05:40:17 -07002025 trace_suspend_resume(TPS("dpm_prepare"), state.event, false);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02002026 return error;
2027}
2028
2029/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02002030 * dpm_suspend_start - Prepare devices for PM transition and suspend them.
2031 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02002032 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02002033 * Prepare all non-sysdev devices for system PM transition and execute "suspend"
2034 * callbacks for them.
Alan Sterncd59abf2007-09-21 15:36:56 -04002035 */
Alan Sternd1616302009-05-24 22:05:42 +02002036int dpm_suspend_start(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -04002037{
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01002038 int error;
Alan Sterncd59abf2007-09-21 15:36:56 -04002039
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02002040 error = dpm_prepare(state);
ShuoX Liu2a77c462011-08-10 23:01:26 +02002041 if (error) {
2042 suspend_stats.failed_prepare++;
2043 dpm_save_failed_step(SUSPEND_PREPARE);
2044 } else
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02002045 error = dpm_suspend(state);
Alan Sterncd59abf2007-09-21 15:36:56 -04002046 return error;
Alan Sterncd59abf2007-09-21 15:36:56 -04002047}
Alan Sternd1616302009-05-24 22:05:42 +02002048EXPORT_SYMBOL_GPL(dpm_suspend_start);
Alan Sterncd59abf2007-09-21 15:36:56 -04002049
2050void __suspend_report_result(const char *function, void *fn, int ret)
2051{
Bjorn Helgaasc80cfb02008-10-15 22:01:35 -07002052 if (ret)
2053 printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret);
Alan Sterncd59abf2007-09-21 15:36:56 -04002054}
2055EXPORT_SYMBOL_GPL(__suspend_report_result);
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01002056
2057/**
2058 * device_pm_wait_for_dev - Wait for suspend/resume of a device to complete.
2059 * @dev: Device to wait for.
2060 * @subordinate: Device that needs to wait for @dev.
2061 */
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02002062int device_pm_wait_for_dev(struct device *subordinate, struct device *dev)
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01002063{
2064 dpm_wait(dev, subordinate->power.async_suspend);
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02002065 return async_error;
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01002066}
2067EXPORT_SYMBOL_GPL(device_pm_wait_for_dev);
Ming Leidfe32122012-08-17 22:06:59 +08002068
2069/**
2070 * dpm_for_each_dev - device iterator.
2071 * @data: data for the callback.
2072 * @fn: function to be called for each device.
2073 *
2074 * Iterate over devices in dpm_list, and call @fn for each device,
2075 * passing it @data.
2076 */
2077void dpm_for_each_dev(void *data, void (*fn)(struct device *, void *))
2078{
2079 struct device *dev;
2080
2081 if (!fn)
2082 return;
2083
2084 device_pm_lock();
2085 list_for_each_entry(dev, &dpm_list, power.entry)
2086 fn(dev, data);
2087 device_pm_unlock();
2088}
2089EXPORT_SYMBOL_GPL(dpm_for_each_dev);
Tomeu Vizosoaa8e54b52016-01-07 16:46:14 +01002090
2091static bool pm_ops_is_empty(const struct dev_pm_ops *ops)
2092{
2093 if (!ops)
2094 return true;
2095
2096 return !ops->prepare &&
2097 !ops->suspend &&
2098 !ops->suspend_late &&
2099 !ops->suspend_noirq &&
2100 !ops->resume_noirq &&
2101 !ops->resume_early &&
2102 !ops->resume &&
2103 !ops->complete;
2104}
2105
2106void device_pm_check_callbacks(struct device *dev)
2107{
2108 spin_lock_irq(&dev->power.lock);
2109 dev->power.no_pm_callbacks =
Rafael J. Wysocki157c4602017-09-19 02:22:39 +02002110 (!dev->bus || (pm_ops_is_empty(dev->bus->pm) &&
2111 !dev->bus->suspend && !dev->bus->resume)) &&
Rafael J. Wysockia380f2e2017-09-25 14:56:44 +02002112 (!dev->class || pm_ops_is_empty(dev->class->pm)) &&
Tomeu Vizosoaa8e54b52016-01-07 16:46:14 +01002113 (!dev->type || pm_ops_is_empty(dev->type->pm)) &&
2114 (!dev->pm_domain || pm_ops_is_empty(&dev->pm_domain->ops)) &&
Rafael J. Wysocki157c4602017-09-19 02:22:39 +02002115 (!dev->driver || (pm_ops_is_empty(dev->driver->pm) &&
2116 !dev->driver->suspend && !dev->driver->resume));
Tomeu Vizosoaa8e54b52016-01-07 16:46:14 +01002117 spin_unlock_irq(&dev->power.lock);
2118}
Rafael J. Wysockic4b65152017-10-26 12:12:22 +02002119
2120bool dev_pm_smart_suspend_and_suspended(struct device *dev)
2121{
2122 return dev_pm_test_driver_flags(dev, DPM_FLAG_SMART_SUSPEND) &&
2123 pm_runtime_status_suspended(dev);
2124}