blob: ea3f1d2c28cff881b4968887a08f84bfcbad0933 [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>
Alan Sterncd59abf2007-09-21 15:36:56 -040026#include <linux/resume-trace.h>
Rafael J. Wysocki2ed8d2b32009-03-16 22:34:06 +010027#include <linux/interrupt.h>
Arjan van de Venf2511772009-12-13 20:29:01 +010028#include <linux/sched.h>
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +010029#include <linux/async.h>
Rafael J. Wysocki1e752272010-12-03 22:58:05 +010030#include <linux/suspend.h>
Shuah Khan53644672013-07-26 13:30:20 -060031#include <trace/events/power.h>
Preeti U Murthy8651f972012-07-09 10:12:56 +020032#include <linux/cpuidle.h>
Benoit Goby70fea602013-10-17 10:48:46 -070033#include <linux/timer.h>
34
Alan Sterncd59abf2007-09-21 15:36:56 -040035#include "../base.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070036#include "power.h"
37
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +010038typedef int (*pm_callback_t)(struct device *);
39
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010040/*
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020041 * The entries in the dpm_list list are in a depth first order, simply
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010042 * because children are guaranteed to be discovered after parents, and
43 * are inserted at the back of the list on discovery.
44 *
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -080045 * Since device_pm_add() may be called with a device lock held,
46 * we must never try to acquire a device lock while holding
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010047 * dpm_list_mutex.
48 */
49
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020050LIST_HEAD(dpm_list);
Sachin Kamat7664e962012-07-17 22:38:08 +020051static LIST_HEAD(dpm_prepared_list);
52static LIST_HEAD(dpm_suspended_list);
53static LIST_HEAD(dpm_late_early_list);
54static LIST_HEAD(dpm_noirq_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -070055
ShuoX Liu2a77c462011-08-10 23:01:26 +020056struct suspend_stats suspend_stats;
Alan Sterncd59abf2007-09-21 15:36:56 -040057static DEFINE_MUTEX(dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +010058static pm_message_t pm_transition;
Linus Torvalds1da177e2005-04-16 15:20:36 -070059
Rafael J. Wysocki098dff72010-09-22 22:10:57 +020060static int async_error;
61
Shuah Khan53644672013-07-26 13:30:20 -060062static char *pm_verb(int event)
63{
64 switch (event) {
65 case PM_EVENT_SUSPEND:
66 return "suspend";
67 case PM_EVENT_RESUME:
68 return "resume";
69 case PM_EVENT_FREEZE:
70 return "freeze";
71 case PM_EVENT_QUIESCE:
72 return "quiesce";
73 case PM_EVENT_HIBERNATE:
74 return "hibernate";
75 case PM_EVENT_THAW:
76 return "thaw";
77 case PM_EVENT_RESTORE:
78 return "restore";
79 case PM_EVENT_RECOVER:
80 return "recover";
81 default:
82 return "(unknown PM event)";
83 }
84}
85
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020086/**
Rafael J. Wysockie91c11b2012-08-06 01:44:28 +020087 * device_pm_sleep_init - Initialize system suspend-related device fields.
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +020088 * @dev: Device object being initialized.
89 */
Rafael J. Wysockie91c11b2012-08-06 01:44:28 +020090void device_pm_sleep_init(struct device *dev)
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +020091{
Alan Sternf76b168b2011-06-18 20:22:23 +020092 dev->power.is_prepared = false;
Alan Stern6d0e0e82011-06-18 22:42:09 +020093 dev->power.is_suspended = false;
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +080094 dev->power.is_noirq_suspended = false;
95 dev->power.is_late_suspended = false;
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +010096 init_completion(&dev->power.completion);
Colin Cross152e1d52010-09-03 01:24:07 +020097 complete_all(&dev->power.completion);
Rafael J. Wysocki074037e2010-09-22 22:09:10 +020098 dev->power.wakeup = NULL;
Rafael J. Wysocki22110fa2011-04-26 11:33:09 +020099 INIT_LIST_HEAD(&dev->power.entry);
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +0200100}
101
102/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200103 * device_pm_lock - Lock the list of active devices used by the PM core.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200104 */
105void device_pm_lock(void)
106{
107 mutex_lock(&dpm_list_mtx);
108}
109
110/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200111 * device_pm_unlock - Unlock the list of active devices used by the PM core.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200112 */
113void device_pm_unlock(void)
114{
115 mutex_unlock(&dpm_list_mtx);
116}
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100117
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100118/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200119 * device_pm_add - Add a device to the PM core's list of active devices.
120 * @dev: Device to add to the list.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100121 */
Alan Stern3b98aea2008-08-07 13:06:12 -0400122void device_pm_add(struct device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700123{
Linus Torvalds1da177e2005-04-16 15:20:36 -0700124 pr_debug("PM: Adding info for %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100125 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700126 mutex_lock(&dpm_list_mtx);
Alan Sternf76b168b2011-06-18 20:22:23 +0200127 if (dev->parent && dev->parent->power.is_prepared)
Rafael J. Wysockib64959e2010-12-16 17:11:45 +0100128 dev_warn(dev, "parent %s should not be sleeping\n",
129 dev_name(dev->parent));
Alan Stern3b98aea2008-08-07 13:06:12 -0400130 list_add_tail(&dev->power.entry, &dpm_list);
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200131 mutex_unlock(&dpm_list_mtx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700132}
133
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100134/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200135 * device_pm_remove - Remove a device from the PM core's list of active devices.
136 * @dev: Device to be removed from the list.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100137 */
Rafael J. Wysocki9cddad72007-06-13 15:53:34 +0200138void device_pm_remove(struct device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700139{
140 pr_debug("PM: Removing info for %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100141 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100142 complete_all(&dev->power.completion);
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700143 mutex_lock(&dpm_list_mtx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700144 list_del_init(&dev->power.entry);
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700145 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki074037e2010-09-22 22:09:10 +0200146 device_wakeup_disable(dev);
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +0200147 pm_runtime_remove(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100148}
149
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200150/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200151 * device_pm_move_before - Move device in the PM core's list of active devices.
152 * @deva: Device to move in dpm_list.
153 * @devb: Device @deva should come before.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100154 */
155void device_pm_move_before(struct device *deva, struct device *devb)
156{
157 pr_debug("PM: Moving %s:%s before %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100158 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
159 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
Cornelia Huckffa6a702009-03-04 12:44:00 +0100160 /* Delete deva from dpm_list and reinsert before devb. */
161 list_move_tail(&deva->power.entry, &devb->power.entry);
162}
163
164/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200165 * device_pm_move_after - Move device in the PM core's list of active devices.
166 * @deva: Device to move in dpm_list.
167 * @devb: Device @deva should come after.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100168 */
169void device_pm_move_after(struct device *deva, struct device *devb)
170{
171 pr_debug("PM: Moving %s:%s after %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100172 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
173 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
Cornelia Huckffa6a702009-03-04 12:44:00 +0100174 /* Delete deva from dpm_list and reinsert after devb. */
175 list_move(&deva->power.entry, &devb->power.entry);
176}
177
178/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200179 * device_pm_move_last - Move device to end of the PM core's list of devices.
180 * @dev: Device to move in dpm_list.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100181 */
182void device_pm_move_last(struct device *dev)
183{
184 pr_debug("PM: Moving %s:%s to end of list\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100185 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
Cornelia Huckffa6a702009-03-04 12:44:00 +0100186 list_move_tail(&dev->power.entry, &dpm_list);
187}
188
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100189static ktime_t initcall_debug_start(struct device *dev)
190{
191 ktime_t calltime = ktime_set(0, 0);
192
Rafael J. Wysockib2df1d42012-06-21 00:19:33 +0200193 if (pm_print_times_enabled) {
Rafael J. Wysocki0c6aebe2011-12-03 00:23:43 +0100194 pr_info("calling %s+ @ %i, parent: %s\n",
195 dev_name(dev), task_pid_nr(current),
196 dev->parent ? dev_name(dev->parent) : "none");
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100197 calltime = ktime_get();
198 }
199
200 return calltime;
201}
202
203static void initcall_debug_report(struct device *dev, ktime_t calltime,
Shuah Khan53644672013-07-26 13:30:20 -0600204 int error, pm_message_t state, char *info)
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100205{
Shuah Khan53644672013-07-26 13:30:20 -0600206 ktime_t rettime;
207 s64 nsecs;
208
209 rettime = ktime_get();
210 nsecs = (s64) ktime_to_ns(ktime_sub(rettime, calltime));
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100211
Rafael J. Wysockib2df1d42012-06-21 00:19:33 +0200212 if (pm_print_times_enabled) {
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100213 pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
Shuah Khan53644672013-07-26 13:30:20 -0600214 error, (unsigned long long)nsecs >> 10);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100215 }
Shuah Khan53644672013-07-26 13:30:20 -0600216
217 trace_device_pm_report_time(dev, info, nsecs, pm_verb(state.event),
218 error);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100219}
220
Cornelia Huckffa6a702009-03-04 12:44:00 +0100221/**
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100222 * dpm_wait - Wait for a PM operation to complete.
223 * @dev: Device to wait for.
224 * @async: If unset, wait only if the device's power.async_suspend flag is set.
225 */
226static void dpm_wait(struct device *dev, bool async)
227{
228 if (!dev)
229 return;
230
Rafael J. Wysocki0e06b4a2010-01-23 22:25:15 +0100231 if (async || (pm_async_enabled && dev->power.async_suspend))
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100232 wait_for_completion(&dev->power.completion);
233}
234
235static int dpm_wait_fn(struct device *dev, void *async_ptr)
236{
237 dpm_wait(dev, *((bool *)async_ptr));
238 return 0;
239}
240
241static void dpm_wait_for_children(struct device *dev, bool async)
242{
243 device_for_each_child(dev, &async, dpm_wait_fn);
244}
245
246/**
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100247 * pm_op - Return the PM operation appropriate for given PM event.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200248 * @ops: PM operations to choose from.
249 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200250 */
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100251static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200252{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200253 switch (state.event) {
254#ifdef CONFIG_SUSPEND
255 case PM_EVENT_SUSPEND:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100256 return ops->suspend;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200257 case PM_EVENT_RESUME:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100258 return ops->resume;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200259#endif /* CONFIG_SUSPEND */
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200260#ifdef CONFIG_HIBERNATE_CALLBACKS
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200261 case PM_EVENT_FREEZE:
262 case PM_EVENT_QUIESCE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100263 return ops->freeze;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200264 case PM_EVENT_HIBERNATE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100265 return ops->poweroff;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200266 case PM_EVENT_THAW:
267 case PM_EVENT_RECOVER:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100268 return ops->thaw;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200269 break;
270 case PM_EVENT_RESTORE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100271 return ops->restore;
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200272#endif /* CONFIG_HIBERNATE_CALLBACKS */
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200273 }
Arjan van de Venf2511772009-12-13 20:29:01 +0100274
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100275 return NULL;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200276}
277
278/**
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100279 * pm_late_early_op - Return the PM operation appropriate for given PM event.
280 * @ops: PM operations to choose from.
281 * @state: PM transition of the system being carried out.
282 *
283 * Runtime PM is disabled for @dev while this function is being executed.
284 */
285static pm_callback_t pm_late_early_op(const struct dev_pm_ops *ops,
286 pm_message_t state)
287{
288 switch (state.event) {
289#ifdef CONFIG_SUSPEND
290 case PM_EVENT_SUSPEND:
291 return ops->suspend_late;
292 case PM_EVENT_RESUME:
293 return ops->resume_early;
294#endif /* CONFIG_SUSPEND */
295#ifdef CONFIG_HIBERNATE_CALLBACKS
296 case PM_EVENT_FREEZE:
297 case PM_EVENT_QUIESCE:
298 return ops->freeze_late;
299 case PM_EVENT_HIBERNATE:
300 return ops->poweroff_late;
301 case PM_EVENT_THAW:
302 case PM_EVENT_RECOVER:
303 return ops->thaw_early;
304 case PM_EVENT_RESTORE:
305 return ops->restore_early;
306#endif /* CONFIG_HIBERNATE_CALLBACKS */
307 }
308
309 return NULL;
310}
311
312/**
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100313 * pm_noirq_op - Return the PM operation appropriate for given PM event.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200314 * @ops: PM operations to choose from.
315 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200316 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200317 * The driver of @dev will not receive interrupts while this function is being
318 * executed.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200319 */
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100320static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200321{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200322 switch (state.event) {
323#ifdef CONFIG_SUSPEND
324 case PM_EVENT_SUSPEND:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100325 return ops->suspend_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200326 case PM_EVENT_RESUME:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100327 return ops->resume_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200328#endif /* CONFIG_SUSPEND */
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200329#ifdef CONFIG_HIBERNATE_CALLBACKS
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200330 case PM_EVENT_FREEZE:
331 case PM_EVENT_QUIESCE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100332 return ops->freeze_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200333 case PM_EVENT_HIBERNATE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100334 return ops->poweroff_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200335 case PM_EVENT_THAW:
336 case PM_EVENT_RECOVER:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100337 return ops->thaw_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200338 case PM_EVENT_RESTORE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100339 return ops->restore_noirq;
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200340#endif /* CONFIG_HIBERNATE_CALLBACKS */
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200341 }
Arjan van de Venf2511772009-12-13 20:29:01 +0100342
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100343 return NULL;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200344}
345
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200346static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info)
347{
348 dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event),
349 ((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ?
350 ", may wakeup" : "");
351}
352
353static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
354 int error)
355{
356 printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100357 dev_name(dev), pm_verb(state.event), info, error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200358}
359
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100360static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
361{
362 ktime_t calltime;
Kevin Cernekee0702d9ee2010-09-20 22:32:10 +0200363 u64 usecs64;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100364 int usecs;
365
366 calltime = ktime_get();
367 usecs64 = ktime_to_ns(ktime_sub(calltime, starttime));
368 do_div(usecs64, NSEC_PER_USEC);
369 usecs = usecs64;
370 if (usecs == 0)
371 usecs = 1;
372 pr_info("PM: %s%s%s of devices complete after %ld.%03ld msecs\n",
373 info ?: "", info ? " " : "", pm_verb(state.event),
374 usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
375}
376
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100377static int dpm_run_callback(pm_callback_t cb, struct device *dev,
378 pm_message_t state, char *info)
379{
380 ktime_t calltime;
381 int error;
382
383 if (!cb)
384 return 0;
385
386 calltime = initcall_debug_start(dev);
387
388 pm_dev_dbg(dev, state, info);
389 error = cb(dev);
390 suspend_report_result(cb, error);
391
Shuah Khan53644672013-07-26 13:30:20 -0600392 initcall_debug_report(dev, calltime, error, state, info);
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100393
394 return error;
395}
396
Benoit Goby70fea602013-10-17 10:48:46 -0700397#ifdef CONFIG_DPM_WATCHDOG
398struct dpm_watchdog {
399 struct device *dev;
400 struct task_struct *tsk;
401 struct timer_list timer;
402};
403
404#define DECLARE_DPM_WATCHDOG_ON_STACK(wd) \
405 struct dpm_watchdog wd
406
407/**
408 * dpm_watchdog_handler - Driver suspend / resume watchdog handler.
409 * @data: Watchdog object address.
410 *
411 * Called when a driver has timed out suspending or resuming.
412 * There's not much we can do here to recover so panic() to
413 * capture a crash-dump in pstore.
414 */
415static void dpm_watchdog_handler(unsigned long data)
416{
417 struct dpm_watchdog *wd = (void *)data;
418
419 dev_emerg(wd->dev, "**** DPM device timeout ****\n");
420 show_stack(wd->tsk, NULL);
421 panic("%s %s: unrecoverable failure\n",
422 dev_driver_string(wd->dev), dev_name(wd->dev));
423}
424
425/**
426 * dpm_watchdog_set - Enable pm watchdog for given device.
427 * @wd: Watchdog. Must be allocated on the stack.
428 * @dev: Device to handle.
429 */
430static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev)
431{
432 struct timer_list *timer = &wd->timer;
433
434 wd->dev = dev;
435 wd->tsk = current;
436
437 init_timer_on_stack(timer);
438 /* use same timeout value for both suspend and resume */
439 timer->expires = jiffies + HZ * CONFIG_DPM_WATCHDOG_TIMEOUT;
440 timer->function = dpm_watchdog_handler;
441 timer->data = (unsigned long)wd;
442 add_timer(timer);
443}
444
445/**
446 * dpm_watchdog_clear - Disable suspend/resume watchdog.
447 * @wd: Watchdog to disable.
448 */
449static void dpm_watchdog_clear(struct dpm_watchdog *wd)
450{
451 struct timer_list *timer = &wd->timer;
452
453 del_timer_sync(timer);
454 destroy_timer_on_stack(timer);
455}
456#else
457#define DECLARE_DPM_WATCHDOG_ON_STACK(wd)
458#define dpm_watchdog_set(x, y)
459#define dpm_watchdog_clear(x)
460#endif
461
Alan Sterncd59abf2007-09-21 15:36:56 -0400462/*------------------------- Resume routines -------------------------*/
463
464/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200465 * device_resume_noirq - Execute an "early resume" callback for given device.
466 * @dev: Device to handle.
467 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -0400468 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200469 * The driver of @dev will not receive interrupts while this function is being
470 * executed.
Alan Sterncd59abf2007-09-21 15:36:56 -0400471 */
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800472static int device_resume_noirq(struct device *dev, pm_message_t state, bool async)
Alan Sterncd59abf2007-09-21 15:36:56 -0400473{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100474 pm_callback_t callback = NULL;
475 char *info = NULL;
Alan Sterncd59abf2007-09-21 15:36:56 -0400476 int error = 0;
477
478 TRACE_DEVICE(dev);
479 TRACE_RESUME(0);
480
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200481 if (dev->power.syscore)
482 goto Out;
483
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800484 if (!dev->power.is_noirq_suspended)
485 goto Out;
486
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800487 dpm_wait(dev->parent, async);
488
Rafael J. Wysocki564b9052011-06-23 01:52:55 +0200489 if (dev->pm_domain) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100490 info = "noirq power domain ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100491 callback = pm_noirq_op(&dev->pm_domain->ops, state);
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200492 } else if (dev->type && dev->type->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100493 info = "noirq type ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100494 callback = pm_noirq_op(dev->type->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100495 } else if (dev->class && dev->class->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100496 info = "noirq class ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100497 callback = pm_noirq_op(dev->class->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100498 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100499 info = "noirq bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100500 callback = pm_noirq_op(dev->bus->pm, state);
Dominik Brodowskie7176a32010-03-15 21:43:11 +0100501 }
502
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100503 if (!callback && dev->driver && dev->driver->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100504 info = "noirq driver ";
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100505 callback = pm_noirq_op(dev->driver->pm, state);
506 }
507
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100508 error = dpm_run_callback(callback, dev, state, info);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800509 dev->power.is_noirq_suspended = false;
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100510
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200511 Out:
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800512 complete_all(&dev->power.completion);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100513 TRACE_RESUME(error);
514 return error;
515}
516
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800517static bool is_async(struct device *dev)
518{
519 return dev->power.async_suspend && pm_async_enabled
520 && !pm_trace_is_enabled();
521}
522
523static void async_resume_noirq(void *data, async_cookie_t cookie)
524{
525 struct device *dev = (struct device *)data;
526 int error;
527
528 error = device_resume_noirq(dev, pm_transition, true);
529 if (error)
530 pm_dev_err(dev, pm_transition, " async", error);
531
532 put_device(dev);
533}
534
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100535/**
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100536 * dpm_resume_noirq - Execute "noirq resume" callbacks for all devices.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200537 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100538 *
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100539 * Call the "noirq" resume handlers for all devices in dpm_noirq_list and
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200540 * enable device drivers to receive interrupts.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100541 */
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100542static void dpm_resume_noirq(pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100543{
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800544 struct device *dev;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100545 ktime_t starttime = ktime_get();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100546
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200547 mutex_lock(&dpm_list_mtx);
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800548 pm_transition = state;
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100549
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800550 /*
551 * Advanced the async threads upfront,
552 * in case the starting of async threads is
553 * delayed by non-async resuming devices.
554 */
555 list_for_each_entry(dev, &dpm_noirq_list, power.entry) {
556 reinit_completion(&dev->power.completion);
557 if (is_async(dev)) {
558 get_device(dev);
559 async_schedule(async_resume_noirq, dev);
560 }
561 }
562
563 while (!list_empty(&dpm_noirq_list)) {
564 dev = to_device(dpm_noirq_list.next);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100565 get_device(dev);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100566 list_move_tail(&dev->power.entry, &dpm_late_early_list);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100567 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100568
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800569 if (!is_async(dev)) {
570 int error;
571
572 error = device_resume_noirq(dev, state, false);
573 if (error) {
574 suspend_stats.failed_resume_noirq++;
575 dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
576 dpm_save_failed_dev(dev_name(dev));
577 pm_dev_err(dev, state, " noirq", error);
578 }
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100579 }
580
581 mutex_lock(&dpm_list_mtx);
582 put_device(dev);
583 }
584 mutex_unlock(&dpm_list_mtx);
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800585 async_synchronize_full();
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100586 dpm_show_time(starttime, state, "noirq");
587 resume_device_irqs();
Preeti U Murthy8651f972012-07-09 10:12:56 +0200588 cpuidle_resume();
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100589}
590
591/**
592 * device_resume_early - Execute an "early resume" callback for given device.
593 * @dev: Device to handle.
594 * @state: PM transition of the system being carried out.
595 *
596 * Runtime PM is disabled for @dev while this function is being executed.
597 */
598static int device_resume_early(struct device *dev, pm_message_t state)
599{
600 pm_callback_t callback = NULL;
601 char *info = NULL;
602 int error = 0;
603
604 TRACE_DEVICE(dev);
605 TRACE_RESUME(0);
606
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200607 if (dev->power.syscore)
608 goto Out;
609
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800610 if (!dev->power.is_late_suspended)
611 goto Out;
612
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100613 if (dev->pm_domain) {
614 info = "early power domain ";
615 callback = pm_late_early_op(&dev->pm_domain->ops, state);
616 } else if (dev->type && dev->type->pm) {
617 info = "early type ";
618 callback = pm_late_early_op(dev->type->pm, state);
619 } else if (dev->class && dev->class->pm) {
620 info = "early class ";
621 callback = pm_late_early_op(dev->class->pm, state);
622 } else if (dev->bus && dev->bus->pm) {
623 info = "early bus ";
624 callback = pm_late_early_op(dev->bus->pm, state);
625 }
626
627 if (!callback && dev->driver && dev->driver->pm) {
628 info = "early driver ";
629 callback = pm_late_early_op(dev->driver->pm, state);
630 }
631
632 error = dpm_run_callback(callback, dev, state, info);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800633 dev->power.is_late_suspended = false;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100634
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200635 Out:
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100636 TRACE_RESUME(error);
Rafael J. Wysocki9f6d8f62012-12-22 23:59:01 +0100637
638 pm_runtime_enable(dev);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100639 return error;
640}
641
642/**
643 * dpm_resume_early - Execute "early resume" callbacks for all devices.
644 * @state: PM transition of the system being carried out.
645 */
646static void dpm_resume_early(pm_message_t state)
647{
648 ktime_t starttime = ktime_get();
649
650 mutex_lock(&dpm_list_mtx);
651 while (!list_empty(&dpm_late_early_list)) {
652 struct device *dev = to_device(dpm_late_early_list.next);
653 int error;
654
655 get_device(dev);
656 list_move_tail(&dev->power.entry, &dpm_suspended_list);
657 mutex_unlock(&dpm_list_mtx);
658
659 error = device_resume_early(dev, state);
660 if (error) {
661 suspend_stats.failed_resume_early++;
662 dpm_save_failed_step(SUSPEND_RESUME_EARLY);
663 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100664 pm_dev_err(dev, state, " early", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +0200665 }
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100666
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100667 mutex_lock(&dpm_list_mtx);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100668 put_device(dev);
669 }
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200670 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100671 dpm_show_time(starttime, state, "early");
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100672}
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100673
674/**
675 * dpm_resume_start - Execute "noirq" and "early" device callbacks.
676 * @state: PM transition of the system being carried out.
677 */
678void dpm_resume_start(pm_message_t state)
679{
680 dpm_resume_noirq(state);
681 dpm_resume_early(state);
682}
683EXPORT_SYMBOL_GPL(dpm_resume_start);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100684
685/**
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100686 * device_resume - Execute "resume" callbacks for given device.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200687 * @dev: Device to handle.
688 * @state: PM transition of the system being carried out.
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100689 * @async: If true, the device is being resumed asynchronously.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100690 */
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100691static int device_resume(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100692{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100693 pm_callback_t callback = NULL;
694 char *info = NULL;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100695 int error = 0;
Benoit Goby70fea602013-10-17 10:48:46 -0700696 DECLARE_DPM_WATCHDOG_ON_STACK(wd);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100697
698 TRACE_DEVICE(dev);
699 TRACE_RESUME(0);
Alan Sterncd59abf2007-09-21 15:36:56 -0400700
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200701 if (dev->power.syscore)
702 goto Complete;
703
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100704 dpm_wait(dev->parent, async);
Benoit Goby70fea602013-10-17 10:48:46 -0700705 dpm_watchdog_set(&wd, dev);
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800706 device_lock(dev);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100707
Alan Sternf76b168b2011-06-18 20:22:23 +0200708 /*
709 * This is a fib. But we'll allow new children to be added below
710 * a resumed device, even if the device hasn't been completed yet.
711 */
712 dev->power.is_prepared = false;
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100713
Alan Stern6d0e0e82011-06-18 22:42:09 +0200714 if (!dev->power.is_suspended)
715 goto Unlock;
716
Rafael J. Wysocki564b9052011-06-23 01:52:55 +0200717 if (dev->pm_domain) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100718 info = "power domain ";
719 callback = pm_op(&dev->pm_domain->ops, state);
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100720 goto Driver;
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +0100721 }
722
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100723 if (dev->type && dev->type->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100724 info = "type ";
725 callback = pm_op(dev->type->pm, state);
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100726 goto Driver;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100727 }
728
729 if (dev->class) {
730 if (dev->class->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100731 info = "class ";
732 callback = pm_op(dev->class->pm, state);
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100733 goto Driver;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100734 } else if (dev->class->resume) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100735 info = "legacy class ";
736 callback = dev->class->resume;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100737 goto End;
738 }
739 }
740
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200741 if (dev->bus) {
742 if (dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100743 info = "bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100744 callback = pm_op(dev->bus->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200745 } else if (dev->bus->resume) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100746 info = "legacy bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100747 callback = dev->bus->resume;
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100748 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200749 }
Alan Sterncd59abf2007-09-21 15:36:56 -0400750 }
751
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100752 Driver:
753 if (!callback && dev->driver && dev->driver->pm) {
754 info = "driver ";
755 callback = pm_op(dev->driver->pm, state);
756 }
757
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200758 End:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100759 error = dpm_run_callback(callback, dev, state, info);
Alan Stern6d0e0e82011-06-18 22:42:09 +0200760 dev->power.is_suspended = false;
761
762 Unlock:
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800763 device_unlock(dev);
Benoit Goby70fea602013-10-17 10:48:46 -0700764 dpm_watchdog_clear(&wd);
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200765
766 Complete:
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100767 complete_all(&dev->power.completion);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100768
Alan Sterncd59abf2007-09-21 15:36:56 -0400769 TRACE_RESUME(error);
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +0200770
Alan Sterncd59abf2007-09-21 15:36:56 -0400771 return error;
772}
773
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100774static void async_resume(void *data, async_cookie_t cookie)
775{
776 struct device *dev = (struct device *)data;
777 int error;
778
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100779 error = device_resume(dev, pm_transition, true);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100780 if (error)
781 pm_dev_err(dev, pm_transition, " async", error);
782 put_device(dev);
783}
784
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100785/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200786 * dpm_resume - Execute "resume" callbacks for non-sysdev devices.
787 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100788 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200789 * Execute the appropriate "resume" callback for all devices whose status
790 * indicates that they are suspended.
Alan Sterncd59abf2007-09-21 15:36:56 -0400791 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200792void dpm_resume(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400793{
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100794 struct device *dev;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100795 ktime_t starttime = ktime_get();
Alan Sterncd59abf2007-09-21 15:36:56 -0400796
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200797 might_sleep();
798
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200799 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100800 pm_transition = state;
Rafael J. Wysocki098dff72010-09-22 22:10:57 +0200801 async_error = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200802
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100803 list_for_each_entry(dev, &dpm_suspended_list, power.entry) {
Wolfram Sang16735d02013-11-14 14:32:02 -0800804 reinit_completion(&dev->power.completion);
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100805 if (is_async(dev)) {
806 get_device(dev);
807 async_schedule(async_resume, dev);
808 }
809 }
810
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100811 while (!list_empty(&dpm_suspended_list)) {
812 dev = to_device(dpm_suspended_list.next);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200813 get_device(dev);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100814 if (!is_async(dev)) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200815 int error;
816
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200817 mutex_unlock(&dpm_list_mtx);
818
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100819 error = device_resume(dev, state, false);
ShuoX Liu2a77c462011-08-10 23:01:26 +0200820 if (error) {
821 suspend_stats.failed_resume++;
822 dpm_save_failed_step(SUSPEND_RESUME);
823 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200824 pm_dev_err(dev, state, "", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +0200825 }
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100826
827 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200828 }
829 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100830 list_move_tail(&dev->power.entry, &dpm_prepared_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200831 put_device(dev);
Alan Sterncd59abf2007-09-21 15:36:56 -0400832 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200833 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100834 async_synchronize_full();
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100835 dpm_show_time(starttime, state, NULL);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200836}
837
838/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200839 * device_complete - Complete a PM transition for given device.
840 * @dev: Device to handle.
841 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200842 */
Alan Sternd1616302009-05-24 22:05:42 +0200843static void device_complete(struct device *dev, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200844{
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100845 void (*callback)(struct device *) = NULL;
846 char *info = NULL;
847
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200848 if (dev->power.syscore)
849 return;
850
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800851 device_lock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200852
Rafael J. Wysocki564b9052011-06-23 01:52:55 +0200853 if (dev->pm_domain) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100854 info = "completing power domain ";
855 callback = dev->pm_domain->ops.complete;
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200856 } else if (dev->type && dev->type->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100857 info = "completing type ";
858 callback = dev->type->pm->complete;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100859 } else if (dev->class && dev->class->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100860 info = "completing class ";
861 callback = dev->class->pm->complete;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100862 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100863 info = "completing bus ";
864 callback = dev->bus->pm->complete;
865 }
866
867 if (!callback && dev->driver && dev->driver->pm) {
868 info = "completing driver ";
869 callback = dev->driver->pm->complete;
870 }
871
872 if (callback) {
873 pm_dev_dbg(dev, state, info);
874 callback(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200875 }
876
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800877 device_unlock(dev);
Alan Stern88d26132012-09-19 21:59:02 +0200878
Ulf Hanssonaf939332013-04-12 09:41:06 +0000879 pm_runtime_put(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200880}
881
882/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200883 * dpm_complete - Complete a PM transition for all non-sysdev devices.
884 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200885 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200886 * Execute the ->complete() callbacks for all devices whose PM status is not
887 * DPM_ON (this allows new devices to be registered).
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200888 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200889void dpm_complete(pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200890{
891 struct list_head list;
892
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200893 might_sleep();
894
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200895 INIT_LIST_HEAD(&list);
896 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100897 while (!list_empty(&dpm_prepared_list)) {
898 struct device *dev = to_device(dpm_prepared_list.prev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200899
900 get_device(dev);
Alan Sternf76b168b2011-06-18 20:22:23 +0200901 dev->power.is_prepared = false;
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100902 list_move(&dev->power.entry, &list);
903 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200904
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100905 device_complete(dev, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200906
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100907 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200908 put_device(dev);
909 }
910 list_splice(&list, &dpm_list);
Alan Sterncd59abf2007-09-21 15:36:56 -0400911 mutex_unlock(&dpm_list_mtx);
912}
913
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100914/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200915 * dpm_resume_end - Execute "resume" callbacks and complete system transition.
916 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -0400917 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200918 * Execute "resume" callbacks for all devices and complete the PM transition of
919 * the system.
Alan Sterncd59abf2007-09-21 15:36:56 -0400920 */
Alan Sternd1616302009-05-24 22:05:42 +0200921void dpm_resume_end(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400922{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200923 dpm_resume(state);
924 dpm_complete(state);
Alan Sterncd59abf2007-09-21 15:36:56 -0400925}
Alan Sternd1616302009-05-24 22:05:42 +0200926EXPORT_SYMBOL_GPL(dpm_resume_end);
Alan Sterncd59abf2007-09-21 15:36:56 -0400927
928
Alan Sterncd59abf2007-09-21 15:36:56 -0400929/*------------------------- Suspend routines -------------------------*/
930
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200931/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200932 * resume_event - Return a "resume" message for given "suspend" sleep state.
933 * @sleep_state: PM message representing a sleep state.
934 *
935 * Return a PM message representing the resume event corresponding to given
936 * sleep state.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200937 */
938static pm_message_t resume_event(pm_message_t sleep_state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400939{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200940 switch (sleep_state.event) {
941 case PM_EVENT_SUSPEND:
942 return PMSG_RESUME;
943 case PM_EVENT_FREEZE:
944 case PM_EVENT_QUIESCE:
945 return PMSG_RECOVER;
946 case PM_EVENT_HIBERNATE:
947 return PMSG_RESTORE;
Alan Sterncd59abf2007-09-21 15:36:56 -0400948 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200949 return PMSG_ON;
Alan Sterncd59abf2007-09-21 15:36:56 -0400950}
951
952/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200953 * device_suspend_noirq - Execute a "late suspend" callback for given device.
954 * @dev: Device to handle.
955 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100956 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200957 * The driver of @dev will not receive interrupts while this function is being
958 * executed.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100959 */
Alan Sternd1616302009-05-24 22:05:42 +0200960static int device_suspend_noirq(struct device *dev, pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100961{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100962 pm_callback_t callback = NULL;
963 char *info = NULL;
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800964 int error;
Dominik Brodowskie7176a32010-03-15 21:43:11 +0100965
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200966 if (dev->power.syscore)
967 return 0;
968
Rafael J. Wysocki564b9052011-06-23 01:52:55 +0200969 if (dev->pm_domain) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100970 info = "noirq power domain ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100971 callback = pm_noirq_op(&dev->pm_domain->ops, state);
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200972 } else if (dev->type && dev->type->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100973 info = "noirq type ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100974 callback = pm_noirq_op(dev->type->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100975 } else if (dev->class && dev->class->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100976 info = "noirq class ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100977 callback = pm_noirq_op(dev->class->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100978 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100979 info = "noirq bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100980 callback = pm_noirq_op(dev->bus->pm, state);
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +0100981 }
982
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100983 if (!callback && dev->driver && dev->driver->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100984 info = "noirq driver ";
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100985 callback = pm_noirq_op(dev->driver->pm, state);
986 }
987
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800988 error = dpm_run_callback(callback, dev, state, info);
989 if (!error)
990 dev->power.is_noirq_suspended = true;
991
992 return error;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100993}
994
995/**
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100996 * dpm_suspend_noirq - Execute "noirq suspend" callbacks for all devices.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200997 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100998 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200999 * Prevent device drivers from receiving interrupts and call the "noirq" suspend
1000 * handlers for all non-sysdev devices.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001001 */
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001002static int dpm_suspend_noirq(pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001003{
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001004 ktime_t starttime = ktime_get();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001005 int error = 0;
1006
Preeti U Murthy8651f972012-07-09 10:12:56 +02001007 cpuidle_pause();
Rafael J. Wysocki2ed8d2b32009-03-16 22:34:06 +01001008 suspend_device_irqs();
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +02001009 mutex_lock(&dpm_list_mtx);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001010 while (!list_empty(&dpm_late_early_list)) {
1011 struct device *dev = to_device(dpm_late_early_list.prev);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001012
1013 get_device(dev);
1014 mutex_unlock(&dpm_list_mtx);
1015
Alan Sternd1616302009-05-24 22:05:42 +02001016 error = device_suspend_noirq(dev, state);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001017
1018 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001019 if (error) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001020 pm_dev_err(dev, state, " noirq", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001021 suspend_stats.failed_suspend_noirq++;
1022 dpm_save_failed_step(SUSPEND_SUSPEND_NOIRQ);
1023 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001024 put_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001025 break;
1026 }
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001027 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001028 list_move(&dev->power.entry, &dpm_noirq_list);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001029 put_device(dev);
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001030
1031 if (pm_wakeup_pending()) {
1032 error = -EBUSY;
1033 break;
1034 }
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001035 }
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +02001036 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001037 if (error)
Alan Sternd1616302009-05-24 22:05:42 +02001038 dpm_resume_noirq(resume_event(state));
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001039 else
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001040 dpm_show_time(starttime, state, "noirq");
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001041 return error;
1042}
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001043
1044/**
1045 * device_suspend_late - Execute a "late suspend" callback for given device.
1046 * @dev: Device to handle.
1047 * @state: PM transition of the system being carried out.
1048 *
1049 * Runtime PM is disabled for @dev while this function is being executed.
1050 */
1051static int device_suspend_late(struct device *dev, pm_message_t state)
1052{
1053 pm_callback_t callback = NULL;
1054 char *info = NULL;
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001055 int error;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001056
Rafael J. Wysocki9f6d8f62012-12-22 23:59:01 +01001057 __pm_runtime_disable(dev, false);
1058
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001059 if (dev->power.syscore)
1060 return 0;
1061
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001062 if (dev->pm_domain) {
1063 info = "late power domain ";
1064 callback = pm_late_early_op(&dev->pm_domain->ops, state);
1065 } else if (dev->type && dev->type->pm) {
1066 info = "late type ";
1067 callback = pm_late_early_op(dev->type->pm, state);
1068 } else if (dev->class && dev->class->pm) {
1069 info = "late class ";
1070 callback = pm_late_early_op(dev->class->pm, state);
1071 } else if (dev->bus && dev->bus->pm) {
1072 info = "late bus ";
1073 callback = pm_late_early_op(dev->bus->pm, state);
1074 }
1075
1076 if (!callback && dev->driver && dev->driver->pm) {
1077 info = "late driver ";
1078 callback = pm_late_early_op(dev->driver->pm, state);
1079 }
1080
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001081 error = dpm_run_callback(callback, dev, state, info);
1082 if (!error)
1083 dev->power.is_late_suspended = true;
1084
1085 return error;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001086}
1087
1088/**
1089 * dpm_suspend_late - Execute "late suspend" callbacks for all devices.
1090 * @state: PM transition of the system being carried out.
1091 */
1092static int dpm_suspend_late(pm_message_t state)
1093{
1094 ktime_t starttime = ktime_get();
1095 int error = 0;
1096
1097 mutex_lock(&dpm_list_mtx);
1098 while (!list_empty(&dpm_suspended_list)) {
1099 struct device *dev = to_device(dpm_suspended_list.prev);
1100
1101 get_device(dev);
1102 mutex_unlock(&dpm_list_mtx);
1103
1104 error = device_suspend_late(dev, state);
1105
1106 mutex_lock(&dpm_list_mtx);
1107 if (error) {
1108 pm_dev_err(dev, state, " late", error);
1109 suspend_stats.failed_suspend_late++;
1110 dpm_save_failed_step(SUSPEND_SUSPEND_LATE);
1111 dpm_save_failed_dev(dev_name(dev));
1112 put_device(dev);
1113 break;
1114 }
1115 if (!list_empty(&dev->power.entry))
1116 list_move(&dev->power.entry, &dpm_late_early_list);
1117 put_device(dev);
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001118
1119 if (pm_wakeup_pending()) {
1120 error = -EBUSY;
1121 break;
1122 }
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001123 }
1124 mutex_unlock(&dpm_list_mtx);
1125 if (error)
1126 dpm_resume_early(resume_event(state));
1127 else
1128 dpm_show_time(starttime, state, "late");
1129
1130 return error;
1131}
1132
1133/**
1134 * dpm_suspend_end - Execute "late" and "noirq" device suspend callbacks.
1135 * @state: PM transition of the system being carried out.
1136 */
1137int dpm_suspend_end(pm_message_t state)
1138{
1139 int error = dpm_suspend_late(state);
Colin Cross064b0212012-07-19 10:38:06 +02001140 if (error)
1141 return error;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001142
Colin Cross064b0212012-07-19 10:38:06 +02001143 error = dpm_suspend_noirq(state);
1144 if (error) {
Feng Hong997a0312012-09-19 14:16:00 +02001145 dpm_resume_early(resume_event(state));
Colin Cross064b0212012-07-19 10:38:06 +02001146 return error;
1147 }
1148
1149 return 0;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001150}
1151EXPORT_SYMBOL_GPL(dpm_suspend_end);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001152
1153/**
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001154 * legacy_suspend - Execute a legacy (bus or class) suspend callback for device.
Randy Dunlap0a884222010-01-08 14:42:57 -08001155 * @dev: Device to suspend.
1156 * @state: PM transition of the system being carried out.
1157 * @cb: Suspend callback to execute.
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001158 */
1159static int legacy_suspend(struct device *dev, pm_message_t state,
Shuah Khan53644672013-07-26 13:30:20 -06001160 int (*cb)(struct device *dev, pm_message_t state),
1161 char *info)
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001162{
1163 int error;
1164 ktime_t calltime;
1165
1166 calltime = initcall_debug_start(dev);
1167
1168 error = cb(dev, state);
1169 suspend_report_result(cb, error);
1170
Shuah Khan53644672013-07-26 13:30:20 -06001171 initcall_debug_report(dev, calltime, error, state, info);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001172
1173 return error;
1174}
1175
1176/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001177 * device_suspend - Execute "suspend" callbacks for given device.
1178 * @dev: Device to handle.
1179 * @state: PM transition of the system being carried out.
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001180 * @async: If true, the device is being suspended asynchronously.
Alan Sterncd59abf2007-09-21 15:36:56 -04001181 */
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001182static int __device_suspend(struct device *dev, pm_message_t state, bool async)
Alan Sterncd59abf2007-09-21 15:36:56 -04001183{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001184 pm_callback_t callback = NULL;
1185 char *info = NULL;
Alan Sterncd59abf2007-09-21 15:36:56 -04001186 int error = 0;
Benoit Goby70fea602013-10-17 10:48:46 -07001187 DECLARE_DPM_WATCHDOG_ON_STACK(wd);
Alan Sterncd59abf2007-09-21 15:36:56 -04001188
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001189 dpm_wait_for_children(dev, async);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +01001190
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001191 if (async_error)
Mandeep Singh Baines1f758b22012-06-24 23:31:09 +02001192 goto Complete;
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001193
Alan Stern88d26132012-09-19 21:59:02 +02001194 /*
1195 * If a device configured to wake up the system from sleep states
1196 * has been suspended at run time and there's a resume request pending
1197 * for it, this is equivalent to the device signaling wakeup, so the
1198 * system suspend operation should be aborted.
1199 */
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001200 if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
1201 pm_wakeup_event(dev, 0);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001202
Rafael J. Wysockid83f9052010-12-03 23:14:26 +01001203 if (pm_wakeup_pending()) {
1204 async_error = -EBUSY;
Mandeep Singh Baines1f758b22012-06-24 23:31:09 +02001205 goto Complete;
Rafael J. Wysockid83f9052010-12-03 23:14:26 +01001206 }
1207
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001208 if (dev->power.syscore)
1209 goto Complete;
1210
Benoit Goby70fea602013-10-17 10:48:46 -07001211 dpm_watchdog_set(&wd, dev);
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001212 device_lock(dev);
1213
Rafael J. Wysocki564b9052011-06-23 01:52:55 +02001214 if (dev->pm_domain) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001215 info = "power domain ";
1216 callback = pm_op(&dev->pm_domain->ops, state);
1217 goto Run;
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001218 }
1219
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001220 if (dev->type && dev->type->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001221 info = "type ";
1222 callback = pm_op(dev->type->pm, state);
1223 goto Run;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001224 }
1225
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001226 if (dev->class) {
1227 if (dev->class->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001228 info = "class ";
1229 callback = pm_op(dev->class->pm, state);
1230 goto Run;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001231 } else if (dev->class->suspend) {
1232 pm_dev_dbg(dev, state, "legacy class ");
Shuah Khan53644672013-07-26 13:30:20 -06001233 error = legacy_suspend(dev, state, dev->class->suspend,
1234 "legacy class ");
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001235 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001236 }
Alan Sterncd59abf2007-09-21 15:36:56 -04001237 }
1238
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001239 if (dev->bus) {
1240 if (dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001241 info = "bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001242 callback = pm_op(dev->bus->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001243 } else if (dev->bus->suspend) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001244 pm_dev_dbg(dev, state, "legacy bus ");
Shuah Khan53644672013-07-26 13:30:20 -06001245 error = legacy_suspend(dev, state, dev->bus->suspend,
1246 "legacy bus ");
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001247 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001248 }
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001249 }
1250
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001251 Run:
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001252 if (!callback && dev->driver && dev->driver->pm) {
1253 info = "driver ";
1254 callback = pm_op(dev->driver->pm, state);
1255 }
1256
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001257 error = dpm_run_callback(callback, dev, state, info);
1258
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001259 End:
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001260 if (!error) {
1261 dev->power.is_suspended = true;
Rafael J. Wysocki8b258cc2011-11-17 21:39:33 +01001262 if (dev->power.wakeup_path
1263 && dev->parent && !dev->parent->power.ignore_children)
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001264 dev->parent->power.wakeup_path = true;
1265 }
Alan Stern6d0e0e82011-06-18 22:42:09 +02001266
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001267 device_unlock(dev);
Benoit Goby70fea602013-10-17 10:48:46 -07001268 dpm_watchdog_clear(&wd);
Mandeep Singh Baines1f758b22012-06-24 23:31:09 +02001269
1270 Complete:
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001271 complete_all(&dev->power.completion);
Alan Stern88d26132012-09-19 21:59:02 +02001272 if (error)
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001273 async_error = error;
1274
Alan Sterncd59abf2007-09-21 15:36:56 -04001275 return error;
1276}
1277
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001278static void async_suspend(void *data, async_cookie_t cookie)
1279{
1280 struct device *dev = (struct device *)data;
1281 int error;
1282
1283 error = __device_suspend(dev, pm_transition, true);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001284 if (error) {
1285 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001286 pm_dev_err(dev, pm_transition, " async", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001287 }
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001288
1289 put_device(dev);
1290}
1291
1292static int device_suspend(struct device *dev)
1293{
Wolfram Sang16735d02013-11-14 14:32:02 -08001294 reinit_completion(&dev->power.completion);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001295
Rafael J. Wysocki0e06b4a2010-01-23 22:25:15 +01001296 if (pm_async_enabled && dev->power.async_suspend) {
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001297 get_device(dev);
1298 async_schedule(async_suspend, dev);
1299 return 0;
1300 }
1301
1302 return __device_suspend(dev, pm_transition, false);
1303}
1304
Alan Sterncd59abf2007-09-21 15:36:56 -04001305/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001306 * dpm_suspend - Execute "suspend" callbacks for all non-sysdev devices.
1307 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -04001308 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001309int dpm_suspend(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001310{
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001311 ktime_t starttime = ktime_get();
Alan Sterncd59abf2007-09-21 15:36:56 -04001312 int error = 0;
1313
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001314 might_sleep();
1315
Alan Sterncd59abf2007-09-21 15:36:56 -04001316 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001317 pm_transition = state;
1318 async_error = 0;
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001319 while (!list_empty(&dpm_prepared_list)) {
1320 struct device *dev = to_device(dpm_prepared_list.prev);
Alan Sterncd59abf2007-09-21 15:36:56 -04001321
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001322 get_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001323 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001324
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001325 error = device_suspend(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001326
Alan Stern1b3cbec2008-02-29 11:50:22 -05001327 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001328 if (error) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001329 pm_dev_err(dev, state, "", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001330 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001331 put_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001332 break;
1333 }
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +01001334 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001335 list_move(&dev->power.entry, &dpm_suspended_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001336 put_device(dev);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001337 if (async_error)
1338 break;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001339 }
1340 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001341 async_synchronize_full();
1342 if (!error)
1343 error = async_error;
ShuoX Liu2a77c462011-08-10 23:01:26 +02001344 if (error) {
1345 suspend_stats.failed_suspend++;
1346 dpm_save_failed_step(SUSPEND_SUSPEND);
1347 } else
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001348 dpm_show_time(starttime, state, NULL);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001349 return error;
1350}
1351
1352/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001353 * device_prepare - Prepare a device for system power transition.
1354 * @dev: Device to handle.
1355 * @state: PM transition of the system being carried out.
1356 *
1357 * Execute the ->prepare() callback(s) for given device. No new children of the
1358 * device may be registered after this function has returned.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001359 */
Alan Sternd1616302009-05-24 22:05:42 +02001360static int device_prepare(struct device *dev, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001361{
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001362 int (*callback)(struct device *) = NULL;
1363 char *info = NULL;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001364 int error = 0;
1365
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001366 if (dev->power.syscore)
1367 return 0;
1368
Alan Stern88d26132012-09-19 21:59:02 +02001369 /*
1370 * If a device's parent goes into runtime suspend at the wrong time,
1371 * it won't be possible to resume the device. To prevent this we
1372 * block runtime suspend here, during the prepare phase, and allow
1373 * it again during the complete phase.
1374 */
1375 pm_runtime_get_noresume(dev);
1376
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001377 device_lock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001378
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001379 dev->power.wakeup_path = device_may_wakeup(dev);
1380
Rafael J. Wysocki564b9052011-06-23 01:52:55 +02001381 if (dev->pm_domain) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001382 info = "preparing power domain ";
1383 callback = dev->pm_domain->ops.prepare;
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001384 } else if (dev->type && dev->type->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001385 info = "preparing type ";
1386 callback = dev->type->pm->prepare;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001387 } else if (dev->class && dev->class->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001388 info = "preparing class ";
1389 callback = dev->class->pm->prepare;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001390 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001391 info = "preparing bus ";
1392 callback = dev->bus->pm->prepare;
1393 }
1394
1395 if (!callback && dev->driver && dev->driver->pm) {
1396 info = "preparing driver ";
1397 callback = dev->driver->pm->prepare;
1398 }
1399
1400 if (callback) {
1401 error = callback(dev);
1402 suspend_report_result(callback, error);
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001403 }
1404
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001405 device_unlock(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001406
Ulf Hanssonaa1b9f12013-11-13 15:45:03 +01001407 if (error)
1408 pm_runtime_put(dev);
1409
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001410 return error;
1411}
1412
1413/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001414 * dpm_prepare - Prepare all non-sysdev devices for a system PM transition.
1415 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -04001416 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001417 * Execute the ->prepare() callback(s) for all devices.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001418 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001419int dpm_prepare(pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001420{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001421 int error = 0;
1422
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001423 might_sleep();
1424
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001425 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001426 while (!list_empty(&dpm_list)) {
1427 struct device *dev = to_device(dpm_list.next);
1428
1429 get_device(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001430 mutex_unlock(&dpm_list_mtx);
1431
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001432 error = device_prepare(dev, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001433
1434 mutex_lock(&dpm_list_mtx);
1435 if (error) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001436 if (error == -EAGAIN) {
1437 put_device(dev);
Sebastian Ott886a7a32009-07-08 13:26:05 +02001438 error = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001439 continue;
1440 }
Rafael J. Wysocki1e752272010-12-03 22:58:05 +01001441 printk(KERN_INFO "PM: Device %s not prepared "
1442 "for power transition: code %d\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +01001443 dev_name(dev), error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001444 put_device(dev);
1445 break;
1446 }
Alan Sternf76b168b2011-06-18 20:22:23 +02001447 dev->power.is_prepared = true;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001448 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001449 list_move_tail(&dev->power.entry, &dpm_prepared_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001450 put_device(dev);
1451 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001452 mutex_unlock(&dpm_list_mtx);
1453 return error;
1454}
1455
1456/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001457 * dpm_suspend_start - Prepare devices for PM transition and suspend them.
1458 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001459 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001460 * Prepare all non-sysdev devices for system PM transition and execute "suspend"
1461 * callbacks for them.
Alan Sterncd59abf2007-09-21 15:36:56 -04001462 */
Alan Sternd1616302009-05-24 22:05:42 +02001463int dpm_suspend_start(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001464{
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001465 int error;
Alan Sterncd59abf2007-09-21 15:36:56 -04001466
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001467 error = dpm_prepare(state);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001468 if (error) {
1469 suspend_stats.failed_prepare++;
1470 dpm_save_failed_step(SUSPEND_PREPARE);
1471 } else
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001472 error = dpm_suspend(state);
Alan Sterncd59abf2007-09-21 15:36:56 -04001473 return error;
Alan Sterncd59abf2007-09-21 15:36:56 -04001474}
Alan Sternd1616302009-05-24 22:05:42 +02001475EXPORT_SYMBOL_GPL(dpm_suspend_start);
Alan Sterncd59abf2007-09-21 15:36:56 -04001476
1477void __suspend_report_result(const char *function, void *fn, int ret)
1478{
Bjorn Helgaasc80cfb02008-10-15 22:01:35 -07001479 if (ret)
1480 printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret);
Alan Sterncd59abf2007-09-21 15:36:56 -04001481}
1482EXPORT_SYMBOL_GPL(__suspend_report_result);
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001483
1484/**
1485 * device_pm_wait_for_dev - Wait for suspend/resume of a device to complete.
1486 * @dev: Device to wait for.
1487 * @subordinate: Device that needs to wait for @dev.
1488 */
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001489int device_pm_wait_for_dev(struct device *subordinate, struct device *dev)
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001490{
1491 dpm_wait(dev, subordinate->power.async_suspend);
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001492 return async_error;
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001493}
1494EXPORT_SYMBOL_GPL(device_pm_wait_for_dev);
Ming Leidfe32122012-08-17 22:06:59 +08001495
1496/**
1497 * dpm_for_each_dev - device iterator.
1498 * @data: data for the callback.
1499 * @fn: function to be called for each device.
1500 *
1501 * Iterate over devices in dpm_list, and call @fn for each device,
1502 * passing it @data.
1503 */
1504void dpm_for_each_dev(void *data, void (*fn)(struct device *, void *))
1505{
1506 struct device *dev;
1507
1508 if (!fn)
1509 return;
1510
1511 device_pm_lock();
1512 list_for_each_entry(dev, &dpm_list, power.entry)
1513 fn(dev, data);
1514 device_pm_unlock();
1515}
1516EXPORT_SYMBOL_GPL(dpm_for_each_dev);