blob: 249e0304597f5bb6e4e48a26725bc712b1a5120b [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>
Alan Sterncd59abf2007-09-21 15:36:56 -040021#include <linux/kallsyms.h>
Paul Gortmaker1b6bc322011-05-27 07:12:15 -040022#include <linux/export.h>
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -070023#include <linux/mutex.h>
Alan Sterncd59abf2007-09-21 15:36:56 -040024#include <linux/pm.h>
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +020025#include <linux/pm_runtime.h>
Zhonghui Fu431d4522015-03-18 15:54:27 +010026#include <linux/pm-trace.h>
Tony Lindgren4990d4f2015-05-18 15:40:29 -070027#include <linux/pm_wakeirq.h>
Rafael J. Wysocki2ed8d2b2009-03-16 22:34:06 +010028#include <linux/interrupt.h>
Arjan van de Venf2511772009-12-13 20:29:01 +010029#include <linux/sched.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
Shuah Khan53644672013-07-26 13:30:20 -060064static char *pm_verb(int event)
65{
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
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100195static ktime_t initcall_debug_start(struct device *dev)
196{
Thomas Gleixner8b0e1952016-12-25 12:30:41 +0100197 ktime_t calltime = 0;
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100198
Rafael J. Wysockib2df1d42012-06-21 00:19:33 +0200199 if (pm_print_times_enabled) {
Rafael J. Wysocki0c6aebe2011-12-03 00:23:43 +0100200 pr_info("calling %s+ @ %i, parent: %s\n",
201 dev_name(dev), task_pid_nr(current),
202 dev->parent ? dev_name(dev->parent) : "none");
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100203 calltime = ktime_get();
204 }
205
206 return calltime;
207}
208
209static void initcall_debug_report(struct device *dev, ktime_t calltime,
Shuah Khan53644672013-07-26 13:30:20 -0600210 int error, pm_message_t state, char *info)
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100211{
Shuah Khan53644672013-07-26 13:30:20 -0600212 ktime_t rettime;
213 s64 nsecs;
214
215 rettime = ktime_get();
216 nsecs = (s64) ktime_to_ns(ktime_sub(rettime, calltime));
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100217
Rafael J. Wysockib2df1d42012-06-21 00:19:33 +0200218 if (pm_print_times_enabled) {
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100219 pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
Shuah Khan53644672013-07-26 13:30:20 -0600220 error, (unsigned long long)nsecs >> 10);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100221 }
222}
223
Cornelia Huckffa6a702009-03-04 12:44:00 +0100224/**
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100225 * dpm_wait - Wait for a PM operation to complete.
226 * @dev: Device to wait for.
227 * @async: If unset, wait only if the device's power.async_suspend flag is set.
228 */
229static void dpm_wait(struct device *dev, bool async)
230{
231 if (!dev)
232 return;
233
Rafael J. Wysocki0e06b4a2010-01-23 22:25:15 +0100234 if (async || (pm_async_enabled && dev->power.async_suspend))
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100235 wait_for_completion(&dev->power.completion);
236}
237
238static int dpm_wait_fn(struct device *dev, void *async_ptr)
239{
240 dpm_wait(dev, *((bool *)async_ptr));
241 return 0;
242}
243
244static void dpm_wait_for_children(struct device *dev, bool async)
245{
246 device_for_each_child(dev, &async, dpm_wait_fn);
247}
248
Rafael J. Wysocki8c73b422016-10-30 17:28:49 +0100249static void dpm_wait_for_suppliers(struct device *dev, bool async)
250{
251 struct device_link *link;
252 int idx;
253
254 idx = device_links_read_lock();
255
256 /*
257 * If the supplier goes away right after we've checked the link to it,
258 * we'll wait for its completion to change the state, but that's fine,
259 * because the only things that will block as a result are the SRCU
260 * callbacks freeing the link objects for the links in the list we're
261 * walking.
262 */
263 list_for_each_entry_rcu(link, &dev->links.suppliers, c_node)
264 if (READ_ONCE(link->status) != DL_STATE_DORMANT)
265 dpm_wait(link->supplier, async);
266
267 device_links_read_unlock(idx);
268}
269
270static void dpm_wait_for_superior(struct device *dev, bool async)
271{
272 dpm_wait(dev->parent, async);
273 dpm_wait_for_suppliers(dev, async);
274}
275
276static void dpm_wait_for_consumers(struct device *dev, bool async)
277{
278 struct device_link *link;
279 int idx;
280
281 idx = device_links_read_lock();
282
283 /*
284 * The status of a device link can only be changed from "dormant" by a
285 * probe, but that cannot happen during system suspend/resume. In
286 * theory it can change to "dormant" at that time, but then it is
287 * reasonable to wait for the target device anyway (eg. if it goes
288 * away, it's better to wait for it to go away completely and then
289 * continue instead of trying to continue in parallel with its
290 * unregistration).
291 */
292 list_for_each_entry_rcu(link, &dev->links.consumers, s_node)
293 if (READ_ONCE(link->status) != DL_STATE_DORMANT)
294 dpm_wait(link->consumer, async);
295
296 device_links_read_unlock(idx);
297}
298
299static void dpm_wait_for_subordinate(struct device *dev, bool async)
300{
301 dpm_wait_for_children(dev, async);
302 dpm_wait_for_consumers(dev, async);
303}
304
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100305/**
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100306 * pm_op - Return the PM operation appropriate for given PM event.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200307 * @ops: PM operations to choose from.
308 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200309 */
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100310static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200311{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200312 switch (state.event) {
313#ifdef CONFIG_SUSPEND
314 case PM_EVENT_SUSPEND:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100315 return ops->suspend;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200316 case PM_EVENT_RESUME:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100317 return ops->resume;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200318#endif /* CONFIG_SUSPEND */
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200319#ifdef CONFIG_HIBERNATE_CALLBACKS
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200320 case PM_EVENT_FREEZE:
321 case PM_EVENT_QUIESCE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100322 return ops->freeze;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200323 case PM_EVENT_HIBERNATE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100324 return ops->poweroff;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200325 case PM_EVENT_THAW:
326 case PM_EVENT_RECOVER:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100327 return ops->thaw;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200328 break;
329 case PM_EVENT_RESTORE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100330 return ops->restore;
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200331#endif /* CONFIG_HIBERNATE_CALLBACKS */
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200332 }
Arjan van de Venf2511772009-12-13 20:29:01 +0100333
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100334 return NULL;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200335}
336
337/**
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100338 * pm_late_early_op - Return the PM operation appropriate for given PM event.
339 * @ops: PM operations to choose from.
340 * @state: PM transition of the system being carried out.
341 *
342 * Runtime PM is disabled for @dev while this function is being executed.
343 */
344static pm_callback_t pm_late_early_op(const struct dev_pm_ops *ops,
345 pm_message_t state)
346{
347 switch (state.event) {
348#ifdef CONFIG_SUSPEND
349 case PM_EVENT_SUSPEND:
350 return ops->suspend_late;
351 case PM_EVENT_RESUME:
352 return ops->resume_early;
353#endif /* CONFIG_SUSPEND */
354#ifdef CONFIG_HIBERNATE_CALLBACKS
355 case PM_EVENT_FREEZE:
356 case PM_EVENT_QUIESCE:
357 return ops->freeze_late;
358 case PM_EVENT_HIBERNATE:
359 return ops->poweroff_late;
360 case PM_EVENT_THAW:
361 case PM_EVENT_RECOVER:
362 return ops->thaw_early;
363 case PM_EVENT_RESTORE:
364 return ops->restore_early;
365#endif /* CONFIG_HIBERNATE_CALLBACKS */
366 }
367
368 return NULL;
369}
370
371/**
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100372 * pm_noirq_op - Return the PM operation appropriate for given PM event.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200373 * @ops: PM operations to choose from.
374 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200375 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200376 * The driver of @dev will not receive interrupts while this function is being
377 * executed.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200378 */
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100379static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200380{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200381 switch (state.event) {
382#ifdef CONFIG_SUSPEND
383 case PM_EVENT_SUSPEND:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100384 return ops->suspend_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200385 case PM_EVENT_RESUME:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100386 return ops->resume_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200387#endif /* CONFIG_SUSPEND */
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200388#ifdef CONFIG_HIBERNATE_CALLBACKS
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200389 case PM_EVENT_FREEZE:
390 case PM_EVENT_QUIESCE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100391 return ops->freeze_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200392 case PM_EVENT_HIBERNATE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100393 return ops->poweroff_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200394 case PM_EVENT_THAW:
395 case PM_EVENT_RECOVER:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100396 return ops->thaw_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200397 case PM_EVENT_RESTORE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100398 return ops->restore_noirq;
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200399#endif /* CONFIG_HIBERNATE_CALLBACKS */
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200400 }
Arjan van de Venf2511772009-12-13 20:29:01 +0100401
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100402 return NULL;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200403}
404
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200405static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info)
406{
407 dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event),
408 ((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ?
409 ", may wakeup" : "");
410}
411
412static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
413 int error)
414{
415 printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100416 dev_name(dev), pm_verb(state.event), info, error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200417}
418
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100419static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
420{
421 ktime_t calltime;
Kevin Cernekee0702d9ee2010-09-20 22:32:10 +0200422 u64 usecs64;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100423 int usecs;
424
425 calltime = ktime_get();
426 usecs64 = ktime_to_ns(ktime_sub(calltime, starttime));
427 do_div(usecs64, NSEC_PER_USEC);
428 usecs = usecs64;
429 if (usecs == 0)
430 usecs = 1;
431 pr_info("PM: %s%s%s of devices complete after %ld.%03ld msecs\n",
432 info ?: "", info ? " " : "", pm_verb(state.event),
433 usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
434}
435
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100436static int dpm_run_callback(pm_callback_t cb, struct device *dev,
437 pm_message_t state, char *info)
438{
439 ktime_t calltime;
440 int error;
441
442 if (!cb)
443 return 0;
444
445 calltime = initcall_debug_start(dev);
446
447 pm_dev_dbg(dev, state, info);
Todd E Brandte8bca472014-06-10 07:31:22 -0700448 trace_device_pm_callback_start(dev, info, state.event);
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100449 error = cb(dev);
Todd E Brandte8bca472014-06-10 07:31:22 -0700450 trace_device_pm_callback_end(dev, error);
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100451 suspend_report_result(cb, error);
452
Shuah Khan53644672013-07-26 13:30:20 -0600453 initcall_debug_report(dev, calltime, error, state, info);
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100454
455 return error;
456}
457
Benoit Goby70fea602013-10-17 10:48:46 -0700458#ifdef CONFIG_DPM_WATCHDOG
459struct dpm_watchdog {
460 struct device *dev;
461 struct task_struct *tsk;
462 struct timer_list timer;
463};
464
465#define DECLARE_DPM_WATCHDOG_ON_STACK(wd) \
466 struct dpm_watchdog wd
467
468/**
469 * dpm_watchdog_handler - Driver suspend / resume watchdog handler.
470 * @data: Watchdog object address.
471 *
472 * Called when a driver has timed out suspending or resuming.
473 * There's not much we can do here to recover so panic() to
474 * capture a crash-dump in pstore.
475 */
476static void dpm_watchdog_handler(unsigned long data)
477{
478 struct dpm_watchdog *wd = (void *)data;
479
480 dev_emerg(wd->dev, "**** DPM device timeout ****\n");
481 show_stack(wd->tsk, NULL);
482 panic("%s %s: unrecoverable failure\n",
483 dev_driver_string(wd->dev), dev_name(wd->dev));
484}
485
486/**
487 * dpm_watchdog_set - Enable pm watchdog for given device.
488 * @wd: Watchdog. Must be allocated on the stack.
489 * @dev: Device to handle.
490 */
491static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev)
492{
493 struct timer_list *timer = &wd->timer;
494
495 wd->dev = dev;
496 wd->tsk = current;
497
498 init_timer_on_stack(timer);
499 /* use same timeout value for both suspend and resume */
500 timer->expires = jiffies + HZ * CONFIG_DPM_WATCHDOG_TIMEOUT;
501 timer->function = dpm_watchdog_handler;
502 timer->data = (unsigned long)wd;
503 add_timer(timer);
504}
505
506/**
507 * dpm_watchdog_clear - Disable suspend/resume watchdog.
508 * @wd: Watchdog to disable.
509 */
510static void dpm_watchdog_clear(struct dpm_watchdog *wd)
511{
512 struct timer_list *timer = &wd->timer;
513
514 del_timer_sync(timer);
515 destroy_timer_on_stack(timer);
516}
517#else
518#define DECLARE_DPM_WATCHDOG_ON_STACK(wd)
519#define dpm_watchdog_set(x, y)
520#define dpm_watchdog_clear(x)
521#endif
522
Alan Sterncd59abf2007-09-21 15:36:56 -0400523/*------------------------- Resume routines -------------------------*/
524
525/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200526 * device_resume_noirq - Execute an "early resume" callback for given device.
527 * @dev: Device to handle.
528 * @state: PM transition of the system being carried out.
Randy Dunlap58c256a2014-07-27 16:17:15 -0700529 * @async: If true, the device is being resumed asynchronously.
Alan Sterncd59abf2007-09-21 15:36:56 -0400530 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200531 * The driver of @dev will not receive interrupts while this function is being
532 * executed.
Alan Sterncd59abf2007-09-21 15:36:56 -0400533 */
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800534static int device_resume_noirq(struct device *dev, pm_message_t state, bool async)
Alan Sterncd59abf2007-09-21 15:36:56 -0400535{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100536 pm_callback_t callback = NULL;
537 char *info = NULL;
Alan Sterncd59abf2007-09-21 15:36:56 -0400538 int error = 0;
539
540 TRACE_DEVICE(dev);
541 TRACE_RESUME(0);
542
Rafael J. Wysockiaae45182014-05-16 02:46:50 +0200543 if (dev->power.syscore || dev->power.direct_complete)
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200544 goto Out;
545
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800546 if (!dev->power.is_noirq_suspended)
547 goto Out;
548
Rafael J. Wysocki8c73b422016-10-30 17:28:49 +0100549 dpm_wait_for_superior(dev, async);
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800550
Rafael J. Wysocki564b9052011-06-23 01:52:55 +0200551 if (dev->pm_domain) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100552 info = "noirq power domain ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100553 callback = pm_noirq_op(&dev->pm_domain->ops, state);
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200554 } else if (dev->type && dev->type->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100555 info = "noirq type ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100556 callback = pm_noirq_op(dev->type->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100557 } else if (dev->class && dev->class->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100558 info = "noirq class ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100559 callback = pm_noirq_op(dev->class->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100560 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100561 info = "noirq bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100562 callback = pm_noirq_op(dev->bus->pm, state);
Dominik Brodowskie7176a32010-03-15 21:43:11 +0100563 }
564
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100565 if (!callback && dev->driver && dev->driver->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100566 info = "noirq driver ";
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100567 callback = pm_noirq_op(dev->driver->pm, state);
568 }
569
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100570 error = dpm_run_callback(callback, dev, state, info);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800571 dev->power.is_noirq_suspended = false;
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100572
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200573 Out:
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800574 complete_all(&dev->power.completion);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100575 TRACE_RESUME(error);
576 return error;
577}
578
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800579static bool is_async(struct device *dev)
580{
581 return dev->power.async_suspend && pm_async_enabled
582 && !pm_trace_is_enabled();
583}
584
585static void async_resume_noirq(void *data, async_cookie_t cookie)
586{
587 struct device *dev = (struct device *)data;
588 int error;
589
590 error = device_resume_noirq(dev, pm_transition, true);
591 if (error)
592 pm_dev_err(dev, pm_transition, " async", error);
593
594 put_device(dev);
595}
596
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100597/**
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100598 * dpm_resume_noirq - Execute "noirq resume" callbacks for all devices.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200599 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100600 *
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100601 * Call the "noirq" resume handlers for all devices in dpm_noirq_list and
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200602 * enable device drivers to receive interrupts.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100603 */
Rafael J. Wysocki2a8a8ce2014-09-30 02:21:34 +0200604void dpm_resume_noirq(pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100605{
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800606 struct device *dev;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100607 ktime_t starttime = ktime_get();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100608
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700609 trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, true);
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200610 mutex_lock(&dpm_list_mtx);
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800611 pm_transition = state;
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100612
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800613 /*
614 * Advanced the async threads upfront,
615 * in case the starting of async threads is
616 * delayed by non-async resuming devices.
617 */
618 list_for_each_entry(dev, &dpm_noirq_list, power.entry) {
619 reinit_completion(&dev->power.completion);
620 if (is_async(dev)) {
621 get_device(dev);
622 async_schedule(async_resume_noirq, dev);
623 }
624 }
625
626 while (!list_empty(&dpm_noirq_list)) {
627 dev = to_device(dpm_noirq_list.next);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100628 get_device(dev);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100629 list_move_tail(&dev->power.entry, &dpm_late_early_list);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100630 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100631
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800632 if (!is_async(dev)) {
633 int error;
634
635 error = device_resume_noirq(dev, state, false);
636 if (error) {
637 suspend_stats.failed_resume_noirq++;
638 dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
639 dpm_save_failed_dev(dev_name(dev));
640 pm_dev_err(dev, state, " noirq", error);
641 }
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100642 }
643
644 mutex_lock(&dpm_list_mtx);
645 put_device(dev);
646 }
647 mutex_unlock(&dpm_list_mtx);
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800648 async_synchronize_full();
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100649 dpm_show_time(starttime, state, "noirq");
650 resume_device_irqs();
Tony Lindgren4990d4f2015-05-18 15:40:29 -0700651 device_wakeup_disarm_wake_irqs();
Preeti U Murthy8651f972012-07-09 10:12:56 +0200652 cpuidle_resume();
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700653 trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, false);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100654}
655
656/**
657 * device_resume_early - Execute an "early resume" callback for given device.
658 * @dev: Device to handle.
659 * @state: PM transition of the system being carried out.
Randy Dunlap58c256a2014-07-27 16:17:15 -0700660 * @async: If true, the device is being resumed asynchronously.
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100661 *
662 * Runtime PM is disabled for @dev while this function is being executed.
663 */
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800664static int device_resume_early(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100665{
666 pm_callback_t callback = NULL;
667 char *info = NULL;
668 int error = 0;
669
670 TRACE_DEVICE(dev);
671 TRACE_RESUME(0);
672
Rafael J. Wysockiaae45182014-05-16 02:46:50 +0200673 if (dev->power.syscore || dev->power.direct_complete)
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200674 goto Out;
675
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800676 if (!dev->power.is_late_suspended)
677 goto Out;
678
Rafael J. Wysocki8c73b422016-10-30 17:28:49 +0100679 dpm_wait_for_superior(dev, async);
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800680
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100681 if (dev->pm_domain) {
682 info = "early power domain ";
683 callback = pm_late_early_op(&dev->pm_domain->ops, state);
684 } else if (dev->type && dev->type->pm) {
685 info = "early type ";
686 callback = pm_late_early_op(dev->type->pm, state);
687 } else if (dev->class && dev->class->pm) {
688 info = "early class ";
689 callback = pm_late_early_op(dev->class->pm, state);
690 } else if (dev->bus && dev->bus->pm) {
691 info = "early bus ";
692 callback = pm_late_early_op(dev->bus->pm, state);
693 }
694
695 if (!callback && dev->driver && dev->driver->pm) {
696 info = "early driver ";
697 callback = pm_late_early_op(dev->driver->pm, state);
698 }
699
700 error = dpm_run_callback(callback, dev, state, info);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800701 dev->power.is_late_suspended = false;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100702
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200703 Out:
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100704 TRACE_RESUME(error);
Rafael J. Wysocki9f6d8f62012-12-22 23:59:01 +0100705
706 pm_runtime_enable(dev);
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800707 complete_all(&dev->power.completion);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100708 return error;
709}
710
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800711static void async_resume_early(void *data, async_cookie_t cookie)
712{
713 struct device *dev = (struct device *)data;
714 int error;
715
716 error = device_resume_early(dev, pm_transition, true);
717 if (error)
718 pm_dev_err(dev, pm_transition, " async", error);
719
720 put_device(dev);
721}
722
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100723/**
724 * dpm_resume_early - Execute "early resume" callbacks for all devices.
725 * @state: PM transition of the system being carried out.
726 */
Rafael J. Wysocki2a8a8ce2014-09-30 02:21:34 +0200727void dpm_resume_early(pm_message_t state)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100728{
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800729 struct device *dev;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100730 ktime_t starttime = ktime_get();
731
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700732 trace_suspend_resume(TPS("dpm_resume_early"), state.event, true);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100733 mutex_lock(&dpm_list_mtx);
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800734 pm_transition = state;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100735
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800736 /*
737 * Advanced the async threads upfront,
738 * in case the starting of async threads is
739 * delayed by non-async resuming devices.
740 */
741 list_for_each_entry(dev, &dpm_late_early_list, power.entry) {
742 reinit_completion(&dev->power.completion);
743 if (is_async(dev)) {
744 get_device(dev);
745 async_schedule(async_resume_early, dev);
746 }
747 }
748
749 while (!list_empty(&dpm_late_early_list)) {
750 dev = to_device(dpm_late_early_list.next);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100751 get_device(dev);
752 list_move_tail(&dev->power.entry, &dpm_suspended_list);
753 mutex_unlock(&dpm_list_mtx);
754
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800755 if (!is_async(dev)) {
756 int error;
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100757
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800758 error = device_resume_early(dev, state, false);
759 if (error) {
760 suspend_stats.failed_resume_early++;
761 dpm_save_failed_step(SUSPEND_RESUME_EARLY);
762 dpm_save_failed_dev(dev_name(dev));
763 pm_dev_err(dev, state, " early", error);
764 }
765 }
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100766 mutex_lock(&dpm_list_mtx);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100767 put_device(dev);
768 }
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200769 mutex_unlock(&dpm_list_mtx);
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800770 async_synchronize_full();
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100771 dpm_show_time(starttime, state, "early");
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700772 trace_suspend_resume(TPS("dpm_resume_early"), state.event, false);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100773}
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100774
775/**
776 * dpm_resume_start - Execute "noirq" and "early" device callbacks.
777 * @state: PM transition of the system being carried out.
778 */
779void dpm_resume_start(pm_message_t state)
780{
781 dpm_resume_noirq(state);
782 dpm_resume_early(state);
783}
784EXPORT_SYMBOL_GPL(dpm_resume_start);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100785
786/**
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100787 * device_resume - Execute "resume" callbacks for given device.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200788 * @dev: Device to handle.
789 * @state: PM transition of the system being carried out.
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100790 * @async: If true, the device is being resumed asynchronously.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100791 */
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100792static int device_resume(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100793{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100794 pm_callback_t callback = NULL;
795 char *info = NULL;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100796 int error = 0;
Benoit Goby70fea602013-10-17 10:48:46 -0700797 DECLARE_DPM_WATCHDOG_ON_STACK(wd);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100798
799 TRACE_DEVICE(dev);
800 TRACE_RESUME(0);
Alan Sterncd59abf2007-09-21 15:36:56 -0400801
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200802 if (dev->power.syscore)
803 goto Complete;
804
Rafael J. Wysockiaae45182014-05-16 02:46:50 +0200805 if (dev->power.direct_complete) {
806 /* Match the pm_runtime_disable() in __device_suspend(). */
807 pm_runtime_enable(dev);
808 goto Complete;
809 }
810
Rafael J. Wysocki8c73b422016-10-30 17:28:49 +0100811 dpm_wait_for_superior(dev, async);
Benoit Goby70fea602013-10-17 10:48:46 -0700812 dpm_watchdog_set(&wd, dev);
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800813 device_lock(dev);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100814
Alan Sternf76b168b2011-06-18 20:22:23 +0200815 /*
816 * This is a fib. But we'll allow new children to be added below
817 * a resumed device, even if the device hasn't been completed yet.
818 */
819 dev->power.is_prepared = false;
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100820
Alan Stern6d0e0e82011-06-18 22:42:09 +0200821 if (!dev->power.is_suspended)
822 goto Unlock;
823
Rafael J. Wysocki564b9052011-06-23 01:52:55 +0200824 if (dev->pm_domain) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100825 info = "power domain ";
826 callback = pm_op(&dev->pm_domain->ops, state);
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100827 goto Driver;
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +0100828 }
829
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100830 if (dev->type && dev->type->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100831 info = "type ";
832 callback = pm_op(dev->type->pm, state);
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100833 goto Driver;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100834 }
835
836 if (dev->class) {
837 if (dev->class->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100838 info = "class ";
839 callback = pm_op(dev->class->pm, state);
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100840 goto Driver;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100841 } else if (dev->class->resume) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100842 info = "legacy class ";
843 callback = dev->class->resume;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100844 goto End;
845 }
846 }
847
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200848 if (dev->bus) {
849 if (dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100850 info = "bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100851 callback = pm_op(dev->bus->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200852 } else if (dev->bus->resume) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100853 info = "legacy bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100854 callback = dev->bus->resume;
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100855 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200856 }
Alan Sterncd59abf2007-09-21 15:36:56 -0400857 }
858
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100859 Driver:
860 if (!callback && dev->driver && dev->driver->pm) {
861 info = "driver ";
862 callback = pm_op(dev->driver->pm, state);
863 }
864
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200865 End:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100866 error = dpm_run_callback(callback, dev, state, info);
Alan Stern6d0e0e82011-06-18 22:42:09 +0200867 dev->power.is_suspended = false;
868
869 Unlock:
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800870 device_unlock(dev);
Benoit Goby70fea602013-10-17 10:48:46 -0700871 dpm_watchdog_clear(&wd);
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200872
873 Complete:
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100874 complete_all(&dev->power.completion);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100875
Alan Sterncd59abf2007-09-21 15:36:56 -0400876 TRACE_RESUME(error);
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +0200877
Alan Sterncd59abf2007-09-21 15:36:56 -0400878 return error;
879}
880
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100881static void async_resume(void *data, async_cookie_t cookie)
882{
883 struct device *dev = (struct device *)data;
884 int error;
885
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100886 error = device_resume(dev, pm_transition, true);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100887 if (error)
888 pm_dev_err(dev, pm_transition, " async", error);
889 put_device(dev);
890}
891
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100892/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200893 * dpm_resume - Execute "resume" callbacks for non-sysdev devices.
894 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100895 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200896 * Execute the appropriate "resume" callback for all devices whose status
897 * indicates that they are suspended.
Alan Sterncd59abf2007-09-21 15:36:56 -0400898 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200899void dpm_resume(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400900{
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100901 struct device *dev;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100902 ktime_t starttime = ktime_get();
Alan Sterncd59abf2007-09-21 15:36:56 -0400903
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700904 trace_suspend_resume(TPS("dpm_resume"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200905 might_sleep();
906
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200907 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100908 pm_transition = state;
Rafael J. Wysocki098dff72010-09-22 22:10:57 +0200909 async_error = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200910
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100911 list_for_each_entry(dev, &dpm_suspended_list, power.entry) {
Wolfram Sang16735d02013-11-14 14:32:02 -0800912 reinit_completion(&dev->power.completion);
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100913 if (is_async(dev)) {
914 get_device(dev);
915 async_schedule(async_resume, dev);
916 }
917 }
918
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100919 while (!list_empty(&dpm_suspended_list)) {
920 dev = to_device(dpm_suspended_list.next);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200921 get_device(dev);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100922 if (!is_async(dev)) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200923 int error;
924
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200925 mutex_unlock(&dpm_list_mtx);
926
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100927 error = device_resume(dev, state, false);
ShuoX Liu2a77c462011-08-10 23:01:26 +0200928 if (error) {
929 suspend_stats.failed_resume++;
930 dpm_save_failed_step(SUSPEND_RESUME);
931 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200932 pm_dev_err(dev, state, "", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +0200933 }
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100934
935 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200936 }
937 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100938 list_move_tail(&dev->power.entry, &dpm_prepared_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200939 put_device(dev);
Alan Sterncd59abf2007-09-21 15:36:56 -0400940 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200941 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100942 async_synchronize_full();
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100943 dpm_show_time(starttime, state, NULL);
Viresh Kumar2f0aea92014-03-04 11:00:26 +0800944
945 cpufreq_resume();
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700946 trace_suspend_resume(TPS("dpm_resume"), state.event, false);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200947}
948
949/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200950 * device_complete - Complete a PM transition for given device.
951 * @dev: Device to handle.
952 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200953 */
Alan Sternd1616302009-05-24 22:05:42 +0200954static void device_complete(struct device *dev, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200955{
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100956 void (*callback)(struct device *) = NULL;
957 char *info = NULL;
958
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200959 if (dev->power.syscore)
960 return;
961
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800962 device_lock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200963
Rafael J. Wysocki564b9052011-06-23 01:52:55 +0200964 if (dev->pm_domain) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100965 info = "completing power domain ";
966 callback = dev->pm_domain->ops.complete;
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200967 } else if (dev->type && dev->type->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100968 info = "completing type ";
969 callback = dev->type->pm->complete;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100970 } else if (dev->class && dev->class->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100971 info = "completing class ";
972 callback = dev->class->pm->complete;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100973 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100974 info = "completing bus ";
975 callback = dev->bus->pm->complete;
976 }
977
978 if (!callback && dev->driver && dev->driver->pm) {
979 info = "completing driver ";
980 callback = dev->driver->pm->complete;
981 }
982
983 if (callback) {
984 pm_dev_dbg(dev, state, info);
985 callback(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200986 }
987
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800988 device_unlock(dev);
Alan Stern88d26132012-09-19 21:59:02 +0200989
Ulf Hanssonaf939332013-04-12 09:41:06 +0000990 pm_runtime_put(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200991}
992
993/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200994 * dpm_complete - Complete a PM transition for all non-sysdev devices.
995 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200996 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200997 * Execute the ->complete() callbacks for all devices whose PM status is not
998 * DPM_ON (this allows new devices to be registered).
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200999 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001000void dpm_complete(pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001001{
1002 struct list_head list;
1003
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001004 trace_suspend_resume(TPS("dpm_complete"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001005 might_sleep();
1006
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001007 INIT_LIST_HEAD(&list);
1008 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001009 while (!list_empty(&dpm_prepared_list)) {
1010 struct device *dev = to_device(dpm_prepared_list.prev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001011
1012 get_device(dev);
Alan Sternf76b168b2011-06-18 20:22:23 +02001013 dev->power.is_prepared = false;
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +01001014 list_move(&dev->power.entry, &list);
1015 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001016
Todd E Brandt32e8d682015-05-28 12:55:53 -07001017 trace_device_pm_callback_start(dev, "", state.event);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +01001018 device_complete(dev, state);
Todd E Brandt32e8d682015-05-28 12:55:53 -07001019 trace_device_pm_callback_end(dev, 0);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001020
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +01001021 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001022 put_device(dev);
1023 }
1024 list_splice(&list, &dpm_list);
Alan Sterncd59abf2007-09-21 15:36:56 -04001025 mutex_unlock(&dpm_list_mtx);
Strashko, Grygorii013c0742015-11-10 11:42:34 +02001026
1027 /* Allow device probing and trigger re-probing of deferred devices */
1028 device_unblock_probing();
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001029 trace_suspend_resume(TPS("dpm_complete"), state.event, false);
Alan Sterncd59abf2007-09-21 15:36:56 -04001030}
1031
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001032/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001033 * dpm_resume_end - Execute "resume" callbacks and complete system transition.
1034 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -04001035 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001036 * Execute "resume" callbacks for all devices and complete the PM transition of
1037 * the system.
Alan Sterncd59abf2007-09-21 15:36:56 -04001038 */
Alan Sternd1616302009-05-24 22:05:42 +02001039void dpm_resume_end(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001040{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001041 dpm_resume(state);
1042 dpm_complete(state);
Alan Sterncd59abf2007-09-21 15:36:56 -04001043}
Alan Sternd1616302009-05-24 22:05:42 +02001044EXPORT_SYMBOL_GPL(dpm_resume_end);
Alan Sterncd59abf2007-09-21 15:36:56 -04001045
1046
Alan Sterncd59abf2007-09-21 15:36:56 -04001047/*------------------------- Suspend routines -------------------------*/
1048
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001049/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001050 * resume_event - Return a "resume" message for given "suspend" sleep state.
1051 * @sleep_state: PM message representing a sleep state.
1052 *
1053 * Return a PM message representing the resume event corresponding to given
1054 * sleep state.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001055 */
1056static pm_message_t resume_event(pm_message_t sleep_state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001057{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001058 switch (sleep_state.event) {
1059 case PM_EVENT_SUSPEND:
1060 return PMSG_RESUME;
1061 case PM_EVENT_FREEZE:
1062 case PM_EVENT_QUIESCE:
1063 return PMSG_RECOVER;
1064 case PM_EVENT_HIBERNATE:
1065 return PMSG_RESTORE;
Alan Sterncd59abf2007-09-21 15:36:56 -04001066 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001067 return PMSG_ON;
Alan Sterncd59abf2007-09-21 15:36:56 -04001068}
1069
1070/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001071 * device_suspend_noirq - Execute a "late suspend" callback for given device.
1072 * @dev: Device to handle.
1073 * @state: PM transition of the system being carried out.
Randy Dunlap58c256a2014-07-27 16:17:15 -07001074 * @async: If true, the device is being suspended asynchronously.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001075 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001076 * The driver of @dev will not receive interrupts while this function is being
1077 * executed.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001078 */
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001079static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001080{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001081 pm_callback_t callback = NULL;
1082 char *info = NULL;
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001083 int error = 0;
1084
Zhonghui Fu431d4522015-03-18 15:54:27 +01001085 TRACE_DEVICE(dev);
1086 TRACE_SUSPEND(0);
1087
Linus Torvalds098c3052016-12-13 11:42:18 -08001088 dpm_wait_for_subordinate(dev, async);
Brian Norris6f75c3f2016-11-09 17:21:08 -08001089
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001090 if (async_error)
1091 goto Complete;
1092
1093 if (pm_wakeup_pending()) {
1094 async_error = -EBUSY;
1095 goto Complete;
1096 }
Dominik Brodowskie7176a32010-03-15 21:43:11 +01001097
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001098 if (dev->power.syscore || dev->power.direct_complete)
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001099 goto Complete;
1100
Rafael J. Wysocki564b9052011-06-23 01:52:55 +02001101 if (dev->pm_domain) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001102 info = "noirq power domain ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001103 callback = pm_noirq_op(&dev->pm_domain->ops, state);
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001104 } else if (dev->type && dev->type->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001105 info = "noirq type ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001106 callback = pm_noirq_op(dev->type->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001107 } else if (dev->class && dev->class->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001108 info = "noirq class ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001109 callback = pm_noirq_op(dev->class->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001110 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001111 info = "noirq bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001112 callback = pm_noirq_op(dev->bus->pm, state);
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001113 }
1114
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001115 if (!callback && dev->driver && dev->driver->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001116 info = "noirq driver ";
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001117 callback = pm_noirq_op(dev->driver->pm, state);
1118 }
1119
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001120 error = dpm_run_callback(callback, dev, state, info);
1121 if (!error)
1122 dev->power.is_noirq_suspended = true;
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001123 else
1124 async_error = error;
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001125
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001126Complete:
1127 complete_all(&dev->power.completion);
Zhonghui Fu431d4522015-03-18 15:54:27 +01001128 TRACE_SUSPEND(error);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001129 return error;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001130}
1131
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001132static void async_suspend_noirq(void *data, async_cookie_t cookie)
1133{
1134 struct device *dev = (struct device *)data;
1135 int error;
1136
1137 error = __device_suspend_noirq(dev, pm_transition, true);
1138 if (error) {
1139 dpm_save_failed_dev(dev_name(dev));
1140 pm_dev_err(dev, pm_transition, " async", error);
1141 }
1142
1143 put_device(dev);
1144}
1145
1146static int device_suspend_noirq(struct device *dev)
1147{
1148 reinit_completion(&dev->power.completion);
1149
Zhonghui Fu431d4522015-03-18 15:54:27 +01001150 if (is_async(dev)) {
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001151 get_device(dev);
1152 async_schedule(async_suspend_noirq, dev);
1153 return 0;
1154 }
1155 return __device_suspend_noirq(dev, pm_transition, false);
1156}
1157
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001158/**
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001159 * dpm_suspend_noirq - Execute "noirq suspend" callbacks for all devices.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001160 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001161 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001162 * Prevent device drivers from receiving interrupts and call the "noirq" suspend
1163 * handlers for all non-sysdev devices.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001164 */
Rafael J. Wysocki2a8a8ce2014-09-30 02:21:34 +02001165int dpm_suspend_noirq(pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001166{
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001167 ktime_t starttime = ktime_get();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001168 int error = 0;
1169
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001170 trace_suspend_resume(TPS("dpm_suspend_noirq"), state.event, true);
Preeti U Murthy8651f972012-07-09 10:12:56 +02001171 cpuidle_pause();
Tony Lindgren4990d4f2015-05-18 15:40:29 -07001172 device_wakeup_arm_wake_irqs();
Rafael J. Wysocki2ed8d2b2009-03-16 22:34:06 +01001173 suspend_device_irqs();
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +02001174 mutex_lock(&dpm_list_mtx);
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001175 pm_transition = state;
1176 async_error = 0;
1177
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001178 while (!list_empty(&dpm_late_early_list)) {
1179 struct device *dev = to_device(dpm_late_early_list.prev);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001180
1181 get_device(dev);
1182 mutex_unlock(&dpm_list_mtx);
1183
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001184 error = device_suspend_noirq(dev);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001185
1186 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001187 if (error) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001188 pm_dev_err(dev, state, " noirq", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001189 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001190 put_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001191 break;
1192 }
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001193 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001194 list_move(&dev->power.entry, &dpm_noirq_list);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001195 put_device(dev);
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001196
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001197 if (async_error)
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001198 break;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001199 }
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +02001200 mutex_unlock(&dpm_list_mtx);
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001201 async_synchronize_full();
1202 if (!error)
1203 error = async_error;
1204
1205 if (error) {
1206 suspend_stats.failed_suspend_noirq++;
1207 dpm_save_failed_step(SUSPEND_SUSPEND_NOIRQ);
Alan Sternd1616302009-05-24 22:05:42 +02001208 dpm_resume_noirq(resume_event(state));
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001209 } else {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001210 dpm_show_time(starttime, state, "noirq");
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001211 }
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001212 trace_suspend_resume(TPS("dpm_suspend_noirq"), state.event, false);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001213 return error;
1214}
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001215
1216/**
1217 * device_suspend_late - Execute a "late suspend" callback for given device.
1218 * @dev: Device to handle.
1219 * @state: PM transition of the system being carried out.
Randy Dunlap58c256a2014-07-27 16:17:15 -07001220 * @async: If true, the device is being suspended asynchronously.
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001221 *
1222 * Runtime PM is disabled for @dev while this function is being executed.
1223 */
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001224static int __device_suspend_late(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001225{
1226 pm_callback_t callback = NULL;
1227 char *info = NULL;
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001228 int error = 0;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001229
Zhonghui Fu431d4522015-03-18 15:54:27 +01001230 TRACE_DEVICE(dev);
1231 TRACE_SUSPEND(0);
1232
Rafael J. Wysocki9f6d8f62012-12-22 23:59:01 +01001233 __pm_runtime_disable(dev, false);
1234
Linus Torvalds098c3052016-12-13 11:42:18 -08001235 dpm_wait_for_subordinate(dev, async);
Brian Norris6f75c3f2016-11-09 17:21:08 -08001236
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001237 if (async_error)
1238 goto Complete;
1239
1240 if (pm_wakeup_pending()) {
1241 async_error = -EBUSY;
1242 goto Complete;
1243 }
1244
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001245 if (dev->power.syscore || dev->power.direct_complete)
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001246 goto Complete;
1247
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001248 if (dev->pm_domain) {
1249 info = "late power domain ";
1250 callback = pm_late_early_op(&dev->pm_domain->ops, state);
1251 } else if (dev->type && dev->type->pm) {
1252 info = "late type ";
1253 callback = pm_late_early_op(dev->type->pm, state);
1254 } else if (dev->class && dev->class->pm) {
1255 info = "late class ";
1256 callback = pm_late_early_op(dev->class->pm, state);
1257 } else if (dev->bus && dev->bus->pm) {
1258 info = "late bus ";
1259 callback = pm_late_early_op(dev->bus->pm, state);
1260 }
1261
1262 if (!callback && dev->driver && dev->driver->pm) {
1263 info = "late driver ";
1264 callback = pm_late_early_op(dev->driver->pm, state);
1265 }
1266
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001267 error = dpm_run_callback(callback, dev, state, info);
1268 if (!error)
1269 dev->power.is_late_suspended = true;
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001270 else
1271 async_error = error;
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001272
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001273Complete:
Zhonghui Fu431d4522015-03-18 15:54:27 +01001274 TRACE_SUSPEND(error);
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001275 complete_all(&dev->power.completion);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001276 return error;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001277}
1278
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001279static void async_suspend_late(void *data, async_cookie_t cookie)
1280{
1281 struct device *dev = (struct device *)data;
1282 int error;
1283
1284 error = __device_suspend_late(dev, pm_transition, true);
1285 if (error) {
1286 dpm_save_failed_dev(dev_name(dev));
1287 pm_dev_err(dev, pm_transition, " async", error);
1288 }
1289 put_device(dev);
1290}
1291
1292static int device_suspend_late(struct device *dev)
1293{
1294 reinit_completion(&dev->power.completion);
1295
Zhonghui Fu431d4522015-03-18 15:54:27 +01001296 if (is_async(dev)) {
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001297 get_device(dev);
1298 async_schedule(async_suspend_late, dev);
1299 return 0;
1300 }
1301
1302 return __device_suspend_late(dev, pm_transition, false);
1303}
1304
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001305/**
1306 * dpm_suspend_late - Execute "late suspend" callbacks for all devices.
1307 * @state: PM transition of the system being carried out.
1308 */
Rafael J. Wysocki2a8a8ce2014-09-30 02:21:34 +02001309int dpm_suspend_late(pm_message_t state)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001310{
1311 ktime_t starttime = ktime_get();
1312 int error = 0;
1313
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001314 trace_suspend_resume(TPS("dpm_suspend_late"), state.event, true);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001315 mutex_lock(&dpm_list_mtx);
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001316 pm_transition = state;
1317 async_error = 0;
1318
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001319 while (!list_empty(&dpm_suspended_list)) {
1320 struct device *dev = to_device(dpm_suspended_list.prev);
1321
1322 get_device(dev);
1323 mutex_unlock(&dpm_list_mtx);
1324
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001325 error = device_suspend_late(dev);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001326
1327 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki3a17fb32016-05-20 23:09:49 +02001328 if (!list_empty(&dev->power.entry))
1329 list_move(&dev->power.entry, &dpm_late_early_list);
1330
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001331 if (error) {
1332 pm_dev_err(dev, state, " late", error);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001333 dpm_save_failed_dev(dev_name(dev));
1334 put_device(dev);
1335 break;
1336 }
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001337 put_device(dev);
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001338
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001339 if (async_error)
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001340 break;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001341 }
1342 mutex_unlock(&dpm_list_mtx);
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001343 async_synchronize_full();
Imre Deak246ef762014-10-24 20:29:09 +03001344 if (!error)
1345 error = async_error;
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001346 if (error) {
1347 suspend_stats.failed_suspend_late++;
1348 dpm_save_failed_step(SUSPEND_SUSPEND_LATE);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001349 dpm_resume_early(resume_event(state));
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001350 } else {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001351 dpm_show_time(starttime, state, "late");
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001352 }
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001353 trace_suspend_resume(TPS("dpm_suspend_late"), state.event, false);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001354 return error;
1355}
1356
1357/**
1358 * dpm_suspend_end - Execute "late" and "noirq" device suspend callbacks.
1359 * @state: PM transition of the system being carried out.
1360 */
1361int dpm_suspend_end(pm_message_t state)
1362{
1363 int error = dpm_suspend_late(state);
Colin Cross064b0212012-07-19 10:38:06 +02001364 if (error)
1365 return error;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001366
Colin Cross064b0212012-07-19 10:38:06 +02001367 error = dpm_suspend_noirq(state);
1368 if (error) {
Feng Hong997a0312012-09-19 14:16:00 +02001369 dpm_resume_early(resume_event(state));
Colin Cross064b0212012-07-19 10:38:06 +02001370 return error;
1371 }
1372
1373 return 0;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001374}
1375EXPORT_SYMBOL_GPL(dpm_suspend_end);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001376
1377/**
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001378 * legacy_suspend - Execute a legacy (bus or class) suspend callback for device.
Randy Dunlap0a884222010-01-08 14:42:57 -08001379 * @dev: Device to suspend.
1380 * @state: PM transition of the system being carried out.
1381 * @cb: Suspend callback to execute.
Randy Dunlap58c256a2014-07-27 16:17:15 -07001382 * @info: string description of caller.
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001383 */
1384static int legacy_suspend(struct device *dev, pm_message_t state,
Shuah Khan53644672013-07-26 13:30:20 -06001385 int (*cb)(struct device *dev, pm_message_t state),
1386 char *info)
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001387{
1388 int error;
1389 ktime_t calltime;
1390
1391 calltime = initcall_debug_start(dev);
1392
Todd E Brandte8bca472014-06-10 07:31:22 -07001393 trace_device_pm_callback_start(dev, info, state.event);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001394 error = cb(dev, state);
Todd E Brandte8bca472014-06-10 07:31:22 -07001395 trace_device_pm_callback_end(dev, error);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001396 suspend_report_result(cb, error);
1397
Shuah Khan53644672013-07-26 13:30:20 -06001398 initcall_debug_report(dev, calltime, error, state, info);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001399
1400 return error;
1401}
1402
Rafael J. Wysocki8c73b422016-10-30 17:28:49 +01001403static void dpm_clear_suppliers_direct_complete(struct device *dev)
1404{
1405 struct device_link *link;
1406 int idx;
1407
1408 idx = device_links_read_lock();
1409
1410 list_for_each_entry_rcu(link, &dev->links.suppliers, c_node) {
1411 spin_lock_irq(&link->supplier->power.lock);
1412 link->supplier->power.direct_complete = false;
1413 spin_unlock_irq(&link->supplier->power.lock);
1414 }
1415
1416 device_links_read_unlock(idx);
1417}
1418
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001419/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001420 * device_suspend - Execute "suspend" callbacks for given device.
1421 * @dev: Device to handle.
1422 * @state: PM transition of the system being carried out.
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001423 * @async: If true, the device is being suspended asynchronously.
Alan Sterncd59abf2007-09-21 15:36:56 -04001424 */
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001425static int __device_suspend(struct device *dev, pm_message_t state, bool async)
Alan Sterncd59abf2007-09-21 15:36:56 -04001426{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001427 pm_callback_t callback = NULL;
1428 char *info = NULL;
Alan Sterncd59abf2007-09-21 15:36:56 -04001429 int error = 0;
Benoit Goby70fea602013-10-17 10:48:46 -07001430 DECLARE_DPM_WATCHDOG_ON_STACK(wd);
Alan Sterncd59abf2007-09-21 15:36:56 -04001431
Zhonghui Fu431d4522015-03-18 15:54:27 +01001432 TRACE_DEVICE(dev);
1433 TRACE_SUSPEND(0);
1434
Rafael J. Wysocki8c73b422016-10-30 17:28:49 +01001435 dpm_wait_for_subordinate(dev, async);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +01001436
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001437 if (async_error)
Mandeep Singh Baines1f758b22012-06-24 23:31:09 +02001438 goto Complete;
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001439
Alan Stern88d26132012-09-19 21:59:02 +02001440 /*
1441 * If a device configured to wake up the system from sleep states
1442 * has been suspended at run time and there's a resume request pending
1443 * for it, this is equivalent to the device signaling wakeup, so the
1444 * system suspend operation should be aborted.
1445 */
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001446 if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
1447 pm_wakeup_event(dev, 0);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001448
Rafael J. Wysockid83f9052010-12-03 23:14:26 +01001449 if (pm_wakeup_pending()) {
1450 async_error = -EBUSY;
Mandeep Singh Baines1f758b22012-06-24 23:31:09 +02001451 goto Complete;
Rafael J. Wysockid83f9052010-12-03 23:14:26 +01001452 }
1453
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001454 if (dev->power.syscore)
1455 goto Complete;
1456
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001457 if (dev->power.direct_complete) {
1458 if (pm_runtime_status_suspended(dev)) {
1459 pm_runtime_disable(dev);
Alan Stern019d8812015-07-15 14:40:06 +02001460 if (pm_runtime_status_suspended(dev))
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001461 goto Complete;
1462
1463 pm_runtime_enable(dev);
1464 }
1465 dev->power.direct_complete = false;
1466 }
1467
Benoit Goby70fea602013-10-17 10:48:46 -07001468 dpm_watchdog_set(&wd, dev);
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001469 device_lock(dev);
1470
Rafael J. Wysocki564b9052011-06-23 01:52:55 +02001471 if (dev->pm_domain) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001472 info = "power domain ";
1473 callback = pm_op(&dev->pm_domain->ops, state);
1474 goto Run;
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001475 }
1476
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001477 if (dev->type && dev->type->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001478 info = "type ";
1479 callback = pm_op(dev->type->pm, state);
1480 goto Run;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001481 }
1482
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001483 if (dev->class) {
1484 if (dev->class->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001485 info = "class ";
1486 callback = pm_op(dev->class->pm, state);
1487 goto Run;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001488 } else if (dev->class->suspend) {
1489 pm_dev_dbg(dev, state, "legacy class ");
Shuah Khan53644672013-07-26 13:30:20 -06001490 error = legacy_suspend(dev, state, dev->class->suspend,
1491 "legacy class ");
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001492 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001493 }
Alan Sterncd59abf2007-09-21 15:36:56 -04001494 }
1495
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001496 if (dev->bus) {
1497 if (dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001498 info = "bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001499 callback = pm_op(dev->bus->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001500 } else if (dev->bus->suspend) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001501 pm_dev_dbg(dev, state, "legacy bus ");
Shuah Khan53644672013-07-26 13:30:20 -06001502 error = legacy_suspend(dev, state, dev->bus->suspend,
1503 "legacy bus ");
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001504 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001505 }
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001506 }
1507
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001508 Run:
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001509 if (!callback && dev->driver && dev->driver->pm) {
1510 info = "driver ";
1511 callback = pm_op(dev->driver->pm, state);
1512 }
1513
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001514 error = dpm_run_callback(callback, dev, state, info);
1515
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001516 End:
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001517 if (!error) {
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001518 struct device *parent = dev->parent;
1519
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001520 dev->power.is_suspended = true;
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001521 if (parent) {
1522 spin_lock_irq(&parent->power.lock);
1523
1524 dev->parent->power.direct_complete = false;
1525 if (dev->power.wakeup_path
1526 && !dev->parent->power.ignore_children)
1527 dev->parent->power.wakeup_path = true;
1528
1529 spin_unlock_irq(&parent->power.lock);
1530 }
Rafael J. Wysocki8c73b422016-10-30 17:28:49 +01001531 dpm_clear_suppliers_direct_complete(dev);
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001532 }
Alan Stern6d0e0e82011-06-18 22:42:09 +02001533
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001534 device_unlock(dev);
Benoit Goby70fea602013-10-17 10:48:46 -07001535 dpm_watchdog_clear(&wd);
Mandeep Singh Baines1f758b22012-06-24 23:31:09 +02001536
1537 Complete:
Alan Stern88d26132012-09-19 21:59:02 +02001538 if (error)
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001539 async_error = error;
1540
Sahitya Tummala05a92622016-12-07 20:10:32 +05301541 complete_all(&dev->power.completion);
Zhonghui Fu431d4522015-03-18 15:54:27 +01001542 TRACE_SUSPEND(error);
Alan Sterncd59abf2007-09-21 15:36:56 -04001543 return error;
1544}
1545
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001546static void async_suspend(void *data, async_cookie_t cookie)
1547{
1548 struct device *dev = (struct device *)data;
1549 int error;
1550
1551 error = __device_suspend(dev, pm_transition, true);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001552 if (error) {
1553 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001554 pm_dev_err(dev, pm_transition, " async", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001555 }
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001556
1557 put_device(dev);
1558}
1559
1560static int device_suspend(struct device *dev)
1561{
Wolfram Sang16735d02013-11-14 14:32:02 -08001562 reinit_completion(&dev->power.completion);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001563
Zhonghui Fu431d4522015-03-18 15:54:27 +01001564 if (is_async(dev)) {
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001565 get_device(dev);
1566 async_schedule(async_suspend, dev);
1567 return 0;
1568 }
1569
1570 return __device_suspend(dev, pm_transition, false);
1571}
1572
Alan Sterncd59abf2007-09-21 15:36:56 -04001573/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001574 * dpm_suspend - Execute "suspend" callbacks for all non-sysdev devices.
1575 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -04001576 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001577int dpm_suspend(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001578{
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001579 ktime_t starttime = ktime_get();
Alan Sterncd59abf2007-09-21 15:36:56 -04001580 int error = 0;
1581
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001582 trace_suspend_resume(TPS("dpm_suspend"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001583 might_sleep();
1584
Viresh Kumar2f0aea92014-03-04 11:00:26 +08001585 cpufreq_suspend();
1586
Alan Sterncd59abf2007-09-21 15:36:56 -04001587 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001588 pm_transition = state;
1589 async_error = 0;
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001590 while (!list_empty(&dpm_prepared_list)) {
1591 struct device *dev = to_device(dpm_prepared_list.prev);
Alan Sterncd59abf2007-09-21 15:36:56 -04001592
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001593 get_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001594 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001595
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001596 error = device_suspend(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001597
Alan Stern1b3cbec2008-02-29 11:50:22 -05001598 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001599 if (error) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001600 pm_dev_err(dev, state, "", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001601 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001602 put_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001603 break;
1604 }
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +01001605 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001606 list_move(&dev->power.entry, &dpm_suspended_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001607 put_device(dev);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001608 if (async_error)
1609 break;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001610 }
1611 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001612 async_synchronize_full();
1613 if (!error)
1614 error = async_error;
ShuoX Liu2a77c462011-08-10 23:01:26 +02001615 if (error) {
1616 suspend_stats.failed_suspend++;
1617 dpm_save_failed_step(SUSPEND_SUSPEND);
1618 } else
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001619 dpm_show_time(starttime, state, NULL);
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001620 trace_suspend_resume(TPS("dpm_suspend"), state.event, false);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001621 return error;
1622}
1623
1624/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001625 * device_prepare - Prepare a device for system power transition.
1626 * @dev: Device to handle.
1627 * @state: PM transition of the system being carried out.
1628 *
1629 * Execute the ->prepare() callback(s) for given device. No new children of the
1630 * device may be registered after this function has returned.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001631 */
Alan Sternd1616302009-05-24 22:05:42 +02001632static int device_prepare(struct device *dev, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001633{
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001634 int (*callback)(struct device *) = NULL;
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001635 int ret = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001636
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001637 if (dev->power.syscore)
1638 return 0;
1639
Alan Stern88d26132012-09-19 21:59:02 +02001640 /*
1641 * If a device's parent goes into runtime suspend at the wrong time,
1642 * it won't be possible to resume the device. To prevent this we
1643 * block runtime suspend here, during the prepare phase, and allow
1644 * it again during the complete phase.
1645 */
1646 pm_runtime_get_noresume(dev);
1647
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001648 device_lock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001649
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001650 dev->power.wakeup_path = device_may_wakeup(dev);
1651
Tomeu Vizosoaa8e54b52016-01-07 16:46:14 +01001652 if (dev->power.no_pm_callbacks) {
1653 ret = 1; /* Let device go direct_complete */
1654 goto unlock;
1655 }
1656
Thierry Redingfba1fbf2016-04-28 14:42:34 +02001657 if (dev->pm_domain)
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001658 callback = dev->pm_domain->ops.prepare;
Thierry Redingfba1fbf2016-04-28 14:42:34 +02001659 else if (dev->type && dev->type->pm)
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001660 callback = dev->type->pm->prepare;
Thierry Redingfba1fbf2016-04-28 14:42:34 +02001661 else if (dev->class && dev->class->pm)
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001662 callback = dev->class->pm->prepare;
Thierry Redingfba1fbf2016-04-28 14:42:34 +02001663 else if (dev->bus && dev->bus->pm)
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001664 callback = dev->bus->pm->prepare;
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001665
Thierry Redingfba1fbf2016-04-28 14:42:34 +02001666 if (!callback && dev->driver && dev->driver->pm)
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001667 callback = dev->driver->pm->prepare;
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001668
Todd E Brandt32e8d682015-05-28 12:55:53 -07001669 if (callback)
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001670 ret = callback(dev);
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001671
Tomeu Vizosoaa8e54b52016-01-07 16:46:14 +01001672unlock:
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001673 device_unlock(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001674
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001675 if (ret < 0) {
1676 suspend_report_result(callback, ret);
Ulf Hanssonaa1b9f12013-11-13 15:45:03 +01001677 pm_runtime_put(dev);
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001678 return ret;
1679 }
1680 /*
1681 * A positive return value from ->prepare() means "this device appears
1682 * to be runtime-suspended and its state is fine, so if it really is
1683 * runtime-suspended, you can leave it in that state provided that you
1684 * will do the same thing with all of its descendants". This only
1685 * applies to suspend transitions, however.
1686 */
1687 spin_lock_irq(&dev->power.lock);
1688 dev->power.direct_complete = ret > 0 && state.event == PM_EVENT_SUSPEND;
1689 spin_unlock_irq(&dev->power.lock);
1690 return 0;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001691}
1692
1693/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001694 * dpm_prepare - Prepare all non-sysdev devices for a system PM transition.
1695 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -04001696 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001697 * Execute the ->prepare() callback(s) for all devices.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001698 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001699int dpm_prepare(pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001700{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001701 int error = 0;
1702
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001703 trace_suspend_resume(TPS("dpm_prepare"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001704 might_sleep();
1705
Strashko, Grygorii013c0742015-11-10 11:42:34 +02001706 /*
1707 * Give a chance for the known devices to complete their probes, before
1708 * disable probing of devices. This sync point is important at least
1709 * at boot time + hibernation restore.
1710 */
1711 wait_for_device_probe();
1712 /*
1713 * It is unsafe if probing of devices will happen during suspend or
1714 * hibernation and system behavior will be unpredictable in this case.
1715 * So, let's prohibit device's probing here and defer their probes
1716 * instead. The normal behavior will be restored in dpm_complete().
1717 */
1718 device_block_probing();
1719
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001720 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001721 while (!list_empty(&dpm_list)) {
1722 struct device *dev = to_device(dpm_list.next);
1723
1724 get_device(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001725 mutex_unlock(&dpm_list_mtx);
1726
Todd E Brandt32e8d682015-05-28 12:55:53 -07001727 trace_device_pm_callback_start(dev, "", state.event);
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001728 error = device_prepare(dev, state);
Todd E Brandt32e8d682015-05-28 12:55:53 -07001729 trace_device_pm_callback_end(dev, error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001730
1731 mutex_lock(&dpm_list_mtx);
1732 if (error) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001733 if (error == -EAGAIN) {
1734 put_device(dev);
Sebastian Ott886a7a32009-07-08 13:26:05 +02001735 error = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001736 continue;
1737 }
Rafael J. Wysocki1e75227e2010-12-03 22:58:05 +01001738 printk(KERN_INFO "PM: Device %s not prepared "
1739 "for power transition: code %d\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +01001740 dev_name(dev), error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001741 put_device(dev);
1742 break;
1743 }
Alan Sternf76b168b2011-06-18 20:22:23 +02001744 dev->power.is_prepared = true;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001745 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001746 list_move_tail(&dev->power.entry, &dpm_prepared_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001747 put_device(dev);
1748 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001749 mutex_unlock(&dpm_list_mtx);
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001750 trace_suspend_resume(TPS("dpm_prepare"), state.event, false);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001751 return error;
1752}
1753
1754/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001755 * dpm_suspend_start - Prepare devices for PM transition and suspend them.
1756 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001757 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001758 * Prepare all non-sysdev devices for system PM transition and execute "suspend"
1759 * callbacks for them.
Alan Sterncd59abf2007-09-21 15:36:56 -04001760 */
Alan Sternd1616302009-05-24 22:05:42 +02001761int dpm_suspend_start(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001762{
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001763 int error;
Alan Sterncd59abf2007-09-21 15:36:56 -04001764
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001765 error = dpm_prepare(state);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001766 if (error) {
1767 suspend_stats.failed_prepare++;
1768 dpm_save_failed_step(SUSPEND_PREPARE);
1769 } else
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001770 error = dpm_suspend(state);
Alan Sterncd59abf2007-09-21 15:36:56 -04001771 return error;
Alan Sterncd59abf2007-09-21 15:36:56 -04001772}
Alan Sternd1616302009-05-24 22:05:42 +02001773EXPORT_SYMBOL_GPL(dpm_suspend_start);
Alan Sterncd59abf2007-09-21 15:36:56 -04001774
1775void __suspend_report_result(const char *function, void *fn, int ret)
1776{
Bjorn Helgaasc80cfb02008-10-15 22:01:35 -07001777 if (ret)
1778 printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret);
Alan Sterncd59abf2007-09-21 15:36:56 -04001779}
1780EXPORT_SYMBOL_GPL(__suspend_report_result);
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001781
1782/**
1783 * device_pm_wait_for_dev - Wait for suspend/resume of a device to complete.
1784 * @dev: Device to wait for.
1785 * @subordinate: Device that needs to wait for @dev.
1786 */
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001787int device_pm_wait_for_dev(struct device *subordinate, struct device *dev)
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001788{
1789 dpm_wait(dev, subordinate->power.async_suspend);
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001790 return async_error;
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001791}
1792EXPORT_SYMBOL_GPL(device_pm_wait_for_dev);
Ming Leidfe32122012-08-17 22:06:59 +08001793
1794/**
1795 * dpm_for_each_dev - device iterator.
1796 * @data: data for the callback.
1797 * @fn: function to be called for each device.
1798 *
1799 * Iterate over devices in dpm_list, and call @fn for each device,
1800 * passing it @data.
1801 */
1802void dpm_for_each_dev(void *data, void (*fn)(struct device *, void *))
1803{
1804 struct device *dev;
1805
1806 if (!fn)
1807 return;
1808
1809 device_pm_lock();
1810 list_for_each_entry(dev, &dpm_list, power.entry)
1811 fn(dev, data);
1812 device_pm_unlock();
1813}
1814EXPORT_SYMBOL_GPL(dpm_for_each_dev);
Tomeu Vizosoaa8e54b52016-01-07 16:46:14 +01001815
1816static bool pm_ops_is_empty(const struct dev_pm_ops *ops)
1817{
1818 if (!ops)
1819 return true;
1820
1821 return !ops->prepare &&
1822 !ops->suspend &&
1823 !ops->suspend_late &&
1824 !ops->suspend_noirq &&
1825 !ops->resume_noirq &&
1826 !ops->resume_early &&
1827 !ops->resume &&
1828 !ops->complete;
1829}
1830
1831void device_pm_check_callbacks(struct device *dev)
1832{
1833 spin_lock_irq(&dev->power.lock);
1834 dev->power.no_pm_callbacks =
1835 (!dev->bus || pm_ops_is_empty(dev->bus->pm)) &&
1836 (!dev->class || pm_ops_is_empty(dev->class->pm)) &&
1837 (!dev->type || pm_ops_is_empty(dev->type->pm)) &&
1838 (!dev->pm_domain || pm_ops_is_empty(&dev->pm_domain->ops)) &&
1839 (!dev->driver || pm_ops_is_empty(dev->driver->pm));
1840 spin_unlock_irq(&dev->power.lock);
1841}