blob: 6f2515c571f1cc2d6455559bd089b0084bf69991 [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. Wysocki2ed8d2b32009-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. Wysocki1e752272010-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));
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700128 mutex_lock(&dpm_list_mtx);
Alan Sternf76b168b2011-06-18 20:22:23 +0200129 if (dev->parent && dev->parent->power.is_prepared)
Rafael J. Wysockib64959e2010-12-16 17:11:45 +0100130 dev_warn(dev, "parent %s should not be sleeping\n",
131 dev_name(dev->parent));
Alan Stern3b98aea2008-08-07 13:06:12 -0400132 list_add_tail(&dev->power.entry, &dpm_list);
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200133 mutex_unlock(&dpm_list_mtx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700134}
135
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100136/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200137 * device_pm_remove - Remove a device from the PM core's list of active devices.
138 * @dev: Device to be removed from the list.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100139 */
Rafael J. Wysocki9cddad72007-06-13 15:53:34 +0200140void device_pm_remove(struct device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700141{
142 pr_debug("PM: Removing info for %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100143 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100144 complete_all(&dev->power.completion);
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700145 mutex_lock(&dpm_list_mtx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700146 list_del_init(&dev->power.entry);
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700147 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki074037e2010-09-22 22:09:10 +0200148 device_wakeup_disable(dev);
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +0200149 pm_runtime_remove(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100150}
151
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200152/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200153 * device_pm_move_before - Move device in the PM core's list of active devices.
154 * @deva: Device to move in dpm_list.
155 * @devb: Device @deva should come before.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100156 */
157void device_pm_move_before(struct device *deva, struct device *devb)
158{
159 pr_debug("PM: Moving %s:%s before %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100160 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
161 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
Cornelia Huckffa6a702009-03-04 12:44:00 +0100162 /* Delete deva from dpm_list and reinsert before devb. */
163 list_move_tail(&deva->power.entry, &devb->power.entry);
164}
165
166/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200167 * device_pm_move_after - Move device in the PM core's list of active devices.
168 * @deva: Device to move in dpm_list.
169 * @devb: Device @deva should come after.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100170 */
171void device_pm_move_after(struct device *deva, struct device *devb)
172{
173 pr_debug("PM: Moving %s:%s after %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100174 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
175 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
Cornelia Huckffa6a702009-03-04 12:44:00 +0100176 /* Delete deva from dpm_list and reinsert after devb. */
177 list_move(&deva->power.entry, &devb->power.entry);
178}
179
180/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200181 * device_pm_move_last - Move device to end of the PM core's list of devices.
182 * @dev: Device to move in dpm_list.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100183 */
184void device_pm_move_last(struct device *dev)
185{
186 pr_debug("PM: Moving %s:%s to end of list\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100187 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
Cornelia Huckffa6a702009-03-04 12:44:00 +0100188 list_move_tail(&dev->power.entry, &dpm_list);
189}
190
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100191static ktime_t initcall_debug_start(struct device *dev)
192{
193 ktime_t calltime = ktime_set(0, 0);
194
Rafael J. Wysockib2df1d42012-06-21 00:19:33 +0200195 if (pm_print_times_enabled) {
Rafael J. Wysocki0c6aebe2011-12-03 00:23:43 +0100196 pr_info("calling %s+ @ %i, parent: %s\n",
197 dev_name(dev), task_pid_nr(current),
198 dev->parent ? dev_name(dev->parent) : "none");
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100199 calltime = ktime_get();
200 }
201
202 return calltime;
203}
204
205static void initcall_debug_report(struct device *dev, ktime_t calltime,
Shuah Khan53644672013-07-26 13:30:20 -0600206 int error, pm_message_t state, char *info)
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100207{
Shuah Khan53644672013-07-26 13:30:20 -0600208 ktime_t rettime;
209 s64 nsecs;
210
211 rettime = ktime_get();
212 nsecs = (s64) ktime_to_ns(ktime_sub(rettime, calltime));
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100213
Rafael J. Wysockib2df1d42012-06-21 00:19:33 +0200214 if (pm_print_times_enabled) {
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100215 pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
Shuah Khan53644672013-07-26 13:30:20 -0600216 error, (unsigned long long)nsecs >> 10);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100217 }
218}
219
Cornelia Huckffa6a702009-03-04 12:44:00 +0100220/**
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100221 * dpm_wait - Wait for a PM operation to complete.
222 * @dev: Device to wait for.
223 * @async: If unset, wait only if the device's power.async_suspend flag is set.
224 */
225static void dpm_wait(struct device *dev, bool async)
226{
227 if (!dev)
228 return;
229
Rafael J. Wysocki0e06b4a2010-01-23 22:25:15 +0100230 if (async || (pm_async_enabled && dev->power.async_suspend))
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100231 wait_for_completion(&dev->power.completion);
232}
233
234static int dpm_wait_fn(struct device *dev, void *async_ptr)
235{
236 dpm_wait(dev, *((bool *)async_ptr));
237 return 0;
238}
239
240static void dpm_wait_for_children(struct device *dev, bool async)
241{
242 device_for_each_child(dev, &async, dpm_wait_fn);
243}
244
245/**
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100246 * pm_op - Return the PM operation appropriate for given PM event.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200247 * @ops: PM operations to choose from.
248 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200249 */
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100250static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200251{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200252 switch (state.event) {
253#ifdef CONFIG_SUSPEND
254 case PM_EVENT_SUSPEND:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100255 return ops->suspend;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200256 case PM_EVENT_RESUME:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100257 return ops->resume;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200258#endif /* CONFIG_SUSPEND */
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200259#ifdef CONFIG_HIBERNATE_CALLBACKS
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200260 case PM_EVENT_FREEZE:
261 case PM_EVENT_QUIESCE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100262 return ops->freeze;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200263 case PM_EVENT_HIBERNATE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100264 return ops->poweroff;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200265 case PM_EVENT_THAW:
266 case PM_EVENT_RECOVER:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100267 return ops->thaw;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200268 break;
269 case PM_EVENT_RESTORE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100270 return ops->restore;
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200271#endif /* CONFIG_HIBERNATE_CALLBACKS */
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200272 }
Arjan van de Venf2511772009-12-13 20:29:01 +0100273
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100274 return NULL;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200275}
276
277/**
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100278 * pm_late_early_op - Return the PM operation appropriate for given PM event.
279 * @ops: PM operations to choose from.
280 * @state: PM transition of the system being carried out.
281 *
282 * Runtime PM is disabled for @dev while this function is being executed.
283 */
284static pm_callback_t pm_late_early_op(const struct dev_pm_ops *ops,
285 pm_message_t state)
286{
287 switch (state.event) {
288#ifdef CONFIG_SUSPEND
289 case PM_EVENT_SUSPEND:
290 return ops->suspend_late;
291 case PM_EVENT_RESUME:
292 return ops->resume_early;
293#endif /* CONFIG_SUSPEND */
294#ifdef CONFIG_HIBERNATE_CALLBACKS
295 case PM_EVENT_FREEZE:
296 case PM_EVENT_QUIESCE:
297 return ops->freeze_late;
298 case PM_EVENT_HIBERNATE:
299 return ops->poweroff_late;
300 case PM_EVENT_THAW:
301 case PM_EVENT_RECOVER:
302 return ops->thaw_early;
303 case PM_EVENT_RESTORE:
304 return ops->restore_early;
305#endif /* CONFIG_HIBERNATE_CALLBACKS */
306 }
307
308 return NULL;
309}
310
311/**
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100312 * pm_noirq_op - Return the PM operation appropriate for given PM event.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200313 * @ops: PM operations to choose from.
314 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200315 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200316 * The driver of @dev will not receive interrupts while this function is being
317 * executed.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200318 */
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100319static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200320{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200321 switch (state.event) {
322#ifdef CONFIG_SUSPEND
323 case PM_EVENT_SUSPEND:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100324 return ops->suspend_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200325 case PM_EVENT_RESUME:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100326 return ops->resume_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200327#endif /* CONFIG_SUSPEND */
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200328#ifdef CONFIG_HIBERNATE_CALLBACKS
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200329 case PM_EVENT_FREEZE:
330 case PM_EVENT_QUIESCE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100331 return ops->freeze_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200332 case PM_EVENT_HIBERNATE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100333 return ops->poweroff_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200334 case PM_EVENT_THAW:
335 case PM_EVENT_RECOVER:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100336 return ops->thaw_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200337 case PM_EVENT_RESTORE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100338 return ops->restore_noirq;
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200339#endif /* CONFIG_HIBERNATE_CALLBACKS */
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200340 }
Arjan van de Venf2511772009-12-13 20:29:01 +0100341
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100342 return NULL;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200343}
344
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200345static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info)
346{
347 dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event),
348 ((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ?
349 ", may wakeup" : "");
350}
351
352static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
353 int error)
354{
355 printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100356 dev_name(dev), pm_verb(state.event), info, error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200357}
358
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100359static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
360{
361 ktime_t calltime;
Kevin Cernekee0702d9ee2010-09-20 22:32:10 +0200362 u64 usecs64;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100363 int usecs;
364
365 calltime = ktime_get();
366 usecs64 = ktime_to_ns(ktime_sub(calltime, starttime));
367 do_div(usecs64, NSEC_PER_USEC);
368 usecs = usecs64;
369 if (usecs == 0)
370 usecs = 1;
371 pr_info("PM: %s%s%s of devices complete after %ld.%03ld msecs\n",
372 info ?: "", info ? " " : "", pm_verb(state.event),
373 usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
374}
375
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100376static int dpm_run_callback(pm_callback_t cb, struct device *dev,
377 pm_message_t state, char *info)
378{
379 ktime_t calltime;
380 int error;
381
382 if (!cb)
383 return 0;
384
385 calltime = initcall_debug_start(dev);
386
387 pm_dev_dbg(dev, state, info);
Todd E Brandte8bca472014-06-10 07:31:22 -0700388 trace_device_pm_callback_start(dev, info, state.event);
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100389 error = cb(dev);
Todd E Brandte8bca472014-06-10 07:31:22 -0700390 trace_device_pm_callback_end(dev, error);
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100391 suspend_report_result(cb, error);
392
Shuah Khan53644672013-07-26 13:30:20 -0600393 initcall_debug_report(dev, calltime, error, state, info);
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100394
395 return error;
396}
397
Benoit Goby70fea602013-10-17 10:48:46 -0700398#ifdef CONFIG_DPM_WATCHDOG
399struct dpm_watchdog {
400 struct device *dev;
401 struct task_struct *tsk;
402 struct timer_list timer;
403};
404
405#define DECLARE_DPM_WATCHDOG_ON_STACK(wd) \
406 struct dpm_watchdog wd
407
408/**
409 * dpm_watchdog_handler - Driver suspend / resume watchdog handler.
410 * @data: Watchdog object address.
411 *
412 * Called when a driver has timed out suspending or resuming.
413 * There's not much we can do here to recover so panic() to
414 * capture a crash-dump in pstore.
415 */
416static void dpm_watchdog_handler(unsigned long data)
417{
418 struct dpm_watchdog *wd = (void *)data;
419
420 dev_emerg(wd->dev, "**** DPM device timeout ****\n");
421 show_stack(wd->tsk, NULL);
422 panic("%s %s: unrecoverable failure\n",
423 dev_driver_string(wd->dev), dev_name(wd->dev));
424}
425
426/**
427 * dpm_watchdog_set - Enable pm watchdog for given device.
428 * @wd: Watchdog. Must be allocated on the stack.
429 * @dev: Device to handle.
430 */
431static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev)
432{
433 struct timer_list *timer = &wd->timer;
434
435 wd->dev = dev;
436 wd->tsk = current;
437
438 init_timer_on_stack(timer);
439 /* use same timeout value for both suspend and resume */
440 timer->expires = jiffies + HZ * CONFIG_DPM_WATCHDOG_TIMEOUT;
441 timer->function = dpm_watchdog_handler;
442 timer->data = (unsigned long)wd;
443 add_timer(timer);
444}
445
446/**
447 * dpm_watchdog_clear - Disable suspend/resume watchdog.
448 * @wd: Watchdog to disable.
449 */
450static void dpm_watchdog_clear(struct dpm_watchdog *wd)
451{
452 struct timer_list *timer = &wd->timer;
453
454 del_timer_sync(timer);
455 destroy_timer_on_stack(timer);
456}
457#else
458#define DECLARE_DPM_WATCHDOG_ON_STACK(wd)
459#define dpm_watchdog_set(x, y)
460#define dpm_watchdog_clear(x)
461#endif
462
Alan Sterncd59abf2007-09-21 15:36:56 -0400463/*------------------------- Resume routines -------------------------*/
464
465/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200466 * device_resume_noirq - Execute an "early resume" callback for given device.
467 * @dev: Device to handle.
468 * @state: PM transition of the system being carried out.
Randy Dunlap58c256a2014-07-27 16:17:15 -0700469 * @async: If true, the device is being resumed asynchronously.
Alan Sterncd59abf2007-09-21 15:36:56 -0400470 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200471 * The driver of @dev will not receive interrupts while this function is being
472 * executed.
Alan Sterncd59abf2007-09-21 15:36:56 -0400473 */
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800474static int device_resume_noirq(struct device *dev, pm_message_t state, bool async)
Alan Sterncd59abf2007-09-21 15:36:56 -0400475{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100476 pm_callback_t callback = NULL;
477 char *info = NULL;
Alan Sterncd59abf2007-09-21 15:36:56 -0400478 int error = 0;
479
480 TRACE_DEVICE(dev);
481 TRACE_RESUME(0);
482
Rafael J. Wysockiaae45182014-05-16 02:46:50 +0200483 if (dev->power.syscore || dev->power.direct_complete)
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200484 goto Out;
485
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800486 if (!dev->power.is_noirq_suspended)
487 goto Out;
488
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800489 dpm_wait(dev->parent, async);
490
Rafael J. Wysocki564b9052011-06-23 01:52:55 +0200491 if (dev->pm_domain) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100492 info = "noirq power domain ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100493 callback = pm_noirq_op(&dev->pm_domain->ops, state);
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200494 } else if (dev->type && dev->type->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100495 info = "noirq type ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100496 callback = pm_noirq_op(dev->type->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100497 } else if (dev->class && dev->class->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100498 info = "noirq class ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100499 callback = pm_noirq_op(dev->class->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100500 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100501 info = "noirq bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100502 callback = pm_noirq_op(dev->bus->pm, state);
Dominik Brodowskie7176a32010-03-15 21:43:11 +0100503 }
504
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100505 if (!callback && dev->driver && dev->driver->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100506 info = "noirq driver ";
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100507 callback = pm_noirq_op(dev->driver->pm, state);
508 }
509
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100510 error = dpm_run_callback(callback, dev, state, info);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800511 dev->power.is_noirq_suspended = false;
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100512
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200513 Out:
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800514 complete_all(&dev->power.completion);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100515 TRACE_RESUME(error);
516 return error;
517}
518
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800519static bool is_async(struct device *dev)
520{
521 return dev->power.async_suspend && pm_async_enabled
522 && !pm_trace_is_enabled();
523}
524
525static void async_resume_noirq(void *data, async_cookie_t cookie)
526{
527 struct device *dev = (struct device *)data;
528 int error;
529
530 error = device_resume_noirq(dev, pm_transition, true);
531 if (error)
532 pm_dev_err(dev, pm_transition, " async", error);
533
534 put_device(dev);
535}
536
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100537/**
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100538 * dpm_resume_noirq - Execute "noirq resume" callbacks for all devices.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200539 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100540 *
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100541 * Call the "noirq" resume handlers for all devices in dpm_noirq_list and
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200542 * enable device drivers to receive interrupts.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100543 */
Rafael J. Wysocki2a8a8ce2014-09-30 02:21:34 +0200544void dpm_resume_noirq(pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100545{
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800546 struct device *dev;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100547 ktime_t starttime = ktime_get();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100548
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700549 trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, true);
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200550 mutex_lock(&dpm_list_mtx);
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800551 pm_transition = state;
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100552
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800553 /*
554 * Advanced the async threads upfront,
555 * in case the starting of async threads is
556 * delayed by non-async resuming devices.
557 */
558 list_for_each_entry(dev, &dpm_noirq_list, power.entry) {
559 reinit_completion(&dev->power.completion);
560 if (is_async(dev)) {
561 get_device(dev);
562 async_schedule(async_resume_noirq, dev);
563 }
564 }
565
566 while (!list_empty(&dpm_noirq_list)) {
567 dev = to_device(dpm_noirq_list.next);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100568 get_device(dev);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100569 list_move_tail(&dev->power.entry, &dpm_late_early_list);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100570 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100571
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800572 if (!is_async(dev)) {
573 int error;
574
575 error = device_resume_noirq(dev, state, false);
576 if (error) {
577 suspend_stats.failed_resume_noirq++;
578 dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
579 dpm_save_failed_dev(dev_name(dev));
580 pm_dev_err(dev, state, " noirq", error);
581 }
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100582 }
583
584 mutex_lock(&dpm_list_mtx);
585 put_device(dev);
586 }
587 mutex_unlock(&dpm_list_mtx);
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800588 async_synchronize_full();
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100589 dpm_show_time(starttime, state, "noirq");
590 resume_device_irqs();
Tony Lindgren4990d4f2015-05-18 15:40:29 -0700591 device_wakeup_disarm_wake_irqs();
Preeti U Murthy8651f972012-07-09 10:12:56 +0200592 cpuidle_resume();
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700593 trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, false);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100594}
595
596/**
597 * device_resume_early - Execute an "early resume" callback for given device.
598 * @dev: Device to handle.
599 * @state: PM transition of the system being carried out.
Randy Dunlap58c256a2014-07-27 16:17:15 -0700600 * @async: If true, the device is being resumed asynchronously.
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100601 *
602 * Runtime PM is disabled for @dev while this function is being executed.
603 */
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800604static int device_resume_early(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100605{
606 pm_callback_t callback = NULL;
607 char *info = NULL;
608 int error = 0;
609
610 TRACE_DEVICE(dev);
611 TRACE_RESUME(0);
612
Rafael J. Wysockiaae45182014-05-16 02:46:50 +0200613 if (dev->power.syscore || dev->power.direct_complete)
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200614 goto Out;
615
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800616 if (!dev->power.is_late_suspended)
617 goto Out;
618
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800619 dpm_wait(dev->parent, async);
620
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100621 if (dev->pm_domain) {
622 info = "early power domain ";
623 callback = pm_late_early_op(&dev->pm_domain->ops, state);
624 } else if (dev->type && dev->type->pm) {
625 info = "early type ";
626 callback = pm_late_early_op(dev->type->pm, state);
627 } else if (dev->class && dev->class->pm) {
628 info = "early class ";
629 callback = pm_late_early_op(dev->class->pm, state);
630 } else if (dev->bus && dev->bus->pm) {
631 info = "early bus ";
632 callback = pm_late_early_op(dev->bus->pm, state);
633 }
634
635 if (!callback && dev->driver && dev->driver->pm) {
636 info = "early driver ";
637 callback = pm_late_early_op(dev->driver->pm, state);
638 }
639
640 error = dpm_run_callback(callback, dev, state, info);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800641 dev->power.is_late_suspended = false;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100642
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200643 Out:
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100644 TRACE_RESUME(error);
Rafael J. Wysocki9f6d8f62012-12-22 23:59:01 +0100645
646 pm_runtime_enable(dev);
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800647 complete_all(&dev->power.completion);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100648 return error;
649}
650
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800651static void async_resume_early(void *data, async_cookie_t cookie)
652{
653 struct device *dev = (struct device *)data;
654 int error;
655
656 error = device_resume_early(dev, pm_transition, true);
657 if (error)
658 pm_dev_err(dev, pm_transition, " async", error);
659
660 put_device(dev);
661}
662
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100663/**
664 * dpm_resume_early - Execute "early resume" callbacks for all devices.
665 * @state: PM transition of the system being carried out.
666 */
Rafael J. Wysocki2a8a8ce2014-09-30 02:21:34 +0200667void dpm_resume_early(pm_message_t state)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100668{
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800669 struct device *dev;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100670 ktime_t starttime = ktime_get();
671
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700672 trace_suspend_resume(TPS("dpm_resume_early"), state.event, true);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100673 mutex_lock(&dpm_list_mtx);
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800674 pm_transition = state;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100675
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800676 /*
677 * Advanced the async threads upfront,
678 * in case the starting of async threads is
679 * delayed by non-async resuming devices.
680 */
681 list_for_each_entry(dev, &dpm_late_early_list, power.entry) {
682 reinit_completion(&dev->power.completion);
683 if (is_async(dev)) {
684 get_device(dev);
685 async_schedule(async_resume_early, dev);
686 }
687 }
688
689 while (!list_empty(&dpm_late_early_list)) {
690 dev = to_device(dpm_late_early_list.next);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100691 get_device(dev);
692 list_move_tail(&dev->power.entry, &dpm_suspended_list);
693 mutex_unlock(&dpm_list_mtx);
694
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800695 if (!is_async(dev)) {
696 int error;
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100697
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800698 error = device_resume_early(dev, state, false);
699 if (error) {
700 suspend_stats.failed_resume_early++;
701 dpm_save_failed_step(SUSPEND_RESUME_EARLY);
702 dpm_save_failed_dev(dev_name(dev));
703 pm_dev_err(dev, state, " early", error);
704 }
705 }
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100706 mutex_lock(&dpm_list_mtx);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100707 put_device(dev);
708 }
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200709 mutex_unlock(&dpm_list_mtx);
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800710 async_synchronize_full();
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100711 dpm_show_time(starttime, state, "early");
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700712 trace_suspend_resume(TPS("dpm_resume_early"), state.event, false);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100713}
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100714
715/**
716 * dpm_resume_start - Execute "noirq" and "early" device callbacks.
717 * @state: PM transition of the system being carried out.
718 */
719void dpm_resume_start(pm_message_t state)
720{
721 dpm_resume_noirq(state);
722 dpm_resume_early(state);
723}
724EXPORT_SYMBOL_GPL(dpm_resume_start);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100725
726/**
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100727 * device_resume - Execute "resume" callbacks for given device.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200728 * @dev: Device to handle.
729 * @state: PM transition of the system being carried out.
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100730 * @async: If true, the device is being resumed asynchronously.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100731 */
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100732static int device_resume(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100733{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100734 pm_callback_t callback = NULL;
735 char *info = NULL;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100736 int error = 0;
Benoit Goby70fea602013-10-17 10:48:46 -0700737 DECLARE_DPM_WATCHDOG_ON_STACK(wd);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100738
739 TRACE_DEVICE(dev);
740 TRACE_RESUME(0);
Alan Sterncd59abf2007-09-21 15:36:56 -0400741
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200742 if (dev->power.syscore)
743 goto Complete;
744
Rafael J. Wysockiaae45182014-05-16 02:46:50 +0200745 if (dev->power.direct_complete) {
746 /* Match the pm_runtime_disable() in __device_suspend(). */
747 pm_runtime_enable(dev);
748 goto Complete;
749 }
750
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100751 dpm_wait(dev->parent, async);
Benoit Goby70fea602013-10-17 10:48:46 -0700752 dpm_watchdog_set(&wd, dev);
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800753 device_lock(dev);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100754
Alan Sternf76b168b2011-06-18 20:22:23 +0200755 /*
756 * This is a fib. But we'll allow new children to be added below
757 * a resumed device, even if the device hasn't been completed yet.
758 */
759 dev->power.is_prepared = false;
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100760
Alan Stern6d0e0e82011-06-18 22:42:09 +0200761 if (!dev->power.is_suspended)
762 goto Unlock;
763
Rafael J. Wysocki564b9052011-06-23 01:52:55 +0200764 if (dev->pm_domain) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100765 info = "power domain ";
766 callback = pm_op(&dev->pm_domain->ops, state);
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100767 goto Driver;
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +0100768 }
769
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100770 if (dev->type && dev->type->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100771 info = "type ";
772 callback = pm_op(dev->type->pm, state);
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100773 goto Driver;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100774 }
775
776 if (dev->class) {
777 if (dev->class->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100778 info = "class ";
779 callback = pm_op(dev->class->pm, state);
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100780 goto Driver;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100781 } else if (dev->class->resume) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100782 info = "legacy class ";
783 callback = dev->class->resume;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100784 goto End;
785 }
786 }
787
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200788 if (dev->bus) {
789 if (dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100790 info = "bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100791 callback = pm_op(dev->bus->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200792 } else if (dev->bus->resume) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100793 info = "legacy bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100794 callback = dev->bus->resume;
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100795 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200796 }
Alan Sterncd59abf2007-09-21 15:36:56 -0400797 }
798
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100799 Driver:
800 if (!callback && dev->driver && dev->driver->pm) {
801 info = "driver ";
802 callback = pm_op(dev->driver->pm, state);
803 }
804
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200805 End:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100806 error = dpm_run_callback(callback, dev, state, info);
Alan Stern6d0e0e82011-06-18 22:42:09 +0200807 dev->power.is_suspended = false;
808
809 Unlock:
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800810 device_unlock(dev);
Benoit Goby70fea602013-10-17 10:48:46 -0700811 dpm_watchdog_clear(&wd);
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200812
813 Complete:
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100814 complete_all(&dev->power.completion);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100815
Alan Sterncd59abf2007-09-21 15:36:56 -0400816 TRACE_RESUME(error);
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +0200817
Alan Sterncd59abf2007-09-21 15:36:56 -0400818 return error;
819}
820
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100821static void async_resume(void *data, async_cookie_t cookie)
822{
823 struct device *dev = (struct device *)data;
824 int error;
825
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100826 error = device_resume(dev, pm_transition, true);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100827 if (error)
828 pm_dev_err(dev, pm_transition, " async", error);
829 put_device(dev);
830}
831
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100832/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200833 * dpm_resume - Execute "resume" callbacks for non-sysdev devices.
834 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100835 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200836 * Execute the appropriate "resume" callback for all devices whose status
837 * indicates that they are suspended.
Alan Sterncd59abf2007-09-21 15:36:56 -0400838 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200839void dpm_resume(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400840{
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100841 struct device *dev;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100842 ktime_t starttime = ktime_get();
Alan Sterncd59abf2007-09-21 15:36:56 -0400843
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700844 trace_suspend_resume(TPS("dpm_resume"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200845 might_sleep();
846
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200847 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100848 pm_transition = state;
Rafael J. Wysocki098dff72010-09-22 22:10:57 +0200849 async_error = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200850
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100851 list_for_each_entry(dev, &dpm_suspended_list, power.entry) {
Wolfram Sang16735d02013-11-14 14:32:02 -0800852 reinit_completion(&dev->power.completion);
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100853 if (is_async(dev)) {
854 get_device(dev);
855 async_schedule(async_resume, dev);
856 }
857 }
858
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100859 while (!list_empty(&dpm_suspended_list)) {
860 dev = to_device(dpm_suspended_list.next);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200861 get_device(dev);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100862 if (!is_async(dev)) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200863 int error;
864
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200865 mutex_unlock(&dpm_list_mtx);
866
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100867 error = device_resume(dev, state, false);
ShuoX Liu2a77c462011-08-10 23:01:26 +0200868 if (error) {
869 suspend_stats.failed_resume++;
870 dpm_save_failed_step(SUSPEND_RESUME);
871 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200872 pm_dev_err(dev, state, "", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +0200873 }
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100874
875 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200876 }
877 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100878 list_move_tail(&dev->power.entry, &dpm_prepared_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200879 put_device(dev);
Alan Sterncd59abf2007-09-21 15:36:56 -0400880 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200881 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100882 async_synchronize_full();
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100883 dpm_show_time(starttime, state, NULL);
Viresh Kumar2f0aea92014-03-04 11:00:26 +0800884
885 cpufreq_resume();
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700886 trace_suspend_resume(TPS("dpm_resume"), state.event, false);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200887}
888
889/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200890 * device_complete - Complete a PM transition for given device.
891 * @dev: Device to handle.
892 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200893 */
Alan Sternd1616302009-05-24 22:05:42 +0200894static void device_complete(struct device *dev, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200895{
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100896 void (*callback)(struct device *) = NULL;
897 char *info = NULL;
898
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200899 if (dev->power.syscore)
900 return;
901
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800902 device_lock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200903
Rafael J. Wysocki564b9052011-06-23 01:52:55 +0200904 if (dev->pm_domain) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100905 info = "completing power domain ";
906 callback = dev->pm_domain->ops.complete;
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200907 } else if (dev->type && dev->type->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100908 info = "completing type ";
909 callback = dev->type->pm->complete;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100910 } else if (dev->class && dev->class->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100911 info = "completing class ";
912 callback = dev->class->pm->complete;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100913 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100914 info = "completing bus ";
915 callback = dev->bus->pm->complete;
916 }
917
918 if (!callback && dev->driver && dev->driver->pm) {
919 info = "completing driver ";
920 callback = dev->driver->pm->complete;
921 }
922
923 if (callback) {
924 pm_dev_dbg(dev, state, info);
Todd E Brandte8bca472014-06-10 07:31:22 -0700925 trace_device_pm_callback_start(dev, info, state.event);
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100926 callback(dev);
Todd E Brandte8bca472014-06-10 07:31:22 -0700927 trace_device_pm_callback_end(dev, 0);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200928 }
929
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800930 device_unlock(dev);
Alan Stern88d26132012-09-19 21:59:02 +0200931
Ulf Hanssonaf939332013-04-12 09:41:06 +0000932 pm_runtime_put(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200933}
934
935/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200936 * dpm_complete - Complete a PM transition for all non-sysdev devices.
937 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200938 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200939 * Execute the ->complete() callbacks for all devices whose PM status is not
940 * DPM_ON (this allows new devices to be registered).
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200941 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200942void dpm_complete(pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200943{
944 struct list_head list;
945
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700946 trace_suspend_resume(TPS("dpm_complete"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200947 might_sleep();
948
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200949 INIT_LIST_HEAD(&list);
950 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100951 while (!list_empty(&dpm_prepared_list)) {
952 struct device *dev = to_device(dpm_prepared_list.prev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200953
954 get_device(dev);
Alan Sternf76b168b2011-06-18 20:22:23 +0200955 dev->power.is_prepared = false;
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100956 list_move(&dev->power.entry, &list);
957 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200958
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100959 device_complete(dev, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200960
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100961 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200962 put_device(dev);
963 }
964 list_splice(&list, &dpm_list);
Alan Sterncd59abf2007-09-21 15:36:56 -0400965 mutex_unlock(&dpm_list_mtx);
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700966 trace_suspend_resume(TPS("dpm_complete"), state.event, false);
Alan Sterncd59abf2007-09-21 15:36:56 -0400967}
968
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100969/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200970 * dpm_resume_end - Execute "resume" callbacks and complete system transition.
971 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -0400972 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200973 * Execute "resume" callbacks for all devices and complete the PM transition of
974 * the system.
Alan Sterncd59abf2007-09-21 15:36:56 -0400975 */
Alan Sternd1616302009-05-24 22:05:42 +0200976void dpm_resume_end(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400977{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200978 dpm_resume(state);
979 dpm_complete(state);
Alan Sterncd59abf2007-09-21 15:36:56 -0400980}
Alan Sternd1616302009-05-24 22:05:42 +0200981EXPORT_SYMBOL_GPL(dpm_resume_end);
Alan Sterncd59abf2007-09-21 15:36:56 -0400982
983
Alan Sterncd59abf2007-09-21 15:36:56 -0400984/*------------------------- Suspend routines -------------------------*/
985
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200986/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200987 * resume_event - Return a "resume" message for given "suspend" sleep state.
988 * @sleep_state: PM message representing a sleep state.
989 *
990 * Return a PM message representing the resume event corresponding to given
991 * sleep state.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200992 */
993static pm_message_t resume_event(pm_message_t sleep_state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400994{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200995 switch (sleep_state.event) {
996 case PM_EVENT_SUSPEND:
997 return PMSG_RESUME;
998 case PM_EVENT_FREEZE:
999 case PM_EVENT_QUIESCE:
1000 return PMSG_RECOVER;
1001 case PM_EVENT_HIBERNATE:
1002 return PMSG_RESTORE;
Alan Sterncd59abf2007-09-21 15:36:56 -04001003 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001004 return PMSG_ON;
Alan Sterncd59abf2007-09-21 15:36:56 -04001005}
1006
1007/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001008 * device_suspend_noirq - Execute a "late suspend" callback for given device.
1009 * @dev: Device to handle.
1010 * @state: PM transition of the system being carried out.
Randy Dunlap58c256a2014-07-27 16:17:15 -07001011 * @async: If true, the device is being suspended asynchronously.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001012 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001013 * The driver of @dev will not receive interrupts while this function is being
1014 * executed.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001015 */
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001016static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001017{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001018 pm_callback_t callback = NULL;
1019 char *info = NULL;
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001020 int error = 0;
1021
Zhonghui Fu431d4522015-03-18 15:54:27 +01001022 TRACE_DEVICE(dev);
1023 TRACE_SUSPEND(0);
1024
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001025 if (async_error)
1026 goto Complete;
1027
1028 if (pm_wakeup_pending()) {
1029 async_error = -EBUSY;
1030 goto Complete;
1031 }
Dominik Brodowskie7176a32010-03-15 21:43:11 +01001032
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001033 if (dev->power.syscore || dev->power.direct_complete)
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001034 goto Complete;
1035
1036 dpm_wait_for_children(dev, async);
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001037
Rafael J. Wysocki564b9052011-06-23 01:52:55 +02001038 if (dev->pm_domain) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001039 info = "noirq power domain ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001040 callback = pm_noirq_op(&dev->pm_domain->ops, state);
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001041 } else if (dev->type && dev->type->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001042 info = "noirq type ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001043 callback = pm_noirq_op(dev->type->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001044 } else if (dev->class && dev->class->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001045 info = "noirq class ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001046 callback = pm_noirq_op(dev->class->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001047 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001048 info = "noirq bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001049 callback = pm_noirq_op(dev->bus->pm, state);
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001050 }
1051
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001052 if (!callback && dev->driver && dev->driver->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001053 info = "noirq driver ";
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001054 callback = pm_noirq_op(dev->driver->pm, state);
1055 }
1056
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001057 error = dpm_run_callback(callback, dev, state, info);
1058 if (!error)
1059 dev->power.is_noirq_suspended = true;
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001060 else
1061 async_error = error;
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001062
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001063Complete:
1064 complete_all(&dev->power.completion);
Zhonghui Fu431d4522015-03-18 15:54:27 +01001065 TRACE_SUSPEND(error);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001066 return error;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001067}
1068
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001069static void async_suspend_noirq(void *data, async_cookie_t cookie)
1070{
1071 struct device *dev = (struct device *)data;
1072 int error;
1073
1074 error = __device_suspend_noirq(dev, pm_transition, true);
1075 if (error) {
1076 dpm_save_failed_dev(dev_name(dev));
1077 pm_dev_err(dev, pm_transition, " async", error);
1078 }
1079
1080 put_device(dev);
1081}
1082
1083static int device_suspend_noirq(struct device *dev)
1084{
1085 reinit_completion(&dev->power.completion);
1086
Zhonghui Fu431d4522015-03-18 15:54:27 +01001087 if (is_async(dev)) {
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001088 get_device(dev);
1089 async_schedule(async_suspend_noirq, dev);
1090 return 0;
1091 }
1092 return __device_suspend_noirq(dev, pm_transition, false);
1093}
1094
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001095/**
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001096 * dpm_suspend_noirq - Execute "noirq suspend" callbacks for all devices.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001097 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001098 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001099 * Prevent device drivers from receiving interrupts and call the "noirq" suspend
1100 * handlers for all non-sysdev devices.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001101 */
Rafael J. Wysocki2a8a8ce2014-09-30 02:21:34 +02001102int dpm_suspend_noirq(pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001103{
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001104 ktime_t starttime = ktime_get();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001105 int error = 0;
1106
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001107 trace_suspend_resume(TPS("dpm_suspend_noirq"), state.event, true);
Preeti U Murthy8651f972012-07-09 10:12:56 +02001108 cpuidle_pause();
Tony Lindgren4990d4f2015-05-18 15:40:29 -07001109 device_wakeup_arm_wake_irqs();
Rafael J. Wysocki2ed8d2b32009-03-16 22:34:06 +01001110 suspend_device_irqs();
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +02001111 mutex_lock(&dpm_list_mtx);
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001112 pm_transition = state;
1113 async_error = 0;
1114
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001115 while (!list_empty(&dpm_late_early_list)) {
1116 struct device *dev = to_device(dpm_late_early_list.prev);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001117
1118 get_device(dev);
1119 mutex_unlock(&dpm_list_mtx);
1120
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001121 error = device_suspend_noirq(dev);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001122
1123 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001124 if (error) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001125 pm_dev_err(dev, state, " noirq", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001126 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001127 put_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001128 break;
1129 }
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001130 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001131 list_move(&dev->power.entry, &dpm_noirq_list);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001132 put_device(dev);
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001133
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001134 if (async_error)
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001135 break;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001136 }
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +02001137 mutex_unlock(&dpm_list_mtx);
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001138 async_synchronize_full();
1139 if (!error)
1140 error = async_error;
1141
1142 if (error) {
1143 suspend_stats.failed_suspend_noirq++;
1144 dpm_save_failed_step(SUSPEND_SUSPEND_NOIRQ);
Alan Sternd1616302009-05-24 22:05:42 +02001145 dpm_resume_noirq(resume_event(state));
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001146 } else {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001147 dpm_show_time(starttime, state, "noirq");
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001148 }
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001149 trace_suspend_resume(TPS("dpm_suspend_noirq"), state.event, false);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001150 return error;
1151}
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001152
1153/**
1154 * device_suspend_late - Execute a "late suspend" callback for given device.
1155 * @dev: Device to handle.
1156 * @state: PM transition of the system being carried out.
Randy Dunlap58c256a2014-07-27 16:17:15 -07001157 * @async: If true, the device is being suspended asynchronously.
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001158 *
1159 * Runtime PM is disabled for @dev while this function is being executed.
1160 */
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001161static int __device_suspend_late(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001162{
1163 pm_callback_t callback = NULL;
1164 char *info = NULL;
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001165 int error = 0;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001166
Zhonghui Fu431d4522015-03-18 15:54:27 +01001167 TRACE_DEVICE(dev);
1168 TRACE_SUSPEND(0);
1169
Rafael J. Wysocki9f6d8f62012-12-22 23:59:01 +01001170 __pm_runtime_disable(dev, false);
1171
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001172 if (async_error)
1173 goto Complete;
1174
1175 if (pm_wakeup_pending()) {
1176 async_error = -EBUSY;
1177 goto Complete;
1178 }
1179
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001180 if (dev->power.syscore || dev->power.direct_complete)
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001181 goto Complete;
1182
1183 dpm_wait_for_children(dev, async);
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001184
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001185 if (dev->pm_domain) {
1186 info = "late power domain ";
1187 callback = pm_late_early_op(&dev->pm_domain->ops, state);
1188 } else if (dev->type && dev->type->pm) {
1189 info = "late type ";
1190 callback = pm_late_early_op(dev->type->pm, state);
1191 } else if (dev->class && dev->class->pm) {
1192 info = "late class ";
1193 callback = pm_late_early_op(dev->class->pm, state);
1194 } else if (dev->bus && dev->bus->pm) {
1195 info = "late bus ";
1196 callback = pm_late_early_op(dev->bus->pm, state);
1197 }
1198
1199 if (!callback && dev->driver && dev->driver->pm) {
1200 info = "late driver ";
1201 callback = pm_late_early_op(dev->driver->pm, state);
1202 }
1203
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001204 error = dpm_run_callback(callback, dev, state, info);
1205 if (!error)
1206 dev->power.is_late_suspended = true;
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001207 else
1208 async_error = error;
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001209
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001210Complete:
Zhonghui Fu431d4522015-03-18 15:54:27 +01001211 TRACE_SUSPEND(error);
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001212 complete_all(&dev->power.completion);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001213 return error;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001214}
1215
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001216static void async_suspend_late(void *data, async_cookie_t cookie)
1217{
1218 struct device *dev = (struct device *)data;
1219 int error;
1220
1221 error = __device_suspend_late(dev, pm_transition, true);
1222 if (error) {
1223 dpm_save_failed_dev(dev_name(dev));
1224 pm_dev_err(dev, pm_transition, " async", error);
1225 }
1226 put_device(dev);
1227}
1228
1229static int device_suspend_late(struct device *dev)
1230{
1231 reinit_completion(&dev->power.completion);
1232
Zhonghui Fu431d4522015-03-18 15:54:27 +01001233 if (is_async(dev)) {
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001234 get_device(dev);
1235 async_schedule(async_suspend_late, dev);
1236 return 0;
1237 }
1238
1239 return __device_suspend_late(dev, pm_transition, false);
1240}
1241
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001242/**
1243 * dpm_suspend_late - Execute "late suspend" callbacks for all devices.
1244 * @state: PM transition of the system being carried out.
1245 */
Rafael J. Wysocki2a8a8ce2014-09-30 02:21:34 +02001246int dpm_suspend_late(pm_message_t state)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001247{
1248 ktime_t starttime = ktime_get();
1249 int error = 0;
1250
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001251 trace_suspend_resume(TPS("dpm_suspend_late"), state.event, true);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001252 mutex_lock(&dpm_list_mtx);
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001253 pm_transition = state;
1254 async_error = 0;
1255
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001256 while (!list_empty(&dpm_suspended_list)) {
1257 struct device *dev = to_device(dpm_suspended_list.prev);
1258
1259 get_device(dev);
1260 mutex_unlock(&dpm_list_mtx);
1261
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001262 error = device_suspend_late(dev);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001263
1264 mutex_lock(&dpm_list_mtx);
1265 if (error) {
1266 pm_dev_err(dev, state, " late", error);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001267 dpm_save_failed_dev(dev_name(dev));
1268 put_device(dev);
1269 break;
1270 }
1271 if (!list_empty(&dev->power.entry))
1272 list_move(&dev->power.entry, &dpm_late_early_list);
1273 put_device(dev);
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001274
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001275 if (async_error)
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001276 break;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001277 }
1278 mutex_unlock(&dpm_list_mtx);
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001279 async_synchronize_full();
Imre Deak246ef762014-10-24 20:29:09 +03001280 if (!error)
1281 error = async_error;
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001282 if (error) {
1283 suspend_stats.failed_suspend_late++;
1284 dpm_save_failed_step(SUSPEND_SUSPEND_LATE);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001285 dpm_resume_early(resume_event(state));
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001286 } else {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001287 dpm_show_time(starttime, state, "late");
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001288 }
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001289 trace_suspend_resume(TPS("dpm_suspend_late"), state.event, false);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001290 return error;
1291}
1292
1293/**
1294 * dpm_suspend_end - Execute "late" and "noirq" device suspend callbacks.
1295 * @state: PM transition of the system being carried out.
1296 */
1297int dpm_suspend_end(pm_message_t state)
1298{
1299 int error = dpm_suspend_late(state);
Colin Cross064b0212012-07-19 10:38:06 +02001300 if (error)
1301 return error;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001302
Colin Cross064b0212012-07-19 10:38:06 +02001303 error = dpm_suspend_noirq(state);
1304 if (error) {
Feng Hong997a0312012-09-19 14:16:00 +02001305 dpm_resume_early(resume_event(state));
Colin Cross064b0212012-07-19 10:38:06 +02001306 return error;
1307 }
1308
1309 return 0;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001310}
1311EXPORT_SYMBOL_GPL(dpm_suspend_end);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001312
1313/**
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001314 * legacy_suspend - Execute a legacy (bus or class) suspend callback for device.
Randy Dunlap0a884222010-01-08 14:42:57 -08001315 * @dev: Device to suspend.
1316 * @state: PM transition of the system being carried out.
1317 * @cb: Suspend callback to execute.
Randy Dunlap58c256a2014-07-27 16:17:15 -07001318 * @info: string description of caller.
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001319 */
1320static int legacy_suspend(struct device *dev, pm_message_t state,
Shuah Khan53644672013-07-26 13:30:20 -06001321 int (*cb)(struct device *dev, pm_message_t state),
1322 char *info)
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001323{
1324 int error;
1325 ktime_t calltime;
1326
1327 calltime = initcall_debug_start(dev);
1328
Todd E Brandte8bca472014-06-10 07:31:22 -07001329 trace_device_pm_callback_start(dev, info, state.event);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001330 error = cb(dev, state);
Todd E Brandte8bca472014-06-10 07:31:22 -07001331 trace_device_pm_callback_end(dev, error);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001332 suspend_report_result(cb, error);
1333
Shuah Khan53644672013-07-26 13:30:20 -06001334 initcall_debug_report(dev, calltime, error, state, info);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001335
1336 return error;
1337}
1338
1339/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001340 * device_suspend - Execute "suspend" callbacks for given device.
1341 * @dev: Device to handle.
1342 * @state: PM transition of the system being carried out.
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001343 * @async: If true, the device is being suspended asynchronously.
Alan Sterncd59abf2007-09-21 15:36:56 -04001344 */
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001345static int __device_suspend(struct device *dev, pm_message_t state, bool async)
Alan Sterncd59abf2007-09-21 15:36:56 -04001346{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001347 pm_callback_t callback = NULL;
1348 char *info = NULL;
Alan Sterncd59abf2007-09-21 15:36:56 -04001349 int error = 0;
Benoit Goby70fea602013-10-17 10:48:46 -07001350 DECLARE_DPM_WATCHDOG_ON_STACK(wd);
Alan Sterncd59abf2007-09-21 15:36:56 -04001351
Zhonghui Fu431d4522015-03-18 15:54:27 +01001352 TRACE_DEVICE(dev);
1353 TRACE_SUSPEND(0);
1354
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001355 dpm_wait_for_children(dev, async);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +01001356
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001357 if (async_error)
Mandeep Singh Baines1f758b22012-06-24 23:31:09 +02001358 goto Complete;
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001359
Alan Stern88d26132012-09-19 21:59:02 +02001360 /*
1361 * If a device configured to wake up the system from sleep states
1362 * has been suspended at run time and there's a resume request pending
1363 * for it, this is equivalent to the device signaling wakeup, so the
1364 * system suspend operation should be aborted.
1365 */
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001366 if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
1367 pm_wakeup_event(dev, 0);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001368
Rafael J. Wysockid83f9052010-12-03 23:14:26 +01001369 if (pm_wakeup_pending()) {
1370 async_error = -EBUSY;
Mandeep Singh Baines1f758b22012-06-24 23:31:09 +02001371 goto Complete;
Rafael J. Wysockid83f9052010-12-03 23:14:26 +01001372 }
1373
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001374 if (dev->power.syscore)
1375 goto Complete;
1376
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001377 if (dev->power.direct_complete) {
1378 if (pm_runtime_status_suspended(dev)) {
1379 pm_runtime_disable(dev);
1380 if (pm_runtime_suspended_if_enabled(dev))
1381 goto Complete;
1382
1383 pm_runtime_enable(dev);
1384 }
1385 dev->power.direct_complete = false;
1386 }
1387
Benoit Goby70fea602013-10-17 10:48:46 -07001388 dpm_watchdog_set(&wd, dev);
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001389 device_lock(dev);
1390
Rafael J. Wysocki564b9052011-06-23 01:52:55 +02001391 if (dev->pm_domain) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001392 info = "power domain ";
1393 callback = pm_op(&dev->pm_domain->ops, state);
1394 goto Run;
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001395 }
1396
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001397 if (dev->type && dev->type->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001398 info = "type ";
1399 callback = pm_op(dev->type->pm, state);
1400 goto Run;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001401 }
1402
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001403 if (dev->class) {
1404 if (dev->class->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001405 info = "class ";
1406 callback = pm_op(dev->class->pm, state);
1407 goto Run;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001408 } else if (dev->class->suspend) {
1409 pm_dev_dbg(dev, state, "legacy class ");
Shuah Khan53644672013-07-26 13:30:20 -06001410 error = legacy_suspend(dev, state, dev->class->suspend,
1411 "legacy class ");
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001412 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001413 }
Alan Sterncd59abf2007-09-21 15:36:56 -04001414 }
1415
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001416 if (dev->bus) {
1417 if (dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001418 info = "bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001419 callback = pm_op(dev->bus->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001420 } else if (dev->bus->suspend) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001421 pm_dev_dbg(dev, state, "legacy bus ");
Shuah Khan53644672013-07-26 13:30:20 -06001422 error = legacy_suspend(dev, state, dev->bus->suspend,
1423 "legacy bus ");
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001424 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001425 }
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001426 }
1427
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001428 Run:
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001429 if (!callback && dev->driver && dev->driver->pm) {
1430 info = "driver ";
1431 callback = pm_op(dev->driver->pm, state);
1432 }
1433
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001434 error = dpm_run_callback(callback, dev, state, info);
1435
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001436 End:
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001437 if (!error) {
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001438 struct device *parent = dev->parent;
1439
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001440 dev->power.is_suspended = true;
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001441 if (parent) {
1442 spin_lock_irq(&parent->power.lock);
1443
1444 dev->parent->power.direct_complete = false;
1445 if (dev->power.wakeup_path
1446 && !dev->parent->power.ignore_children)
1447 dev->parent->power.wakeup_path = true;
1448
1449 spin_unlock_irq(&parent->power.lock);
1450 }
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001451 }
Alan Stern6d0e0e82011-06-18 22:42:09 +02001452
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001453 device_unlock(dev);
Benoit Goby70fea602013-10-17 10:48:46 -07001454 dpm_watchdog_clear(&wd);
Mandeep Singh Baines1f758b22012-06-24 23:31:09 +02001455
1456 Complete:
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001457 complete_all(&dev->power.completion);
Alan Stern88d26132012-09-19 21:59:02 +02001458 if (error)
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001459 async_error = error;
1460
Zhonghui Fu431d4522015-03-18 15:54:27 +01001461 TRACE_SUSPEND(error);
Alan Sterncd59abf2007-09-21 15:36:56 -04001462 return error;
1463}
1464
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001465static void async_suspend(void *data, async_cookie_t cookie)
1466{
1467 struct device *dev = (struct device *)data;
1468 int error;
1469
1470 error = __device_suspend(dev, pm_transition, true);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001471 if (error) {
1472 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001473 pm_dev_err(dev, pm_transition, " async", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001474 }
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001475
1476 put_device(dev);
1477}
1478
1479static int device_suspend(struct device *dev)
1480{
Wolfram Sang16735d02013-11-14 14:32:02 -08001481 reinit_completion(&dev->power.completion);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001482
Zhonghui Fu431d4522015-03-18 15:54:27 +01001483 if (is_async(dev)) {
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001484 get_device(dev);
1485 async_schedule(async_suspend, dev);
1486 return 0;
1487 }
1488
1489 return __device_suspend(dev, pm_transition, false);
1490}
1491
Alan Sterncd59abf2007-09-21 15:36:56 -04001492/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001493 * dpm_suspend - Execute "suspend" callbacks for all non-sysdev devices.
1494 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -04001495 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001496int dpm_suspend(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001497{
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001498 ktime_t starttime = ktime_get();
Alan Sterncd59abf2007-09-21 15:36:56 -04001499 int error = 0;
1500
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001501 trace_suspend_resume(TPS("dpm_suspend"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001502 might_sleep();
1503
Viresh Kumar2f0aea92014-03-04 11:00:26 +08001504 cpufreq_suspend();
1505
Alan Sterncd59abf2007-09-21 15:36:56 -04001506 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001507 pm_transition = state;
1508 async_error = 0;
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001509 while (!list_empty(&dpm_prepared_list)) {
1510 struct device *dev = to_device(dpm_prepared_list.prev);
Alan Sterncd59abf2007-09-21 15:36:56 -04001511
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001512 get_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001513 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001514
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001515 error = device_suspend(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001516
Alan Stern1b3cbec2008-02-29 11:50:22 -05001517 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001518 if (error) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001519 pm_dev_err(dev, state, "", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001520 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001521 put_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001522 break;
1523 }
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +01001524 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001525 list_move(&dev->power.entry, &dpm_suspended_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001526 put_device(dev);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001527 if (async_error)
1528 break;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001529 }
1530 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001531 async_synchronize_full();
1532 if (!error)
1533 error = async_error;
ShuoX Liu2a77c462011-08-10 23:01:26 +02001534 if (error) {
1535 suspend_stats.failed_suspend++;
1536 dpm_save_failed_step(SUSPEND_SUSPEND);
1537 } else
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001538 dpm_show_time(starttime, state, NULL);
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001539 trace_suspend_resume(TPS("dpm_suspend"), state.event, false);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001540 return error;
1541}
1542
1543/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001544 * device_prepare - Prepare a device for system power transition.
1545 * @dev: Device to handle.
1546 * @state: PM transition of the system being carried out.
1547 *
1548 * Execute the ->prepare() callback(s) for given device. No new children of the
1549 * device may be registered after this function has returned.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001550 */
Alan Sternd1616302009-05-24 22:05:42 +02001551static int device_prepare(struct device *dev, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001552{
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001553 int (*callback)(struct device *) = NULL;
1554 char *info = NULL;
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001555 int ret = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001556
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001557 if (dev->power.syscore)
1558 return 0;
1559
Alan Stern88d26132012-09-19 21:59:02 +02001560 /*
1561 * If a device's parent goes into runtime suspend at the wrong time,
1562 * it won't be possible to resume the device. To prevent this we
1563 * block runtime suspend here, during the prepare phase, and allow
1564 * it again during the complete phase.
1565 */
1566 pm_runtime_get_noresume(dev);
1567
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001568 device_lock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001569
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001570 dev->power.wakeup_path = device_may_wakeup(dev);
1571
Rafael J. Wysocki564b9052011-06-23 01:52:55 +02001572 if (dev->pm_domain) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001573 info = "preparing power domain ";
1574 callback = dev->pm_domain->ops.prepare;
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001575 } else if (dev->type && dev->type->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001576 info = "preparing type ";
1577 callback = dev->type->pm->prepare;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001578 } else if (dev->class && dev->class->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001579 info = "preparing class ";
1580 callback = dev->class->pm->prepare;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001581 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001582 info = "preparing bus ";
1583 callback = dev->bus->pm->prepare;
1584 }
1585
1586 if (!callback && dev->driver && dev->driver->pm) {
1587 info = "preparing driver ";
1588 callback = dev->driver->pm->prepare;
1589 }
1590
Todd E Brandte8bca472014-06-10 07:31:22 -07001591 if (callback) {
1592 trace_device_pm_callback_start(dev, info, state.event);
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001593 ret = callback(dev);
Todd E Brandte8bca472014-06-10 07:31:22 -07001594 trace_device_pm_callback_end(dev, ret);
1595 }
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001596
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001597 device_unlock(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001598
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001599 if (ret < 0) {
1600 suspend_report_result(callback, ret);
Ulf Hanssonaa1b9f12013-11-13 15:45:03 +01001601 pm_runtime_put(dev);
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001602 return ret;
1603 }
1604 /*
1605 * A positive return value from ->prepare() means "this device appears
1606 * to be runtime-suspended and its state is fine, so if it really is
1607 * runtime-suspended, you can leave it in that state provided that you
1608 * will do the same thing with all of its descendants". This only
1609 * applies to suspend transitions, however.
1610 */
1611 spin_lock_irq(&dev->power.lock);
1612 dev->power.direct_complete = ret > 0 && state.event == PM_EVENT_SUSPEND;
1613 spin_unlock_irq(&dev->power.lock);
1614 return 0;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001615}
1616
1617/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001618 * dpm_prepare - Prepare all non-sysdev devices for a system PM transition.
1619 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -04001620 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001621 * Execute the ->prepare() callback(s) for all devices.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001622 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001623int dpm_prepare(pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001624{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001625 int error = 0;
1626
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001627 trace_suspend_resume(TPS("dpm_prepare"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001628 might_sleep();
1629
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001630 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001631 while (!list_empty(&dpm_list)) {
1632 struct device *dev = to_device(dpm_list.next);
1633
1634 get_device(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001635 mutex_unlock(&dpm_list_mtx);
1636
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001637 error = device_prepare(dev, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001638
1639 mutex_lock(&dpm_list_mtx);
1640 if (error) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001641 if (error == -EAGAIN) {
1642 put_device(dev);
Sebastian Ott886a7a32009-07-08 13:26:05 +02001643 error = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001644 continue;
1645 }
Rafael J. Wysocki1e752272010-12-03 22:58:05 +01001646 printk(KERN_INFO "PM: Device %s not prepared "
1647 "for power transition: code %d\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +01001648 dev_name(dev), error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001649 put_device(dev);
1650 break;
1651 }
Alan Sternf76b168b2011-06-18 20:22:23 +02001652 dev->power.is_prepared = true;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001653 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001654 list_move_tail(&dev->power.entry, &dpm_prepared_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001655 put_device(dev);
1656 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001657 mutex_unlock(&dpm_list_mtx);
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001658 trace_suspend_resume(TPS("dpm_prepare"), state.event, false);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001659 return error;
1660}
1661
1662/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001663 * dpm_suspend_start - Prepare devices for PM transition and suspend them.
1664 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001665 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001666 * Prepare all non-sysdev devices for system PM transition and execute "suspend"
1667 * callbacks for them.
Alan Sterncd59abf2007-09-21 15:36:56 -04001668 */
Alan Sternd1616302009-05-24 22:05:42 +02001669int dpm_suspend_start(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001670{
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001671 int error;
Alan Sterncd59abf2007-09-21 15:36:56 -04001672
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001673 error = dpm_prepare(state);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001674 if (error) {
1675 suspend_stats.failed_prepare++;
1676 dpm_save_failed_step(SUSPEND_PREPARE);
1677 } else
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001678 error = dpm_suspend(state);
Alan Sterncd59abf2007-09-21 15:36:56 -04001679 return error;
Alan Sterncd59abf2007-09-21 15:36:56 -04001680}
Alan Sternd1616302009-05-24 22:05:42 +02001681EXPORT_SYMBOL_GPL(dpm_suspend_start);
Alan Sterncd59abf2007-09-21 15:36:56 -04001682
1683void __suspend_report_result(const char *function, void *fn, int ret)
1684{
Bjorn Helgaasc80cfb02008-10-15 22:01:35 -07001685 if (ret)
1686 printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret);
Alan Sterncd59abf2007-09-21 15:36:56 -04001687}
1688EXPORT_SYMBOL_GPL(__suspend_report_result);
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001689
1690/**
1691 * device_pm_wait_for_dev - Wait for suspend/resume of a device to complete.
1692 * @dev: Device to wait for.
1693 * @subordinate: Device that needs to wait for @dev.
1694 */
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001695int device_pm_wait_for_dev(struct device *subordinate, struct device *dev)
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001696{
1697 dpm_wait(dev, subordinate->power.async_suspend);
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001698 return async_error;
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001699}
1700EXPORT_SYMBOL_GPL(device_pm_wait_for_dev);
Ming Leidfe32122012-08-17 22:06:59 +08001701
1702/**
1703 * dpm_for_each_dev - device iterator.
1704 * @data: data for the callback.
1705 * @fn: function to be called for each device.
1706 *
1707 * Iterate over devices in dpm_list, and call @fn for each device,
1708 * passing it @data.
1709 */
1710void dpm_for_each_dev(void *data, void (*fn)(struct device *, void *))
1711{
1712 struct device *dev;
1713
1714 if (!fn)
1715 return;
1716
1717 device_pm_lock();
1718 list_for_each_entry(dev, &dpm_list, power.entry)
1719 fn(dev, data);
1720 device_pm_unlock();
1721}
1722EXPORT_SYMBOL_GPL(dpm_for_each_dev);