blob: 420914061405df935ec65b8522cc67d31480022e [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));
Tomeu Vizosoaa8e54b2016-01-07 16:46:14 +0100128 device_pm_check_callbacks(dev);
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700129 mutex_lock(&dpm_list_mtx);
Alan Sternf76b168b2011-06-18 20:22:23 +0200130 if (dev->parent && dev->parent->power.is_prepared)
Rafael J. Wysockib64959e2010-12-16 17:11:45 +0100131 dev_warn(dev, "parent %s should not be sleeping\n",
132 dev_name(dev->parent));
Alan Stern3b98aea2008-08-07 13:06:12 -0400133 list_add_tail(&dev->power.entry, &dpm_list);
Rafael J. Wysocki9ed98952016-10-30 17:32:16 +0100134 dev->power.in_dpm_list = true;
Rafael J. Wysocki1a9a9152011-09-29 22:29:44 +0200135 mutex_unlock(&dpm_list_mtx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700136}
137
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100138/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200139 * device_pm_remove - Remove a device from the PM core's list of active devices.
140 * @dev: Device to be removed from the list.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100141 */
Rafael J. Wysocki9cddad72007-06-13 15:53:34 +0200142void device_pm_remove(struct device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700143{
144 pr_debug("PM: Removing info for %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100145 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100146 complete_all(&dev->power.completion);
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700147 mutex_lock(&dpm_list_mtx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700148 list_del_init(&dev->power.entry);
Rafael J. Wysocki9ed98952016-10-30 17:32:16 +0100149 dev->power.in_dpm_list = false;
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700150 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki074037e2010-09-22 22:09:10 +0200151 device_wakeup_disable(dev);
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +0200152 pm_runtime_remove(dev);
Tomeu Vizosoaa8e54b2016-01-07 16:46:14 +0100153 device_pm_check_callbacks(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100154}
155
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200156/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200157 * device_pm_move_before - Move device in the PM core's list of active devices.
158 * @deva: Device to move in dpm_list.
159 * @devb: Device @deva should come before.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100160 */
161void device_pm_move_before(struct device *deva, struct device *devb)
162{
163 pr_debug("PM: Moving %s:%s before %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100164 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
165 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
Cornelia Huckffa6a702009-03-04 12:44:00 +0100166 /* Delete deva from dpm_list and reinsert before devb. */
167 list_move_tail(&deva->power.entry, &devb->power.entry);
168}
169
170/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200171 * device_pm_move_after - Move device in the PM core's list of active devices.
172 * @deva: Device to move in dpm_list.
173 * @devb: Device @deva should come after.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100174 */
175void device_pm_move_after(struct device *deva, struct device *devb)
176{
177 pr_debug("PM: Moving %s:%s after %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100178 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
179 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
Cornelia Huckffa6a702009-03-04 12:44:00 +0100180 /* Delete deva from dpm_list and reinsert after devb. */
181 list_move(&deva->power.entry, &devb->power.entry);
182}
183
184/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200185 * device_pm_move_last - Move device to end of the PM core's list of devices.
186 * @dev: Device to move in dpm_list.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100187 */
188void device_pm_move_last(struct device *dev)
189{
190 pr_debug("PM: Moving %s:%s to end of list\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100191 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
Cornelia Huckffa6a702009-03-04 12:44:00 +0100192 list_move_tail(&dev->power.entry, &dpm_list);
193}
194
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100195static ktime_t initcall_debug_start(struct device *dev)
196{
197 ktime_t calltime = ktime_set(0, 0);
198
Rafael J. Wysockib2df1d42012-06-21 00:19:33 +0200199 if (pm_print_times_enabled) {
Rafael J. Wysocki0c6aebe2011-12-03 00:23:43 +0100200 pr_info("calling %s+ @ %i, parent: %s\n",
201 dev_name(dev), task_pid_nr(current),
202 dev->parent ? dev_name(dev->parent) : "none");
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100203 calltime = ktime_get();
204 }
205
206 return calltime;
207}
208
209static void initcall_debug_report(struct device *dev, ktime_t calltime,
Shuah Khan53644672013-07-26 13:30:20 -0600210 int error, pm_message_t state, char *info)
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100211{
Shuah Khan53644672013-07-26 13:30:20 -0600212 ktime_t rettime;
213 s64 nsecs;
214
215 rettime = ktime_get();
216 nsecs = (s64) ktime_to_ns(ktime_sub(rettime, calltime));
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100217
Rafael J. Wysockib2df1d42012-06-21 00:19:33 +0200218 if (pm_print_times_enabled) {
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100219 pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
Shuah Khan53644672013-07-26 13:30:20 -0600220 error, (unsigned long long)nsecs >> 10);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100221 }
222}
223
Cornelia Huckffa6a702009-03-04 12:44:00 +0100224/**
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100225 * dpm_wait - Wait for a PM operation to complete.
226 * @dev: Device to wait for.
227 * @async: If unset, wait only if the device's power.async_suspend flag is set.
228 */
229static void dpm_wait(struct device *dev, bool async)
230{
231 if (!dev)
232 return;
233
Rafael J. Wysocki0e06b4a2010-01-23 22:25:15 +0100234 if (async || (pm_async_enabled && dev->power.async_suspend))
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100235 wait_for_completion(&dev->power.completion);
236}
237
238static int dpm_wait_fn(struct device *dev, void *async_ptr)
239{
240 dpm_wait(dev, *((bool *)async_ptr));
241 return 0;
242}
243
244static void dpm_wait_for_children(struct device *dev, bool async)
245{
246 device_for_each_child(dev, &async, dpm_wait_fn);
247}
248
249/**
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100250 * pm_op - Return the PM operation appropriate for given PM event.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200251 * @ops: PM operations to choose from.
252 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200253 */
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100254static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200255{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200256 switch (state.event) {
257#ifdef CONFIG_SUSPEND
258 case PM_EVENT_SUSPEND:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100259 return ops->suspend;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200260 case PM_EVENT_RESUME:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100261 return ops->resume;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200262#endif /* CONFIG_SUSPEND */
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200263#ifdef CONFIG_HIBERNATE_CALLBACKS
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200264 case PM_EVENT_FREEZE:
265 case PM_EVENT_QUIESCE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100266 return ops->freeze;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200267 case PM_EVENT_HIBERNATE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100268 return ops->poweroff;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200269 case PM_EVENT_THAW:
270 case PM_EVENT_RECOVER:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100271 return ops->thaw;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200272 break;
273 case PM_EVENT_RESTORE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100274 return ops->restore;
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200275#endif /* CONFIG_HIBERNATE_CALLBACKS */
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200276 }
Arjan van de Venf2511772009-12-13 20:29:01 +0100277
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100278 return NULL;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200279}
280
281/**
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100282 * pm_late_early_op - Return the PM operation appropriate for given PM event.
283 * @ops: PM operations to choose from.
284 * @state: PM transition of the system being carried out.
285 *
286 * Runtime PM is disabled for @dev while this function is being executed.
287 */
288static pm_callback_t pm_late_early_op(const struct dev_pm_ops *ops,
289 pm_message_t state)
290{
291 switch (state.event) {
292#ifdef CONFIG_SUSPEND
293 case PM_EVENT_SUSPEND:
294 return ops->suspend_late;
295 case PM_EVENT_RESUME:
296 return ops->resume_early;
297#endif /* CONFIG_SUSPEND */
298#ifdef CONFIG_HIBERNATE_CALLBACKS
299 case PM_EVENT_FREEZE:
300 case PM_EVENT_QUIESCE:
301 return ops->freeze_late;
302 case PM_EVENT_HIBERNATE:
303 return ops->poweroff_late;
304 case PM_EVENT_THAW:
305 case PM_EVENT_RECOVER:
306 return ops->thaw_early;
307 case PM_EVENT_RESTORE:
308 return ops->restore_early;
309#endif /* CONFIG_HIBERNATE_CALLBACKS */
310 }
311
312 return NULL;
313}
314
315/**
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100316 * pm_noirq_op - Return the PM operation appropriate for given PM event.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200317 * @ops: PM operations to choose from.
318 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200319 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200320 * The driver of @dev will not receive interrupts while this function is being
321 * executed.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200322 */
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100323static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200324{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200325 switch (state.event) {
326#ifdef CONFIG_SUSPEND
327 case PM_EVENT_SUSPEND:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100328 return ops->suspend_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200329 case PM_EVENT_RESUME:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100330 return ops->resume_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200331#endif /* CONFIG_SUSPEND */
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200332#ifdef CONFIG_HIBERNATE_CALLBACKS
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200333 case PM_EVENT_FREEZE:
334 case PM_EVENT_QUIESCE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100335 return ops->freeze_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200336 case PM_EVENT_HIBERNATE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100337 return ops->poweroff_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200338 case PM_EVENT_THAW:
339 case PM_EVENT_RECOVER:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100340 return ops->thaw_noirq;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200341 case PM_EVENT_RESTORE:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100342 return ops->restore_noirq;
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200343#endif /* CONFIG_HIBERNATE_CALLBACKS */
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200344 }
Arjan van de Venf2511772009-12-13 20:29:01 +0100345
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100346 return NULL;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200347}
348
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200349static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info)
350{
351 dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event),
352 ((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ?
353 ", may wakeup" : "");
354}
355
356static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
357 int error)
358{
359 printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100360 dev_name(dev), pm_verb(state.event), info, error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200361}
362
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100363static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
364{
365 ktime_t calltime;
Kevin Cernekee0702d9ee2010-09-20 22:32:10 +0200366 u64 usecs64;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100367 int usecs;
368
369 calltime = ktime_get();
370 usecs64 = ktime_to_ns(ktime_sub(calltime, starttime));
371 do_div(usecs64, NSEC_PER_USEC);
372 usecs = usecs64;
373 if (usecs == 0)
374 usecs = 1;
375 pr_info("PM: %s%s%s of devices complete after %ld.%03ld msecs\n",
376 info ?: "", info ? " " : "", pm_verb(state.event),
377 usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
378}
379
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100380static int dpm_run_callback(pm_callback_t cb, struct device *dev,
381 pm_message_t state, char *info)
382{
383 ktime_t calltime;
384 int error;
385
386 if (!cb)
387 return 0;
388
389 calltime = initcall_debug_start(dev);
390
391 pm_dev_dbg(dev, state, info);
Todd E Brandte8bca472014-06-10 07:31:22 -0700392 trace_device_pm_callback_start(dev, info, state.event);
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100393 error = cb(dev);
Todd E Brandte8bca472014-06-10 07:31:22 -0700394 trace_device_pm_callback_end(dev, error);
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100395 suspend_report_result(cb, error);
396
Shuah Khan53644672013-07-26 13:30:20 -0600397 initcall_debug_report(dev, calltime, error, state, info);
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100398
399 return error;
400}
401
Benoit Goby70fea602013-10-17 10:48:46 -0700402#ifdef CONFIG_DPM_WATCHDOG
403struct dpm_watchdog {
404 struct device *dev;
405 struct task_struct *tsk;
406 struct timer_list timer;
407};
408
409#define DECLARE_DPM_WATCHDOG_ON_STACK(wd) \
410 struct dpm_watchdog wd
411
412/**
413 * dpm_watchdog_handler - Driver suspend / resume watchdog handler.
414 * @data: Watchdog object address.
415 *
416 * Called when a driver has timed out suspending or resuming.
417 * There's not much we can do here to recover so panic() to
418 * capture a crash-dump in pstore.
419 */
420static void dpm_watchdog_handler(unsigned long data)
421{
422 struct dpm_watchdog *wd = (void *)data;
423
424 dev_emerg(wd->dev, "**** DPM device timeout ****\n");
425 show_stack(wd->tsk, NULL);
426 panic("%s %s: unrecoverable failure\n",
427 dev_driver_string(wd->dev), dev_name(wd->dev));
428}
429
430/**
431 * dpm_watchdog_set - Enable pm watchdog for given device.
432 * @wd: Watchdog. Must be allocated on the stack.
433 * @dev: Device to handle.
434 */
435static void dpm_watchdog_set(struct dpm_watchdog *wd, struct device *dev)
436{
437 struct timer_list *timer = &wd->timer;
438
439 wd->dev = dev;
440 wd->tsk = current;
441
442 init_timer_on_stack(timer);
443 /* use same timeout value for both suspend and resume */
444 timer->expires = jiffies + HZ * CONFIG_DPM_WATCHDOG_TIMEOUT;
445 timer->function = dpm_watchdog_handler;
446 timer->data = (unsigned long)wd;
447 add_timer(timer);
448}
449
450/**
451 * dpm_watchdog_clear - Disable suspend/resume watchdog.
452 * @wd: Watchdog to disable.
453 */
454static void dpm_watchdog_clear(struct dpm_watchdog *wd)
455{
456 struct timer_list *timer = &wd->timer;
457
458 del_timer_sync(timer);
459 destroy_timer_on_stack(timer);
460}
461#else
462#define DECLARE_DPM_WATCHDOG_ON_STACK(wd)
463#define dpm_watchdog_set(x, y)
464#define dpm_watchdog_clear(x)
465#endif
466
Alan Sterncd59abf2007-09-21 15:36:56 -0400467/*------------------------- Resume routines -------------------------*/
468
469/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200470 * device_resume_noirq - Execute an "early resume" callback for given device.
471 * @dev: Device to handle.
472 * @state: PM transition of the system being carried out.
Randy Dunlap58c256a2014-07-27 16:17:15 -0700473 * @async: If true, the device is being resumed asynchronously.
Alan Sterncd59abf2007-09-21 15:36:56 -0400474 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200475 * The driver of @dev will not receive interrupts while this function is being
476 * executed.
Alan Sterncd59abf2007-09-21 15:36:56 -0400477 */
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800478static int device_resume_noirq(struct device *dev, pm_message_t state, bool async)
Alan Sterncd59abf2007-09-21 15:36:56 -0400479{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100480 pm_callback_t callback = NULL;
481 char *info = NULL;
Alan Sterncd59abf2007-09-21 15:36:56 -0400482 int error = 0;
483
484 TRACE_DEVICE(dev);
485 TRACE_RESUME(0);
486
Rafael J. Wysockiaae45182014-05-16 02:46:50 +0200487 if (dev->power.syscore || dev->power.direct_complete)
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200488 goto Out;
489
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800490 if (!dev->power.is_noirq_suspended)
491 goto Out;
492
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800493 dpm_wait(dev->parent, async);
494
Rafael J. Wysocki564b9052011-06-23 01:52:55 +0200495 if (dev->pm_domain) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100496 info = "noirq power domain ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100497 callback = pm_noirq_op(&dev->pm_domain->ops, state);
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200498 } else if (dev->type && dev->type->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100499 info = "noirq type ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100500 callback = pm_noirq_op(dev->type->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100501 } else if (dev->class && dev->class->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100502 info = "noirq class ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100503 callback = pm_noirq_op(dev->class->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100504 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100505 info = "noirq bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100506 callback = pm_noirq_op(dev->bus->pm, state);
Dominik Brodowskie7176a32010-03-15 21:43:11 +0100507 }
508
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100509 if (!callback && dev->driver && dev->driver->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100510 info = "noirq driver ";
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100511 callback = pm_noirq_op(dev->driver->pm, state);
512 }
513
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100514 error = dpm_run_callback(callback, dev, state, info);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800515 dev->power.is_noirq_suspended = false;
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100516
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200517 Out:
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800518 complete_all(&dev->power.completion);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100519 TRACE_RESUME(error);
520 return error;
521}
522
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800523static bool is_async(struct device *dev)
524{
525 return dev->power.async_suspend && pm_async_enabled
526 && !pm_trace_is_enabled();
527}
528
529static void async_resume_noirq(void *data, async_cookie_t cookie)
530{
531 struct device *dev = (struct device *)data;
532 int error;
533
534 error = device_resume_noirq(dev, pm_transition, true);
535 if (error)
536 pm_dev_err(dev, pm_transition, " async", error);
537
538 put_device(dev);
539}
540
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100541/**
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100542 * dpm_resume_noirq - Execute "noirq resume" callbacks for all devices.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200543 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100544 *
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100545 * Call the "noirq" resume handlers for all devices in dpm_noirq_list and
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200546 * enable device drivers to receive interrupts.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100547 */
Rafael J. Wysocki2a8a8ce2014-09-30 02:21:34 +0200548void dpm_resume_noirq(pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100549{
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800550 struct device *dev;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100551 ktime_t starttime = ktime_get();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100552
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700553 trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, true);
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200554 mutex_lock(&dpm_list_mtx);
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800555 pm_transition = state;
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100556
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800557 /*
558 * Advanced the async threads upfront,
559 * in case the starting of async threads is
560 * delayed by non-async resuming devices.
561 */
562 list_for_each_entry(dev, &dpm_noirq_list, power.entry) {
563 reinit_completion(&dev->power.completion);
564 if (is_async(dev)) {
565 get_device(dev);
566 async_schedule(async_resume_noirq, dev);
567 }
568 }
569
570 while (!list_empty(&dpm_noirq_list)) {
571 dev = to_device(dpm_noirq_list.next);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100572 get_device(dev);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100573 list_move_tail(&dev->power.entry, &dpm_late_early_list);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100574 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100575
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800576 if (!is_async(dev)) {
577 int error;
578
579 error = device_resume_noirq(dev, state, false);
580 if (error) {
581 suspend_stats.failed_resume_noirq++;
582 dpm_save_failed_step(SUSPEND_RESUME_NOIRQ);
583 dpm_save_failed_dev(dev_name(dev));
584 pm_dev_err(dev, state, " noirq", error);
585 }
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100586 }
587
588 mutex_lock(&dpm_list_mtx);
589 put_device(dev);
590 }
591 mutex_unlock(&dpm_list_mtx);
Liu, Chuansheng76569fa2014-02-18 10:28:45 +0800592 async_synchronize_full();
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100593 dpm_show_time(starttime, state, "noirq");
594 resume_device_irqs();
Tony Lindgren4990d4f2015-05-18 15:40:29 -0700595 device_wakeup_disarm_wake_irqs();
Preeti U Murthy8651f972012-07-09 10:12:56 +0200596 cpuidle_resume();
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700597 trace_suspend_resume(TPS("dpm_resume_noirq"), state.event, false);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100598}
599
600/**
601 * device_resume_early - Execute an "early resume" callback for given device.
602 * @dev: Device to handle.
603 * @state: PM transition of the system being carried out.
Randy Dunlap58c256a2014-07-27 16:17:15 -0700604 * @async: If true, the device is being resumed asynchronously.
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100605 *
606 * Runtime PM is disabled for @dev while this function is being executed.
607 */
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800608static int device_resume_early(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100609{
610 pm_callback_t callback = NULL;
611 char *info = NULL;
612 int error = 0;
613
614 TRACE_DEVICE(dev);
615 TRACE_RESUME(0);
616
Rafael J. Wysockiaae45182014-05-16 02:46:50 +0200617 if (dev->power.syscore || dev->power.direct_complete)
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200618 goto Out;
619
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800620 if (!dev->power.is_late_suspended)
621 goto Out;
622
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800623 dpm_wait(dev->parent, async);
624
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100625 if (dev->pm_domain) {
626 info = "early power domain ";
627 callback = pm_late_early_op(&dev->pm_domain->ops, state);
628 } else if (dev->type && dev->type->pm) {
629 info = "early type ";
630 callback = pm_late_early_op(dev->type->pm, state);
631 } else if (dev->class && dev->class->pm) {
632 info = "early class ";
633 callback = pm_late_early_op(dev->class->pm, state);
634 } else if (dev->bus && dev->bus->pm) {
635 info = "early bus ";
636 callback = pm_late_early_op(dev->bus->pm, state);
637 }
638
639 if (!callback && dev->driver && dev->driver->pm) {
640 info = "early driver ";
641 callback = pm_late_early_op(dev->driver->pm, state);
642 }
643
644 error = dpm_run_callback(callback, dev, state, info);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +0800645 dev->power.is_late_suspended = false;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100646
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200647 Out:
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100648 TRACE_RESUME(error);
Rafael J. Wysocki9f6d8f62012-12-22 23:59:01 +0100649
650 pm_runtime_enable(dev);
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800651 complete_all(&dev->power.completion);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100652 return error;
653}
654
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800655static void async_resume_early(void *data, async_cookie_t cookie)
656{
657 struct device *dev = (struct device *)data;
658 int error;
659
660 error = device_resume_early(dev, pm_transition, true);
661 if (error)
662 pm_dev_err(dev, pm_transition, " async", error);
663
664 put_device(dev);
665}
666
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100667/**
668 * dpm_resume_early - Execute "early resume" callbacks for all devices.
669 * @state: PM transition of the system being carried out.
670 */
Rafael J. Wysocki2a8a8ce2014-09-30 02:21:34 +0200671void dpm_resume_early(pm_message_t state)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100672{
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800673 struct device *dev;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100674 ktime_t starttime = ktime_get();
675
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700676 trace_suspend_resume(TPS("dpm_resume_early"), state.event, true);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100677 mutex_lock(&dpm_list_mtx);
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800678 pm_transition = state;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100679
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800680 /*
681 * Advanced the async threads upfront,
682 * in case the starting of async threads is
683 * delayed by non-async resuming devices.
684 */
685 list_for_each_entry(dev, &dpm_late_early_list, power.entry) {
686 reinit_completion(&dev->power.completion);
687 if (is_async(dev)) {
688 get_device(dev);
689 async_schedule(async_resume_early, dev);
690 }
691 }
692
693 while (!list_empty(&dpm_late_early_list)) {
694 dev = to_device(dpm_late_early_list.next);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100695 get_device(dev);
696 list_move_tail(&dev->power.entry, &dpm_suspended_list);
697 mutex_unlock(&dpm_list_mtx);
698
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800699 if (!is_async(dev)) {
700 int error;
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100701
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800702 error = device_resume_early(dev, state, false);
703 if (error) {
704 suspend_stats.failed_resume_early++;
705 dpm_save_failed_step(SUSPEND_RESUME_EARLY);
706 dpm_save_failed_dev(dev_name(dev));
707 pm_dev_err(dev, state, " early", error);
708 }
709 }
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100710 mutex_lock(&dpm_list_mtx);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100711 put_device(dev);
712 }
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200713 mutex_unlock(&dpm_list_mtx);
Liu, Chuansheng9e5e7912014-02-18 10:28:46 +0800714 async_synchronize_full();
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100715 dpm_show_time(starttime, state, "early");
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700716 trace_suspend_resume(TPS("dpm_resume_early"), state.event, false);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100717}
Rafael J. Wysockicf579df2012-01-29 20:38:29 +0100718
719/**
720 * dpm_resume_start - Execute "noirq" and "early" device callbacks.
721 * @state: PM transition of the system being carried out.
722 */
723void dpm_resume_start(pm_message_t state)
724{
725 dpm_resume_noirq(state);
726 dpm_resume_early(state);
727}
728EXPORT_SYMBOL_GPL(dpm_resume_start);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100729
730/**
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100731 * device_resume - Execute "resume" callbacks for given device.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200732 * @dev: Device to handle.
733 * @state: PM transition of the system being carried out.
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100734 * @async: If true, the device is being resumed asynchronously.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100735 */
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100736static int device_resume(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100737{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100738 pm_callback_t callback = NULL;
739 char *info = NULL;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100740 int error = 0;
Benoit Goby70fea602013-10-17 10:48:46 -0700741 DECLARE_DPM_WATCHDOG_ON_STACK(wd);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100742
743 TRACE_DEVICE(dev);
744 TRACE_RESUME(0);
Alan Sterncd59abf2007-09-21 15:36:56 -0400745
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200746 if (dev->power.syscore)
747 goto Complete;
748
Rafael J. Wysockiaae45182014-05-16 02:46:50 +0200749 if (dev->power.direct_complete) {
750 /* Match the pm_runtime_disable() in __device_suspend(). */
751 pm_runtime_enable(dev);
752 goto Complete;
753 }
754
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100755 dpm_wait(dev->parent, async);
Benoit Goby70fea602013-10-17 10:48:46 -0700756 dpm_watchdog_set(&wd, dev);
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800757 device_lock(dev);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100758
Alan Sternf76b168b2011-06-18 20:22:23 +0200759 /*
760 * This is a fib. But we'll allow new children to be added below
761 * a resumed device, even if the device hasn't been completed yet.
762 */
763 dev->power.is_prepared = false;
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100764
Alan Stern6d0e0e82011-06-18 22:42:09 +0200765 if (!dev->power.is_suspended)
766 goto Unlock;
767
Rafael J. Wysocki564b9052011-06-23 01:52:55 +0200768 if (dev->pm_domain) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100769 info = "power domain ";
770 callback = pm_op(&dev->pm_domain->ops, state);
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100771 goto Driver;
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +0100772 }
773
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100774 if (dev->type && dev->type->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100775 info = "type ";
776 callback = pm_op(dev->type->pm, state);
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100777 goto Driver;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100778 }
779
780 if (dev->class) {
781 if (dev->class->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100782 info = "class ";
783 callback = pm_op(dev->class->pm, state);
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100784 goto Driver;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100785 } else if (dev->class->resume) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100786 info = "legacy class ";
787 callback = dev->class->resume;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100788 goto End;
789 }
790 }
791
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200792 if (dev->bus) {
793 if (dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100794 info = "bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100795 callback = pm_op(dev->bus->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200796 } else if (dev->bus->resume) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100797 info = "legacy bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100798 callback = dev->bus->resume;
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100799 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200800 }
Alan Sterncd59abf2007-09-21 15:36:56 -0400801 }
802
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100803 Driver:
804 if (!callback && dev->driver && dev->driver->pm) {
805 info = "driver ";
806 callback = pm_op(dev->driver->pm, state);
807 }
808
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200809 End:
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +0100810 error = dpm_run_callback(callback, dev, state, info);
Alan Stern6d0e0e82011-06-18 22:42:09 +0200811 dev->power.is_suspended = false;
812
813 Unlock:
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800814 device_unlock(dev);
Benoit Goby70fea602013-10-17 10:48:46 -0700815 dpm_watchdog_clear(&wd);
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200816
817 Complete:
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100818 complete_all(&dev->power.completion);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100819
Alan Sterncd59abf2007-09-21 15:36:56 -0400820 TRACE_RESUME(error);
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +0200821
Alan Sterncd59abf2007-09-21 15:36:56 -0400822 return error;
823}
824
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100825static void async_resume(void *data, async_cookie_t cookie)
826{
827 struct device *dev = (struct device *)data;
828 int error;
829
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100830 error = device_resume(dev, pm_transition, true);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100831 if (error)
832 pm_dev_err(dev, pm_transition, " async", error);
833 put_device(dev);
834}
835
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100836/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200837 * dpm_resume - Execute "resume" callbacks for non-sysdev devices.
838 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100839 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200840 * Execute the appropriate "resume" callback for all devices whose status
841 * indicates that they are suspended.
Alan Sterncd59abf2007-09-21 15:36:56 -0400842 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200843void dpm_resume(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400844{
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100845 struct device *dev;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100846 ktime_t starttime = ktime_get();
Alan Sterncd59abf2007-09-21 15:36:56 -0400847
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700848 trace_suspend_resume(TPS("dpm_resume"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200849 might_sleep();
850
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200851 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100852 pm_transition = state;
Rafael J. Wysocki098dff72010-09-22 22:10:57 +0200853 async_error = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200854
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100855 list_for_each_entry(dev, &dpm_suspended_list, power.entry) {
Wolfram Sang16735d02013-11-14 14:32:02 -0800856 reinit_completion(&dev->power.completion);
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100857 if (is_async(dev)) {
858 get_device(dev);
859 async_schedule(async_resume, dev);
860 }
861 }
862
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100863 while (!list_empty(&dpm_suspended_list)) {
864 dev = to_device(dpm_suspended_list.next);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200865 get_device(dev);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100866 if (!is_async(dev)) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200867 int error;
868
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200869 mutex_unlock(&dpm_list_mtx);
870
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100871 error = device_resume(dev, state, false);
ShuoX Liu2a77c462011-08-10 23:01:26 +0200872 if (error) {
873 suspend_stats.failed_resume++;
874 dpm_save_failed_step(SUSPEND_RESUME);
875 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200876 pm_dev_err(dev, state, "", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +0200877 }
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100878
879 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200880 }
881 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100882 list_move_tail(&dev->power.entry, &dpm_prepared_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200883 put_device(dev);
Alan Sterncd59abf2007-09-21 15:36:56 -0400884 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200885 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100886 async_synchronize_full();
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100887 dpm_show_time(starttime, state, NULL);
Viresh Kumar2f0aea92014-03-04 11:00:26 +0800888
889 cpufreq_resume();
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700890 trace_suspend_resume(TPS("dpm_resume"), state.event, false);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200891}
892
893/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200894 * device_complete - Complete a PM transition for given device.
895 * @dev: Device to handle.
896 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200897 */
Alan Sternd1616302009-05-24 22:05:42 +0200898static void device_complete(struct device *dev, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200899{
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100900 void (*callback)(struct device *) = NULL;
901 char *info = NULL;
902
Rafael J. Wysockidbf37412012-08-06 01:46:39 +0200903 if (dev->power.syscore)
904 return;
905
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800906 device_lock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200907
Rafael J. Wysocki564b9052011-06-23 01:52:55 +0200908 if (dev->pm_domain) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100909 info = "completing power domain ";
910 callback = dev->pm_domain->ops.complete;
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200911 } else if (dev->type && dev->type->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100912 info = "completing type ";
913 callback = dev->type->pm->complete;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100914 } else if (dev->class && dev->class->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100915 info = "completing class ";
916 callback = dev->class->pm->complete;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100917 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +0100918 info = "completing bus ";
919 callback = dev->bus->pm->complete;
920 }
921
922 if (!callback && dev->driver && dev->driver->pm) {
923 info = "completing driver ";
924 callback = dev->driver->pm->complete;
925 }
926
927 if (callback) {
928 pm_dev_dbg(dev, state, info);
929 callback(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200930 }
931
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800932 device_unlock(dev);
Alan Stern88d26132012-09-19 21:59:02 +0200933
Ulf Hanssonaf939332013-04-12 09:41:06 +0000934 pm_runtime_put(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200935}
936
937/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200938 * dpm_complete - Complete a PM transition for all non-sysdev devices.
939 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200940 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200941 * Execute the ->complete() callbacks for all devices whose PM status is not
942 * DPM_ON (this allows new devices to be registered).
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200943 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200944void dpm_complete(pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200945{
946 struct list_head list;
947
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700948 trace_suspend_resume(TPS("dpm_complete"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200949 might_sleep();
950
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200951 INIT_LIST_HEAD(&list);
952 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100953 while (!list_empty(&dpm_prepared_list)) {
954 struct device *dev = to_device(dpm_prepared_list.prev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200955
956 get_device(dev);
Alan Sternf76b168b2011-06-18 20:22:23 +0200957 dev->power.is_prepared = false;
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100958 list_move(&dev->power.entry, &list);
959 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200960
Todd E Brandt32e8d682015-05-28 12:55:53 -0700961 trace_device_pm_callback_start(dev, "", state.event);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100962 device_complete(dev, state);
Todd E Brandt32e8d682015-05-28 12:55:53 -0700963 trace_device_pm_callback_end(dev, 0);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200964
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100965 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200966 put_device(dev);
967 }
968 list_splice(&list, &dpm_list);
Alan Sterncd59abf2007-09-21 15:36:56 -0400969 mutex_unlock(&dpm_list_mtx);
Strashko, Grygorii013c0742015-11-10 11:42:34 +0200970
971 /* Allow device probing and trigger re-probing of deferred devices */
972 device_unblock_probing();
Todd E Brandtbb3632c2014-06-06 05:40:17 -0700973 trace_suspend_resume(TPS("dpm_complete"), state.event, false);
Alan Sterncd59abf2007-09-21 15:36:56 -0400974}
975
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100976/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200977 * dpm_resume_end - Execute "resume" callbacks and complete system transition.
978 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -0400979 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200980 * Execute "resume" callbacks for all devices and complete the PM transition of
981 * the system.
Alan Sterncd59abf2007-09-21 15:36:56 -0400982 */
Alan Sternd1616302009-05-24 22:05:42 +0200983void dpm_resume_end(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400984{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200985 dpm_resume(state);
986 dpm_complete(state);
Alan Sterncd59abf2007-09-21 15:36:56 -0400987}
Alan Sternd1616302009-05-24 22:05:42 +0200988EXPORT_SYMBOL_GPL(dpm_resume_end);
Alan Sterncd59abf2007-09-21 15:36:56 -0400989
990
Alan Sterncd59abf2007-09-21 15:36:56 -0400991/*------------------------- Suspend routines -------------------------*/
992
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200993/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200994 * resume_event - Return a "resume" message for given "suspend" sleep state.
995 * @sleep_state: PM message representing a sleep state.
996 *
997 * Return a PM message representing the resume event corresponding to given
998 * sleep state.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200999 */
1000static pm_message_t resume_event(pm_message_t sleep_state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001001{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001002 switch (sleep_state.event) {
1003 case PM_EVENT_SUSPEND:
1004 return PMSG_RESUME;
1005 case PM_EVENT_FREEZE:
1006 case PM_EVENT_QUIESCE:
1007 return PMSG_RECOVER;
1008 case PM_EVENT_HIBERNATE:
1009 return PMSG_RESTORE;
Alan Sterncd59abf2007-09-21 15:36:56 -04001010 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001011 return PMSG_ON;
Alan Sterncd59abf2007-09-21 15:36:56 -04001012}
1013
1014/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001015 * device_suspend_noirq - Execute a "late suspend" callback for given device.
1016 * @dev: Device to handle.
1017 * @state: PM transition of the system being carried out.
Randy Dunlap58c256a2014-07-27 16:17:15 -07001018 * @async: If true, the device is being suspended asynchronously.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001019 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001020 * The driver of @dev will not receive interrupts while this function is being
1021 * executed.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001022 */
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001023static int __device_suspend_noirq(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001024{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001025 pm_callback_t callback = NULL;
1026 char *info = NULL;
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001027 int error = 0;
1028
Zhonghui Fu431d4522015-03-18 15:54:27 +01001029 TRACE_DEVICE(dev);
1030 TRACE_SUSPEND(0);
1031
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001032 if (async_error)
1033 goto Complete;
1034
1035 if (pm_wakeup_pending()) {
1036 async_error = -EBUSY;
1037 goto Complete;
1038 }
Dominik Brodowskie7176a32010-03-15 21:43:11 +01001039
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001040 if (dev->power.syscore || dev->power.direct_complete)
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001041 goto Complete;
1042
1043 dpm_wait_for_children(dev, async);
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001044
Rafael J. Wysocki564b9052011-06-23 01:52:55 +02001045 if (dev->pm_domain) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001046 info = "noirq power domain ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001047 callback = pm_noirq_op(&dev->pm_domain->ops, state);
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001048 } else if (dev->type && dev->type->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001049 info = "noirq type ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001050 callback = pm_noirq_op(dev->type->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001051 } else if (dev->class && dev->class->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001052 info = "noirq class ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001053 callback = pm_noirq_op(dev->class->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001054 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001055 info = "noirq bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001056 callback = pm_noirq_op(dev->bus->pm, state);
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001057 }
1058
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001059 if (!callback && dev->driver && dev->driver->pm) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001060 info = "noirq driver ";
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001061 callback = pm_noirq_op(dev->driver->pm, state);
1062 }
1063
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001064 error = dpm_run_callback(callback, dev, state, info);
1065 if (!error)
1066 dev->power.is_noirq_suspended = true;
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001067 else
1068 async_error = error;
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001069
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001070Complete:
1071 complete_all(&dev->power.completion);
Zhonghui Fu431d4522015-03-18 15:54:27 +01001072 TRACE_SUSPEND(error);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001073 return error;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001074}
1075
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001076static void async_suspend_noirq(void *data, async_cookie_t cookie)
1077{
1078 struct device *dev = (struct device *)data;
1079 int error;
1080
1081 error = __device_suspend_noirq(dev, pm_transition, true);
1082 if (error) {
1083 dpm_save_failed_dev(dev_name(dev));
1084 pm_dev_err(dev, pm_transition, " async", error);
1085 }
1086
1087 put_device(dev);
1088}
1089
1090static int device_suspend_noirq(struct device *dev)
1091{
1092 reinit_completion(&dev->power.completion);
1093
Zhonghui Fu431d4522015-03-18 15:54:27 +01001094 if (is_async(dev)) {
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001095 get_device(dev);
1096 async_schedule(async_suspend_noirq, dev);
1097 return 0;
1098 }
1099 return __device_suspend_noirq(dev, pm_transition, false);
1100}
1101
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001102/**
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001103 * dpm_suspend_noirq - Execute "noirq suspend" callbacks for all devices.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001104 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001105 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001106 * Prevent device drivers from receiving interrupts and call the "noirq" suspend
1107 * handlers for all non-sysdev devices.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001108 */
Rafael J. Wysocki2a8a8ce2014-09-30 02:21:34 +02001109int dpm_suspend_noirq(pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001110{
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001111 ktime_t starttime = ktime_get();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001112 int error = 0;
1113
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001114 trace_suspend_resume(TPS("dpm_suspend_noirq"), state.event, true);
Preeti U Murthy8651f972012-07-09 10:12:56 +02001115 cpuidle_pause();
Tony Lindgren4990d4f2015-05-18 15:40:29 -07001116 device_wakeup_arm_wake_irqs();
Rafael J. Wysocki2ed8d2b32009-03-16 22:34:06 +01001117 suspend_device_irqs();
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +02001118 mutex_lock(&dpm_list_mtx);
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001119 pm_transition = state;
1120 async_error = 0;
1121
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001122 while (!list_empty(&dpm_late_early_list)) {
1123 struct device *dev = to_device(dpm_late_early_list.prev);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001124
1125 get_device(dev);
1126 mutex_unlock(&dpm_list_mtx);
1127
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001128 error = device_suspend_noirq(dev);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001129
1130 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001131 if (error) {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001132 pm_dev_err(dev, state, " noirq", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001133 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001134 put_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001135 break;
1136 }
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001137 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001138 list_move(&dev->power.entry, &dpm_noirq_list);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +01001139 put_device(dev);
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001140
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001141 if (async_error)
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001142 break;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001143 }
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +02001144 mutex_unlock(&dpm_list_mtx);
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001145 async_synchronize_full();
1146 if (!error)
1147 error = async_error;
1148
1149 if (error) {
1150 suspend_stats.failed_suspend_noirq++;
1151 dpm_save_failed_step(SUSPEND_SUSPEND_NOIRQ);
Alan Sternd1616302009-05-24 22:05:42 +02001152 dpm_resume_noirq(resume_event(state));
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001153 } else {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001154 dpm_show_time(starttime, state, "noirq");
Liu, Chuansheng28b6fd62014-02-18 10:28:47 +08001155 }
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001156 trace_suspend_resume(TPS("dpm_suspend_noirq"), state.event, false);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001157 return error;
1158}
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001159
1160/**
1161 * device_suspend_late - Execute a "late suspend" callback for given device.
1162 * @dev: Device to handle.
1163 * @state: PM transition of the system being carried out.
Randy Dunlap58c256a2014-07-27 16:17:15 -07001164 * @async: If true, the device is being suspended asynchronously.
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001165 *
1166 * Runtime PM is disabled for @dev while this function is being executed.
1167 */
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001168static int __device_suspend_late(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001169{
1170 pm_callback_t callback = NULL;
1171 char *info = NULL;
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001172 int error = 0;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001173
Zhonghui Fu431d4522015-03-18 15:54:27 +01001174 TRACE_DEVICE(dev);
1175 TRACE_SUSPEND(0);
1176
Rafael J. Wysocki9f6d8f62012-12-22 23:59:01 +01001177 __pm_runtime_disable(dev, false);
1178
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001179 if (async_error)
1180 goto Complete;
1181
1182 if (pm_wakeup_pending()) {
1183 async_error = -EBUSY;
1184 goto Complete;
1185 }
1186
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001187 if (dev->power.syscore || dev->power.direct_complete)
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001188 goto Complete;
1189
1190 dpm_wait_for_children(dev, async);
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001191
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001192 if (dev->pm_domain) {
1193 info = "late power domain ";
1194 callback = pm_late_early_op(&dev->pm_domain->ops, state);
1195 } else if (dev->type && dev->type->pm) {
1196 info = "late type ";
1197 callback = pm_late_early_op(dev->type->pm, state);
1198 } else if (dev->class && dev->class->pm) {
1199 info = "late class ";
1200 callback = pm_late_early_op(dev->class->pm, state);
1201 } else if (dev->bus && dev->bus->pm) {
1202 info = "late bus ";
1203 callback = pm_late_early_op(dev->bus->pm, state);
1204 }
1205
1206 if (!callback && dev->driver && dev->driver->pm) {
1207 info = "late driver ";
1208 callback = pm_late_early_op(dev->driver->pm, state);
1209 }
1210
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001211 error = dpm_run_callback(callback, dev, state, info);
1212 if (!error)
1213 dev->power.is_late_suspended = true;
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001214 else
1215 async_error = error;
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001216
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001217Complete:
Zhonghui Fu431d4522015-03-18 15:54:27 +01001218 TRACE_SUSPEND(error);
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001219 complete_all(&dev->power.completion);
Liu, Chuansheng3d2699b2014-02-18 10:28:44 +08001220 return error;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001221}
1222
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001223static void async_suspend_late(void *data, async_cookie_t cookie)
1224{
1225 struct device *dev = (struct device *)data;
1226 int error;
1227
1228 error = __device_suspend_late(dev, pm_transition, true);
1229 if (error) {
1230 dpm_save_failed_dev(dev_name(dev));
1231 pm_dev_err(dev, pm_transition, " async", error);
1232 }
1233 put_device(dev);
1234}
1235
1236static int device_suspend_late(struct device *dev)
1237{
1238 reinit_completion(&dev->power.completion);
1239
Zhonghui Fu431d4522015-03-18 15:54:27 +01001240 if (is_async(dev)) {
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001241 get_device(dev);
1242 async_schedule(async_suspend_late, dev);
1243 return 0;
1244 }
1245
1246 return __device_suspend_late(dev, pm_transition, false);
1247}
1248
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001249/**
1250 * dpm_suspend_late - Execute "late suspend" callbacks for all devices.
1251 * @state: PM transition of the system being carried out.
1252 */
Rafael J. Wysocki2a8a8ce2014-09-30 02:21:34 +02001253int dpm_suspend_late(pm_message_t state)
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001254{
1255 ktime_t starttime = ktime_get();
1256 int error = 0;
1257
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001258 trace_suspend_resume(TPS("dpm_suspend_late"), state.event, true);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001259 mutex_lock(&dpm_list_mtx);
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001260 pm_transition = state;
1261 async_error = 0;
1262
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001263 while (!list_empty(&dpm_suspended_list)) {
1264 struct device *dev = to_device(dpm_suspended_list.prev);
1265
1266 get_device(dev);
1267 mutex_unlock(&dpm_list_mtx);
1268
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001269 error = device_suspend_late(dev);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001270
1271 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki3a17fb32016-05-20 23:09:49 +02001272 if (!list_empty(&dev->power.entry))
1273 list_move(&dev->power.entry, &dpm_late_early_list);
1274
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001275 if (error) {
1276 pm_dev_err(dev, state, " late", error);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001277 dpm_save_failed_dev(dev_name(dev));
1278 put_device(dev);
1279 break;
1280 }
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001281 put_device(dev);
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001282
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001283 if (async_error)
Rafael J. Wysocki52d136c2012-04-29 22:52:19 +02001284 break;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001285 }
1286 mutex_unlock(&dpm_list_mtx);
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001287 async_synchronize_full();
Imre Deak246ef762014-10-24 20:29:09 +03001288 if (!error)
1289 error = async_error;
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001290 if (error) {
1291 suspend_stats.failed_suspend_late++;
1292 dpm_save_failed_step(SUSPEND_SUSPEND_LATE);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001293 dpm_resume_early(resume_event(state));
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001294 } else {
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001295 dpm_show_time(starttime, state, "late");
Liu, Chuanshengde377b32014-02-18 10:28:48 +08001296 }
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001297 trace_suspend_resume(TPS("dpm_suspend_late"), state.event, false);
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001298 return error;
1299}
1300
1301/**
1302 * dpm_suspend_end - Execute "late" and "noirq" device suspend callbacks.
1303 * @state: PM transition of the system being carried out.
1304 */
1305int dpm_suspend_end(pm_message_t state)
1306{
1307 int error = dpm_suspend_late(state);
Colin Cross064b0212012-07-19 10:38:06 +02001308 if (error)
1309 return error;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001310
Colin Cross064b0212012-07-19 10:38:06 +02001311 error = dpm_suspend_noirq(state);
1312 if (error) {
Feng Hong997a0312012-09-19 14:16:00 +02001313 dpm_resume_early(resume_event(state));
Colin Cross064b0212012-07-19 10:38:06 +02001314 return error;
1315 }
1316
1317 return 0;
Rafael J. Wysockicf579df2012-01-29 20:38:29 +01001318}
1319EXPORT_SYMBOL_GPL(dpm_suspend_end);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001320
1321/**
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001322 * legacy_suspend - Execute a legacy (bus or class) suspend callback for device.
Randy Dunlap0a884222010-01-08 14:42:57 -08001323 * @dev: Device to suspend.
1324 * @state: PM transition of the system being carried out.
1325 * @cb: Suspend callback to execute.
Randy Dunlap58c256a2014-07-27 16:17:15 -07001326 * @info: string description of caller.
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001327 */
1328static int legacy_suspend(struct device *dev, pm_message_t state,
Shuah Khan53644672013-07-26 13:30:20 -06001329 int (*cb)(struct device *dev, pm_message_t state),
1330 char *info)
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001331{
1332 int error;
1333 ktime_t calltime;
1334
1335 calltime = initcall_debug_start(dev);
1336
Todd E Brandte8bca472014-06-10 07:31:22 -07001337 trace_device_pm_callback_start(dev, info, state.event);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001338 error = cb(dev, state);
Todd E Brandte8bca472014-06-10 07:31:22 -07001339 trace_device_pm_callback_end(dev, error);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001340 suspend_report_result(cb, error);
1341
Shuah Khan53644672013-07-26 13:30:20 -06001342 initcall_debug_report(dev, calltime, error, state, info);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +01001343
1344 return error;
1345}
1346
1347/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001348 * device_suspend - Execute "suspend" callbacks for given device.
1349 * @dev: Device to handle.
1350 * @state: PM transition of the system being carried out.
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001351 * @async: If true, the device is being suspended asynchronously.
Alan Sterncd59abf2007-09-21 15:36:56 -04001352 */
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001353static int __device_suspend(struct device *dev, pm_message_t state, bool async)
Alan Sterncd59abf2007-09-21 15:36:56 -04001354{
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001355 pm_callback_t callback = NULL;
1356 char *info = NULL;
Alan Sterncd59abf2007-09-21 15:36:56 -04001357 int error = 0;
Benoit Goby70fea602013-10-17 10:48:46 -07001358 DECLARE_DPM_WATCHDOG_ON_STACK(wd);
Alan Sterncd59abf2007-09-21 15:36:56 -04001359
Zhonghui Fu431d4522015-03-18 15:54:27 +01001360 TRACE_DEVICE(dev);
1361 TRACE_SUSPEND(0);
1362
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001363 dpm_wait_for_children(dev, async);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +01001364
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001365 if (async_error)
Mandeep Singh Baines1f758b22012-06-24 23:31:09 +02001366 goto Complete;
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001367
Alan Stern88d26132012-09-19 21:59:02 +02001368 /*
1369 * If a device configured to wake up the system from sleep states
1370 * has been suspended at run time and there's a resume request pending
1371 * for it, this is equivalent to the device signaling wakeup, so the
1372 * system suspend operation should be aborted.
1373 */
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001374 if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
1375 pm_wakeup_event(dev, 0);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001376
Rafael J. Wysockid83f9052010-12-03 23:14:26 +01001377 if (pm_wakeup_pending()) {
1378 async_error = -EBUSY;
Mandeep Singh Baines1f758b22012-06-24 23:31:09 +02001379 goto Complete;
Rafael J. Wysockid83f9052010-12-03 23:14:26 +01001380 }
1381
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001382 if (dev->power.syscore)
1383 goto Complete;
1384
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001385 if (dev->power.direct_complete) {
1386 if (pm_runtime_status_suspended(dev)) {
1387 pm_runtime_disable(dev);
Alan Stern019d8812015-07-15 14:40:06 +02001388 if (pm_runtime_status_suspended(dev))
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001389 goto Complete;
1390
1391 pm_runtime_enable(dev);
1392 }
1393 dev->power.direct_complete = false;
1394 }
1395
Benoit Goby70fea602013-10-17 10:48:46 -07001396 dpm_watchdog_set(&wd, dev);
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001397 device_lock(dev);
1398
Rafael J. Wysocki564b9052011-06-23 01:52:55 +02001399 if (dev->pm_domain) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001400 info = "power domain ";
1401 callback = pm_op(&dev->pm_domain->ops, state);
1402 goto Run;
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001403 }
1404
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001405 if (dev->type && dev->type->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001406 info = "type ";
1407 callback = pm_op(dev->type->pm, state);
1408 goto Run;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001409 }
1410
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001411 if (dev->class) {
1412 if (dev->class->pm) {
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001413 info = "class ";
1414 callback = pm_op(dev->class->pm, state);
1415 goto Run;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001416 } else if (dev->class->suspend) {
1417 pm_dev_dbg(dev, state, "legacy class ");
Shuah Khan53644672013-07-26 13:30:20 -06001418 error = legacy_suspend(dev, state, dev->class->suspend,
1419 "legacy class ");
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001420 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001421 }
Alan Sterncd59abf2007-09-21 15:36:56 -04001422 }
1423
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001424 if (dev->bus) {
1425 if (dev->bus->pm) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001426 info = "bus ";
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001427 callback = pm_op(dev->bus->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001428 } else if (dev->bus->suspend) {
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001429 pm_dev_dbg(dev, state, "legacy bus ");
Shuah Khan53644672013-07-26 13:30:20 -06001430 error = legacy_suspend(dev, state, dev->bus->suspend,
1431 "legacy bus ");
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001432 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001433 }
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001434 }
1435
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001436 Run:
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001437 if (!callback && dev->driver && dev->driver->pm) {
1438 info = "driver ";
1439 callback = pm_op(dev->driver->pm, state);
1440 }
1441
Rafael J. Wysocki9cf519d2011-12-18 00:34:01 +01001442 error = dpm_run_callback(callback, dev, state, info);
1443
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001444 End:
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001445 if (!error) {
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001446 struct device *parent = dev->parent;
1447
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001448 dev->power.is_suspended = true;
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001449 if (parent) {
1450 spin_lock_irq(&parent->power.lock);
1451
1452 dev->parent->power.direct_complete = false;
1453 if (dev->power.wakeup_path
1454 && !dev->parent->power.ignore_children)
1455 dev->parent->power.wakeup_path = true;
1456
1457 spin_unlock_irq(&parent->power.lock);
1458 }
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001459 }
Alan Stern6d0e0e82011-06-18 22:42:09 +02001460
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001461 device_unlock(dev);
Benoit Goby70fea602013-10-17 10:48:46 -07001462 dpm_watchdog_clear(&wd);
Mandeep Singh Baines1f758b22012-06-24 23:31:09 +02001463
1464 Complete:
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001465 complete_all(&dev->power.completion);
Alan Stern88d26132012-09-19 21:59:02 +02001466 if (error)
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001467 async_error = error;
1468
Zhonghui Fu431d4522015-03-18 15:54:27 +01001469 TRACE_SUSPEND(error);
Alan Sterncd59abf2007-09-21 15:36:56 -04001470 return error;
1471}
1472
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001473static void async_suspend(void *data, async_cookie_t cookie)
1474{
1475 struct device *dev = (struct device *)data;
1476 int error;
1477
1478 error = __device_suspend(dev, pm_transition, true);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001479 if (error) {
1480 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001481 pm_dev_err(dev, pm_transition, " async", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001482 }
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001483
1484 put_device(dev);
1485}
1486
1487static int device_suspend(struct device *dev)
1488{
Wolfram Sang16735d02013-11-14 14:32:02 -08001489 reinit_completion(&dev->power.completion);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001490
Zhonghui Fu431d4522015-03-18 15:54:27 +01001491 if (is_async(dev)) {
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001492 get_device(dev);
1493 async_schedule(async_suspend, dev);
1494 return 0;
1495 }
1496
1497 return __device_suspend(dev, pm_transition, false);
1498}
1499
Alan Sterncd59abf2007-09-21 15:36:56 -04001500/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001501 * dpm_suspend - Execute "suspend" callbacks for all non-sysdev devices.
1502 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -04001503 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001504int dpm_suspend(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001505{
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001506 ktime_t starttime = ktime_get();
Alan Sterncd59abf2007-09-21 15:36:56 -04001507 int error = 0;
1508
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001509 trace_suspend_resume(TPS("dpm_suspend"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001510 might_sleep();
1511
Viresh Kumar2f0aea92014-03-04 11:00:26 +08001512 cpufreq_suspend();
1513
Alan Sterncd59abf2007-09-21 15:36:56 -04001514 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001515 pm_transition = state;
1516 async_error = 0;
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001517 while (!list_empty(&dpm_prepared_list)) {
1518 struct device *dev = to_device(dpm_prepared_list.prev);
Alan Sterncd59abf2007-09-21 15:36:56 -04001519
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001520 get_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001521 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001522
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001523 error = device_suspend(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001524
Alan Stern1b3cbec2008-02-29 11:50:22 -05001525 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001526 if (error) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001527 pm_dev_err(dev, state, "", error);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001528 dpm_save_failed_dev(dev_name(dev));
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001529 put_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001530 break;
1531 }
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +01001532 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001533 list_move(&dev->power.entry, &dpm_suspended_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001534 put_device(dev);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001535 if (async_error)
1536 break;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001537 }
1538 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +01001539 async_synchronize_full();
1540 if (!error)
1541 error = async_error;
ShuoX Liu2a77c462011-08-10 23:01:26 +02001542 if (error) {
1543 suspend_stats.failed_suspend++;
1544 dpm_save_failed_step(SUSPEND_SUSPEND);
1545 } else
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +01001546 dpm_show_time(starttime, state, NULL);
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001547 trace_suspend_resume(TPS("dpm_suspend"), state.event, false);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001548 return error;
1549}
1550
1551/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001552 * device_prepare - Prepare a device for system power transition.
1553 * @dev: Device to handle.
1554 * @state: PM transition of the system being carried out.
1555 *
1556 * Execute the ->prepare() callback(s) for given device. No new children of the
1557 * device may be registered after this function has returned.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001558 */
Alan Sternd1616302009-05-24 22:05:42 +02001559static int device_prepare(struct device *dev, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001560{
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001561 int (*callback)(struct device *) = NULL;
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001562 int ret = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001563
Rafael J. Wysockidbf37412012-08-06 01:46:39 +02001564 if (dev->power.syscore)
1565 return 0;
1566
Alan Stern88d26132012-09-19 21:59:02 +02001567 /*
1568 * If a device's parent goes into runtime suspend at the wrong time,
1569 * it won't be possible to resume the device. To prevent this we
1570 * block runtime suspend here, during the prepare phase, and allow
1571 * it again during the complete phase.
1572 */
1573 pm_runtime_get_noresume(dev);
1574
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001575 device_lock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001576
Rafael J. Wysocki4ca46ff2011-10-16 23:34:36 +02001577 dev->power.wakeup_path = device_may_wakeup(dev);
1578
Tomeu Vizosoaa8e54b2016-01-07 16:46:14 +01001579 if (dev->power.no_pm_callbacks) {
1580 ret = 1; /* Let device go direct_complete */
1581 goto unlock;
1582 }
1583
Thierry Redingfba1fbf2016-04-28 14:42:34 +02001584 if (dev->pm_domain)
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001585 callback = dev->pm_domain->ops.prepare;
Thierry Redingfba1fbf2016-04-28 14:42:34 +02001586 else if (dev->type && dev->type->pm)
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001587 callback = dev->type->pm->prepare;
Thierry Redingfba1fbf2016-04-28 14:42:34 +02001588 else if (dev->class && dev->class->pm)
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001589 callback = dev->class->pm->prepare;
Thierry Redingfba1fbf2016-04-28 14:42:34 +02001590 else if (dev->bus && dev->bus->pm)
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001591 callback = dev->bus->pm->prepare;
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001592
Thierry Redingfba1fbf2016-04-28 14:42:34 +02001593 if (!callback && dev->driver && dev->driver->pm)
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001594 callback = dev->driver->pm->prepare;
Rafael J. Wysocki35cd1332011-12-18 00:34:13 +01001595
Todd E Brandt32e8d682015-05-28 12:55:53 -07001596 if (callback)
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001597 ret = callback(dev);
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001598
Tomeu Vizosoaa8e54b2016-01-07 16:46:14 +01001599unlock:
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001600 device_unlock(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001601
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001602 if (ret < 0) {
1603 suspend_report_result(callback, ret);
Ulf Hanssonaa1b9f12013-11-13 15:45:03 +01001604 pm_runtime_put(dev);
Rafael J. Wysockiaae45182014-05-16 02:46:50 +02001605 return ret;
1606 }
1607 /*
1608 * A positive return value from ->prepare() means "this device appears
1609 * to be runtime-suspended and its state is fine, so if it really is
1610 * runtime-suspended, you can leave it in that state provided that you
1611 * will do the same thing with all of its descendants". This only
1612 * applies to suspend transitions, however.
1613 */
1614 spin_lock_irq(&dev->power.lock);
1615 dev->power.direct_complete = ret > 0 && state.event == PM_EVENT_SUSPEND;
1616 spin_unlock_irq(&dev->power.lock);
1617 return 0;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001618}
1619
1620/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001621 * dpm_prepare - Prepare all non-sysdev devices for a system PM transition.
1622 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -04001623 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001624 * Execute the ->prepare() callback(s) for all devices.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001625 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001626int dpm_prepare(pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001627{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001628 int error = 0;
1629
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001630 trace_suspend_resume(TPS("dpm_prepare"), state.event, true);
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001631 might_sleep();
1632
Strashko, Grygorii013c0742015-11-10 11:42:34 +02001633 /*
1634 * Give a chance for the known devices to complete their probes, before
1635 * disable probing of devices. This sync point is important at least
1636 * at boot time + hibernation restore.
1637 */
1638 wait_for_device_probe();
1639 /*
1640 * It is unsafe if probing of devices will happen during suspend or
1641 * hibernation and system behavior will be unpredictable in this case.
1642 * So, let's prohibit device's probing here and defer their probes
1643 * instead. The normal behavior will be restored in dpm_complete().
1644 */
1645 device_block_probing();
1646
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001647 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001648 while (!list_empty(&dpm_list)) {
1649 struct device *dev = to_device(dpm_list.next);
1650
1651 get_device(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001652 mutex_unlock(&dpm_list_mtx);
1653
Todd E Brandt32e8d682015-05-28 12:55:53 -07001654 trace_device_pm_callback_start(dev, "", state.event);
Rafael J. Wysocki1e2ef052011-07-06 10:51:58 +02001655 error = device_prepare(dev, state);
Todd E Brandt32e8d682015-05-28 12:55:53 -07001656 trace_device_pm_callback_end(dev, error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001657
1658 mutex_lock(&dpm_list_mtx);
1659 if (error) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001660 if (error == -EAGAIN) {
1661 put_device(dev);
Sebastian Ott886a7a32009-07-08 13:26:05 +02001662 error = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001663 continue;
1664 }
Rafael J. Wysocki1e752272010-12-03 22:58:05 +01001665 printk(KERN_INFO "PM: Device %s not prepared "
1666 "for power transition: code %d\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +01001667 dev_name(dev), error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001668 put_device(dev);
1669 break;
1670 }
Alan Sternf76b168b2011-06-18 20:22:23 +02001671 dev->power.is_prepared = true;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001672 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001673 list_move_tail(&dev->power.entry, &dpm_prepared_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001674 put_device(dev);
1675 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001676 mutex_unlock(&dpm_list_mtx);
Todd E Brandtbb3632c2014-06-06 05:40:17 -07001677 trace_suspend_resume(TPS("dpm_prepare"), state.event, false);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001678 return error;
1679}
1680
1681/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001682 * dpm_suspend_start - Prepare devices for PM transition and suspend them.
1683 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001684 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001685 * Prepare all non-sysdev devices for system PM transition and execute "suspend"
1686 * callbacks for them.
Alan Sterncd59abf2007-09-21 15:36:56 -04001687 */
Alan Sternd1616302009-05-24 22:05:42 +02001688int dpm_suspend_start(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001689{
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001690 int error;
Alan Sterncd59abf2007-09-21 15:36:56 -04001691
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001692 error = dpm_prepare(state);
ShuoX Liu2a77c462011-08-10 23:01:26 +02001693 if (error) {
1694 suspend_stats.failed_prepare++;
1695 dpm_save_failed_step(SUSPEND_PREPARE);
1696 } else
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001697 error = dpm_suspend(state);
Alan Sterncd59abf2007-09-21 15:36:56 -04001698 return error;
Alan Sterncd59abf2007-09-21 15:36:56 -04001699}
Alan Sternd1616302009-05-24 22:05:42 +02001700EXPORT_SYMBOL_GPL(dpm_suspend_start);
Alan Sterncd59abf2007-09-21 15:36:56 -04001701
1702void __suspend_report_result(const char *function, void *fn, int ret)
1703{
Bjorn Helgaasc80cfb02008-10-15 22:01:35 -07001704 if (ret)
1705 printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret);
Alan Sterncd59abf2007-09-21 15:36:56 -04001706}
1707EXPORT_SYMBOL_GPL(__suspend_report_result);
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001708
1709/**
1710 * device_pm_wait_for_dev - Wait for suspend/resume of a device to complete.
1711 * @dev: Device to wait for.
1712 * @subordinate: Device that needs to wait for @dev.
1713 */
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001714int device_pm_wait_for_dev(struct device *subordinate, struct device *dev)
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001715{
1716 dpm_wait(dev, subordinate->power.async_suspend);
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001717 return async_error;
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001718}
1719EXPORT_SYMBOL_GPL(device_pm_wait_for_dev);
Ming Leidfe32122012-08-17 22:06:59 +08001720
1721/**
1722 * dpm_for_each_dev - device iterator.
1723 * @data: data for the callback.
1724 * @fn: function to be called for each device.
1725 *
1726 * Iterate over devices in dpm_list, and call @fn for each device,
1727 * passing it @data.
1728 */
1729void dpm_for_each_dev(void *data, void (*fn)(struct device *, void *))
1730{
1731 struct device *dev;
1732
1733 if (!fn)
1734 return;
1735
1736 device_pm_lock();
1737 list_for_each_entry(dev, &dpm_list, power.entry)
1738 fn(dev, data);
1739 device_pm_unlock();
1740}
1741EXPORT_SYMBOL_GPL(dpm_for_each_dev);
Tomeu Vizosoaa8e54b2016-01-07 16:46:14 +01001742
1743static bool pm_ops_is_empty(const struct dev_pm_ops *ops)
1744{
1745 if (!ops)
1746 return true;
1747
1748 return !ops->prepare &&
1749 !ops->suspend &&
1750 !ops->suspend_late &&
1751 !ops->suspend_noirq &&
1752 !ops->resume_noirq &&
1753 !ops->resume_early &&
1754 !ops->resume &&
1755 !ops->complete;
1756}
1757
1758void device_pm_check_callbacks(struct device *dev)
1759{
1760 spin_lock_irq(&dev->power.lock);
1761 dev->power.no_pm_callbacks =
1762 (!dev->bus || pm_ops_is_empty(dev->bus->pm)) &&
1763 (!dev->class || pm_ops_is_empty(dev->class->pm)) &&
1764 (!dev->type || pm_ops_is_empty(dev->type->pm)) &&
1765 (!dev->pm_domain || pm_ops_is_empty(&dev->pm_domain->ops)) &&
1766 (!dev->driver || pm_ops_is_empty(dev->driver->pm));
1767 spin_unlock_irq(&dev->power.lock);
1768}