blob: 4b65d5c64fd260846a442e941fb5b0a5f751cf01 [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>
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -070022#include <linux/mutex.h>
Alan Sterncd59abf2007-09-21 15:36:56 -040023#include <linux/pm.h>
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +020024#include <linux/pm_runtime.h>
Alan Sterncd59abf2007-09-21 15:36:56 -040025#include <linux/resume-trace.h>
Rafael J. Wysocki2ed8d2b2009-03-16 22:34:06 +010026#include <linux/interrupt.h>
Arjan van de Venf2511772009-12-13 20:29:01 +010027#include <linux/sched.h>
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +010028#include <linux/async.h>
Rafael J. Wysocki1e752272010-12-03 22:58:05 +010029#include <linux/suspend.h>
San Mehat9272a142009-08-13 09:40:42 -070030#include <linux/timer.h>
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -070031
Alan Sterncd59abf2007-09-21 15:36:56 -040032#include "../base.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070033#include "power.h"
34
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010035/*
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020036 * The entries in the dpm_list list are in a depth first order, simply
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010037 * because children are guaranteed to be discovered after parents, and
38 * are inserted at the back of the list on discovery.
39 *
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -080040 * Since device_pm_add() may be called with a device lock held,
41 * we must never try to acquire a device lock while holding
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010042 * dpm_list_mutex.
43 */
44
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020045LIST_HEAD(dpm_list);
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +010046LIST_HEAD(dpm_prepared_list);
47LIST_HEAD(dpm_suspended_list);
48LIST_HEAD(dpm_noirq_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -070049
Alan Sterncd59abf2007-09-21 15:36:56 -040050static DEFINE_MUTEX(dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +010051static pm_message_t pm_transition;
Linus Torvalds1da177e2005-04-16 15:20:36 -070052
San Mehat9272a142009-08-13 09:40:42 -070053static void dpm_drv_timeout(unsigned long data);
Benoit Goby8e42bee2011-01-26 18:28:33 -080054struct dpm_drv_wd_data {
Benoit Goby34dcf172011-01-21 15:53:44 -080055 struct device *dev;
56 struct task_struct *tsk;
Benoit Goby8e42bee2011-01-26 18:28:33 -080057};
San Mehat9272a142009-08-13 09:40:42 -070058
Rafael J. Wysocki098dff72010-09-22 22:10:57 +020059static int async_error;
60
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020061/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +020062 * device_pm_init - Initialize the PM-related part of a device object.
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +020063 * @dev: Device object being initialized.
64 */
65void device_pm_init(struct device *dev)
66{
Rafael J. Wysockib8c76f62010-12-16 00:51:21 +010067 dev->power.in_suspend = false;
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +010068 init_completion(&dev->power.completion);
Colin Cross152e1d52010-09-03 01:24:07 +020069 complete_all(&dev->power.completion);
Rafael J. Wysocki074037e2010-09-22 22:09:10 +020070 dev->power.wakeup = NULL;
71 spin_lock_init(&dev->power.lock);
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +020072 pm_runtime_init(dev);
Rafael J. Wysocki22110fa2011-04-26 11:33:09 +020073 INIT_LIST_HEAD(&dev->power.entry);
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +020074}
75
76/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +020077 * device_pm_lock - Lock the list of active devices used by the PM core.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020078 */
79void device_pm_lock(void)
80{
81 mutex_lock(&dpm_list_mtx);
82}
83
84/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +020085 * device_pm_unlock - Unlock the list of active devices used by the PM core.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020086 */
87void device_pm_unlock(void)
88{
89 mutex_unlock(&dpm_list_mtx);
90}
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010091
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010092/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +020093 * device_pm_add - Add a device to the PM core's list of active devices.
94 * @dev: Device to add to the list.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010095 */
Alan Stern3b98aea2008-08-07 13:06:12 -040096void device_pm_add(struct device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -070097{
Linus Torvalds1da177e2005-04-16 15:20:36 -070098 pr_debug("PM: Adding info for %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +010099 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700100 mutex_lock(&dpm_list_mtx);
Rafael J. Wysockib64959e2010-12-16 17:11:45 +0100101 if (dev->parent && dev->parent->power.in_suspend)
102 dev_warn(dev, "parent %s should not be sleeping\n",
103 dev_name(dev->parent));
Alan Stern3b98aea2008-08-07 13:06:12 -0400104 list_add_tail(&dev->power.entry, &dpm_list);
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700105 mutex_unlock(&dpm_list_mtx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700106}
107
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100108/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200109 * device_pm_remove - Remove a device from the PM core's list of active devices.
110 * @dev: Device to be removed from the list.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100111 */
Rafael J. Wysocki9cddad72007-06-13 15:53:34 +0200112void device_pm_remove(struct device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700113{
114 pr_debug("PM: Removing info for %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100115 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100116 complete_all(&dev->power.completion);
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700117 mutex_lock(&dpm_list_mtx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700118 list_del_init(&dev->power.entry);
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700119 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki074037e2010-09-22 22:09:10 +0200120 device_wakeup_disable(dev);
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +0200121 pm_runtime_remove(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100122}
123
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200124/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200125 * device_pm_move_before - Move device in the PM core's list of active devices.
126 * @deva: Device to move in dpm_list.
127 * @devb: Device @deva should come before.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100128 */
129void device_pm_move_before(struct device *deva, struct device *devb)
130{
131 pr_debug("PM: Moving %s:%s before %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100132 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
133 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
Cornelia Huckffa6a702009-03-04 12:44:00 +0100134 /* Delete deva from dpm_list and reinsert before devb. */
135 list_move_tail(&deva->power.entry, &devb->power.entry);
136}
137
138/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200139 * device_pm_move_after - Move device in the PM core's list of active devices.
140 * @deva: Device to move in dpm_list.
141 * @devb: Device @deva should come after.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100142 */
143void device_pm_move_after(struct device *deva, struct device *devb)
144{
145 pr_debug("PM: Moving %s:%s after %s:%s\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100146 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
147 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
Cornelia Huckffa6a702009-03-04 12:44:00 +0100148 /* Delete deva from dpm_list and reinsert after devb. */
149 list_move(&deva->power.entry, &devb->power.entry);
150}
151
152/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200153 * device_pm_move_last - Move device to end of the PM core's list of devices.
154 * @dev: Device to move in dpm_list.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100155 */
156void device_pm_move_last(struct device *dev)
157{
158 pr_debug("PM: Moving %s:%s to end of list\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100159 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
Cornelia Huckffa6a702009-03-04 12:44:00 +0100160 list_move_tail(&dev->power.entry, &dpm_list);
161}
162
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100163static ktime_t initcall_debug_start(struct device *dev)
164{
165 ktime_t calltime = ktime_set(0, 0);
166
167 if (initcall_debug) {
168 pr_info("calling %s+ @ %i\n",
169 dev_name(dev), task_pid_nr(current));
170 calltime = ktime_get();
171 }
172
173 return calltime;
174}
175
176static void initcall_debug_report(struct device *dev, ktime_t calltime,
177 int error)
178{
179 ktime_t delta, rettime;
180
181 if (initcall_debug) {
182 rettime = ktime_get();
183 delta = ktime_sub(rettime, calltime);
184 pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
185 error, (unsigned long long)ktime_to_ns(delta) >> 10);
186 }
187}
188
Cornelia Huckffa6a702009-03-04 12:44:00 +0100189/**
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100190 * dpm_wait - Wait for a PM operation to complete.
191 * @dev: Device to wait for.
192 * @async: If unset, wait only if the device's power.async_suspend flag is set.
193 */
194static void dpm_wait(struct device *dev, bool async)
195{
196 if (!dev)
197 return;
198
Rafael J. Wysocki0e06b4a2010-01-23 22:25:15 +0100199 if (async || (pm_async_enabled && dev->power.async_suspend))
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100200 wait_for_completion(&dev->power.completion);
201}
202
203static int dpm_wait_fn(struct device *dev, void *async_ptr)
204{
205 dpm_wait(dev, *((bool *)async_ptr));
206 return 0;
207}
208
209static void dpm_wait_for_children(struct device *dev, bool async)
210{
211 device_for_each_child(dev, &async, dpm_wait_fn);
212}
213
214/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200215 * pm_op - Execute the PM operation appropriate for given PM event.
216 * @dev: Device to handle.
217 * @ops: PM operations to choose from.
218 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200219 */
Dmitry Torokhovd9ab7712009-07-22 00:37:25 +0200220static int pm_op(struct device *dev,
221 const struct dev_pm_ops *ops,
222 pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200223{
224 int error = 0;
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100225 ktime_t calltime;
Arjan van de Venf2511772009-12-13 20:29:01 +0100226
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100227 calltime = initcall_debug_start(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200228
229 switch (state.event) {
230#ifdef CONFIG_SUSPEND
231 case PM_EVENT_SUSPEND:
232 if (ops->suspend) {
233 error = ops->suspend(dev);
234 suspend_report_result(ops->suspend, error);
235 }
236 break;
237 case PM_EVENT_RESUME:
238 if (ops->resume) {
239 error = ops->resume(dev);
240 suspend_report_result(ops->resume, error);
241 }
242 break;
243#endif /* CONFIG_SUSPEND */
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200244#ifdef CONFIG_HIBERNATE_CALLBACKS
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200245 case PM_EVENT_FREEZE:
246 case PM_EVENT_QUIESCE:
247 if (ops->freeze) {
248 error = ops->freeze(dev);
249 suspend_report_result(ops->freeze, error);
250 }
251 break;
252 case PM_EVENT_HIBERNATE:
253 if (ops->poweroff) {
254 error = ops->poweroff(dev);
255 suspend_report_result(ops->poweroff, error);
256 }
257 break;
258 case PM_EVENT_THAW:
259 case PM_EVENT_RECOVER:
260 if (ops->thaw) {
261 error = ops->thaw(dev);
262 suspend_report_result(ops->thaw, error);
263 }
264 break;
265 case PM_EVENT_RESTORE:
266 if (ops->restore) {
267 error = ops->restore(dev);
268 suspend_report_result(ops->restore, error);
269 }
270 break;
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200271#endif /* CONFIG_HIBERNATE_CALLBACKS */
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200272 default:
273 error = -EINVAL;
274 }
Arjan van de Venf2511772009-12-13 20:29:01 +0100275
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100276 initcall_debug_report(dev, calltime, error);
Arjan van de Venf2511772009-12-13 20:29:01 +0100277
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200278 return error;
279}
280
281/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200282 * pm_noirq_op - Execute the PM operation appropriate for given PM event.
283 * @dev: Device to handle.
284 * @ops: PM operations to choose from.
285 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200286 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200287 * The driver of @dev will not receive interrupts while this function is being
288 * executed.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200289 */
Dmitry Torokhovd9ab7712009-07-22 00:37:25 +0200290static int pm_noirq_op(struct device *dev,
291 const struct dev_pm_ops *ops,
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200292 pm_message_t state)
293{
294 int error = 0;
Rafael J. Wysocki2cbb3ce2010-12-15 00:17:29 +0100295 ktime_t calltime = ktime_set(0, 0), delta, rettime;
Arjan van de Venf2511772009-12-13 20:29:01 +0100296
297 if (initcall_debug) {
Rafael J. Wysocki8cc6b392010-01-23 22:03:29 +0100298 pr_info("calling %s+ @ %i, parent: %s\n",
299 dev_name(dev), task_pid_nr(current),
300 dev->parent ? dev_name(dev->parent) : "none");
Arjan van de Venf2511772009-12-13 20:29:01 +0100301 calltime = ktime_get();
302 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200303
304 switch (state.event) {
305#ifdef CONFIG_SUSPEND
306 case PM_EVENT_SUSPEND:
307 if (ops->suspend_noirq) {
308 error = ops->suspend_noirq(dev);
309 suspend_report_result(ops->suspend_noirq, error);
310 }
311 break;
312 case PM_EVENT_RESUME:
313 if (ops->resume_noirq) {
314 error = ops->resume_noirq(dev);
315 suspend_report_result(ops->resume_noirq, error);
316 }
317 break;
318#endif /* CONFIG_SUSPEND */
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200319#ifdef CONFIG_HIBERNATE_CALLBACKS
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200320 case PM_EVENT_FREEZE:
321 case PM_EVENT_QUIESCE:
322 if (ops->freeze_noirq) {
323 error = ops->freeze_noirq(dev);
324 suspend_report_result(ops->freeze_noirq, error);
325 }
326 break;
327 case PM_EVENT_HIBERNATE:
328 if (ops->poweroff_noirq) {
329 error = ops->poweroff_noirq(dev);
330 suspend_report_result(ops->poweroff_noirq, error);
331 }
332 break;
333 case PM_EVENT_THAW:
334 case PM_EVENT_RECOVER:
335 if (ops->thaw_noirq) {
336 error = ops->thaw_noirq(dev);
337 suspend_report_result(ops->thaw_noirq, error);
338 }
339 break;
340 case PM_EVENT_RESTORE:
341 if (ops->restore_noirq) {
342 error = ops->restore_noirq(dev);
343 suspend_report_result(ops->restore_noirq, error);
344 }
345 break;
Rafael J. Wysocki1f112ce2011-04-11 22:54:42 +0200346#endif /* CONFIG_HIBERNATE_CALLBACKS */
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200347 default:
348 error = -EINVAL;
349 }
Arjan van de Venf2511772009-12-13 20:29:01 +0100350
351 if (initcall_debug) {
352 rettime = ktime_get();
353 delta = ktime_sub(rettime, calltime);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100354 printk("initcall %s_i+ returned %d after %Ld usecs\n",
355 dev_name(dev), error,
356 (unsigned long long)ktime_to_ns(delta) >> 10);
Arjan van de Venf2511772009-12-13 20:29:01 +0100357 }
358
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200359 return error;
360}
361
362static char *pm_verb(int event)
363{
364 switch (event) {
365 case PM_EVENT_SUSPEND:
366 return "suspend";
367 case PM_EVENT_RESUME:
368 return "resume";
369 case PM_EVENT_FREEZE:
370 return "freeze";
371 case PM_EVENT_QUIESCE:
372 return "quiesce";
373 case PM_EVENT_HIBERNATE:
374 return "hibernate";
375 case PM_EVENT_THAW:
376 return "thaw";
377 case PM_EVENT_RESTORE:
378 return "restore";
379 case PM_EVENT_RECOVER:
380 return "recover";
381 default:
382 return "(unknown PM event)";
383 }
384}
385
386static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info)
387{
388 dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event),
389 ((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ?
390 ", may wakeup" : "");
391}
392
393static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
394 int error)
395{
396 printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +0100397 dev_name(dev), pm_verb(state.event), info, error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200398}
399
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100400static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
401{
402 ktime_t calltime;
Kevin Cernekee0702d9e2010-09-20 22:32:10 +0200403 u64 usecs64;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100404 int usecs;
405
406 calltime = ktime_get();
407 usecs64 = ktime_to_ns(ktime_sub(calltime, starttime));
408 do_div(usecs64, NSEC_PER_USEC);
409 usecs = usecs64;
410 if (usecs == 0)
411 usecs = 1;
412 pr_info("PM: %s%s%s of devices complete after %ld.%03ld msecs\n",
413 info ?: "", info ? " " : "", pm_verb(state.event),
414 usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
415}
416
Alan Sterncd59abf2007-09-21 15:36:56 -0400417/*------------------------- Resume routines -------------------------*/
418
419/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200420 * device_resume_noirq - Execute an "early resume" callback for given device.
421 * @dev: Device to handle.
422 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -0400423 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200424 * The driver of @dev will not receive interrupts while this function is being
425 * executed.
Alan Sterncd59abf2007-09-21 15:36:56 -0400426 */
Alan Sternd1616302009-05-24 22:05:42 +0200427static int device_resume_noirq(struct device *dev, pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400428{
429 int error = 0;
430
431 TRACE_DEVICE(dev);
432 TRACE_RESUME(0);
433
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +0100434 if (dev->pwr_domain) {
435 pm_dev_dbg(dev, state, "EARLY power domain ");
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200436 error = pm_noirq_op(dev, &dev->pwr_domain->ops, state);
437 } else if (dev->type && dev->type->pm) {
Dominik Brodowskie7176a32010-03-15 21:43:11 +0100438 pm_dev_dbg(dev, state, "EARLY type ");
439 error = pm_noirq_op(dev, dev->type->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100440 } else if (dev->class && dev->class->pm) {
Dominik Brodowskie7176a32010-03-15 21:43:11 +0100441 pm_dev_dbg(dev, state, "EARLY class ");
442 error = pm_noirq_op(dev, dev->class->pm, state);
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100443 } else if (dev->bus && dev->bus->pm) {
444 pm_dev_dbg(dev, state, "EARLY ");
445 error = pm_noirq_op(dev, dev->bus->pm, state);
Dominik Brodowskie7176a32010-03-15 21:43:11 +0100446 }
447
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100448 TRACE_RESUME(error);
449 return error;
450}
451
452/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200453 * dpm_resume_noirq - Execute "early resume" callbacks for non-sysdev devices.
454 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100455 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200456 * Call the "noirq" resume handlers for all devices marked as DPM_OFF_IRQ and
457 * enable device drivers to receive interrupts.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100458 */
Alan Sternd1616302009-05-24 22:05:42 +0200459void dpm_resume_noirq(pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100460{
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100461 ktime_t starttime = ktime_get();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100462
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200463 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100464 while (!list_empty(&dpm_noirq_list)) {
465 struct device *dev = to_device(dpm_noirq_list.next);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100466 int error;
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100467
468 get_device(dev);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100469 list_move_tail(&dev->power.entry, &dpm_suspended_list);
470 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100471
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100472 error = device_resume_noirq(dev, state);
473 if (error)
474 pm_dev_err(dev, state, " early", error);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100475
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100476 mutex_lock(&dpm_list_mtx);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100477 put_device(dev);
478 }
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200479 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100480 dpm_show_time(starttime, state, "early");
Rafael J. Wysocki2ed8d2b2009-03-16 22:34:06 +0100481 resume_device_irqs();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100482}
Alan Sternd1616302009-05-24 22:05:42 +0200483EXPORT_SYMBOL_GPL(dpm_resume_noirq);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100484
485/**
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100486 * legacy_resume - Execute a legacy (bus or class) resume callback for device.
Randy Dunlap0a884222010-01-08 14:42:57 -0800487 * @dev: Device to resume.
488 * @cb: Resume callback to execute.
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100489 */
490static int legacy_resume(struct device *dev, int (*cb)(struct device *dev))
491{
492 int error;
493 ktime_t calltime;
494
495 calltime = initcall_debug_start(dev);
496
497 error = cb(dev);
498 suspend_report_result(cb, error);
499
500 initcall_debug_report(dev, calltime, error);
501
502 return error;
503}
504
505/**
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100506 * device_resume - Execute "resume" callbacks for given device.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200507 * @dev: Device to handle.
508 * @state: PM transition of the system being carried out.
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100509 * @async: If true, the device is being resumed asynchronously.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100510 */
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100511static int device_resume(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100512{
513 int error = 0;
514
515 TRACE_DEVICE(dev);
516 TRACE_RESUME(0);
Alan Sterncd59abf2007-09-21 15:36:56 -0400517
Benoit Gobya0f07aa2010-12-13 15:27:06 -0800518 if (dev->parent && dev->parent->power.in_suspend)
Colin Crossfa92a3d2010-09-01 18:35:55 -0700519 dpm_wait(dev->parent, async);
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800520 device_lock(dev);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100521
Rafael J. Wysockib8c76f62010-12-16 00:51:21 +0100522 dev->power.in_suspend = false;
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100523
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +0100524 if (dev->pwr_domain) {
525 pm_dev_dbg(dev, state, "power domain ");
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200526 error = pm_op(dev, &dev->pwr_domain->ops, state);
527 goto End;
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +0100528 }
529
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100530 if (dev->type && dev->type->pm) {
531 pm_dev_dbg(dev, state, "type ");
532 error = pm_op(dev, dev->type->pm, state);
533 goto End;
534 }
535
536 if (dev->class) {
537 if (dev->class->pm) {
538 pm_dev_dbg(dev, state, "class ");
539 error = pm_op(dev, dev->class->pm, state);
540 goto End;
541 } else if (dev->class->resume) {
542 pm_dev_dbg(dev, state, "legacy class ");
543 error = legacy_resume(dev, dev->class->resume);
544 goto End;
545 }
546 }
547
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200548 if (dev->bus) {
549 if (dev->bus->pm) {
550 pm_dev_dbg(dev, state, "");
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200551 error = pm_op(dev, dev->bus->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200552 } else if (dev->bus->resume) {
553 pm_dev_dbg(dev, state, "legacy ");
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100554 error = legacy_resume(dev, dev->bus->resume);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200555 }
Alan Sterncd59abf2007-09-21 15:36:56 -0400556 }
557
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200558 End:
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800559 device_unlock(dev);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100560 complete_all(&dev->power.completion);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100561
Alan Sterncd59abf2007-09-21 15:36:56 -0400562 TRACE_RESUME(error);
563 return error;
564}
565
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100566static void async_resume(void *data, async_cookie_t cookie)
567{
568 struct device *dev = (struct device *)data;
569 int error;
570
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100571 error = device_resume(dev, pm_transition, true);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100572 if (error)
573 pm_dev_err(dev, pm_transition, " async", error);
574 put_device(dev);
575}
576
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100577static bool is_async(struct device *dev)
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100578{
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100579 return dev->power.async_suspend && pm_async_enabled
580 && !pm_trace_is_enabled();
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100581}
582
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100583/**
San Mehat9272a142009-08-13 09:40:42 -0700584 * dpm_drv_timeout - Driver suspend / resume watchdog handler
585 * @data: struct device which timed out
586 *
587 * Called when a driver has timed out suspending or resuming.
588 * There's not much we can do here to recover so
589 * BUG() out for a crash-dump
590 *
591 */
592static void dpm_drv_timeout(unsigned long data)
593{
Benoit Goby8e42bee2011-01-26 18:28:33 -0800594 struct dpm_drv_wd_data *wd_data = (void *)data;
595 struct device *dev = wd_data->dev;
596 struct task_struct *tsk = wd_data->tsk;
San Mehat9272a142009-08-13 09:40:42 -0700597
598 printk(KERN_EMERG "**** DPM device timeout: %s (%s)\n", dev_name(dev),
599 (dev->driver ? dev->driver->name : "no driver"));
Benoit Goby34dcf172011-01-21 15:53:44 -0800600
601 printk(KERN_EMERG "dpm suspend stack:\n");
602 show_stack(tsk, NULL);
603
San Mehat9272a142009-08-13 09:40:42 -0700604 BUG();
605}
606
607/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200608 * dpm_resume - Execute "resume" callbacks for non-sysdev devices.
609 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100610 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200611 * Execute the appropriate "resume" callback for all devices whose status
612 * indicates that they are suspended.
Alan Sterncd59abf2007-09-21 15:36:56 -0400613 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200614void dpm_resume(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400615{
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100616 struct device *dev;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100617 ktime_t starttime = ktime_get();
Alan Sterncd59abf2007-09-21 15:36:56 -0400618
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200619 might_sleep();
620
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200621 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100622 pm_transition = state;
Rafael J. Wysocki098dff72010-09-22 22:10:57 +0200623 async_error = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200624
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100625 list_for_each_entry(dev, &dpm_suspended_list, power.entry) {
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100626 INIT_COMPLETION(dev->power.completion);
627 if (is_async(dev)) {
628 get_device(dev);
629 async_schedule(async_resume, dev);
630 }
631 }
632
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100633 while (!list_empty(&dpm_suspended_list)) {
634 dev = to_device(dpm_suspended_list.next);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200635 get_device(dev);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100636 if (!is_async(dev)) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200637 int error;
638
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200639 mutex_unlock(&dpm_list_mtx);
640
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100641 error = device_resume(dev, state, false);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200642 if (error)
643 pm_dev_err(dev, state, "", error);
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100644
645 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200646 }
647 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100648 list_move_tail(&dev->power.entry, &dpm_prepared_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200649 put_device(dev);
Alan Sterncd59abf2007-09-21 15:36:56 -0400650 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200651 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100652 async_synchronize_full();
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100653 dpm_show_time(starttime, state, NULL);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200654}
655
656/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200657 * device_complete - Complete a PM transition for given device.
658 * @dev: Device to handle.
659 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200660 */
Alan Sternd1616302009-05-24 22:05:42 +0200661static void device_complete(struct device *dev, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200662{
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800663 device_lock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200664
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200665 if (dev->pwr_domain) {
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +0100666 pm_dev_dbg(dev, state, "completing power domain ");
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200667 if (dev->pwr_domain->ops.complete)
668 dev->pwr_domain->ops.complete(dev);
669 } else if (dev->type && dev->type->pm) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200670 pm_dev_dbg(dev, state, "completing type ");
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100671 if (dev->type->pm->complete)
672 dev->type->pm->complete(dev);
673 } else if (dev->class && dev->class->pm) {
674 pm_dev_dbg(dev, state, "completing class ");
675 if (dev->class->pm->complete)
676 dev->class->pm->complete(dev);
677 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200678 pm_dev_dbg(dev, state, "completing ");
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100679 if (dev->bus->pm->complete)
680 dev->bus->pm->complete(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200681 }
682
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800683 device_unlock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200684}
685
686/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200687 * dpm_complete - Complete a PM transition for all non-sysdev devices.
688 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200689 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200690 * Execute the ->complete() callbacks for all devices whose PM status is not
691 * DPM_ON (this allows new devices to be registered).
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200692 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200693void dpm_complete(pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200694{
695 struct list_head list;
696
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200697 might_sleep();
698
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200699 INIT_LIST_HEAD(&list);
700 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100701 while (!list_empty(&dpm_prepared_list)) {
702 struct device *dev = to_device(dpm_prepared_list.prev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200703
704 get_device(dev);
Rafael J. Wysockib8c76f62010-12-16 00:51:21 +0100705 dev->power.in_suspend = false;
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100706 list_move(&dev->power.entry, &list);
707 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200708
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100709 device_complete(dev, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200710
Rafael J. Wysocki5b219a52010-12-16 00:51:08 +0100711 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200712 put_device(dev);
713 }
714 list_splice(&list, &dpm_list);
Alan Sterncd59abf2007-09-21 15:36:56 -0400715 mutex_unlock(&dpm_list_mtx);
716}
717
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100718/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200719 * dpm_resume_end - Execute "resume" callbacks and complete system transition.
720 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -0400721 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200722 * Execute "resume" callbacks for all devices and complete the PM transition of
723 * the system.
Alan Sterncd59abf2007-09-21 15:36:56 -0400724 */
Alan Sternd1616302009-05-24 22:05:42 +0200725void dpm_resume_end(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400726{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200727 dpm_resume(state);
728 dpm_complete(state);
Alan Sterncd59abf2007-09-21 15:36:56 -0400729}
Alan Sternd1616302009-05-24 22:05:42 +0200730EXPORT_SYMBOL_GPL(dpm_resume_end);
Alan Sterncd59abf2007-09-21 15:36:56 -0400731
732
Alan Sterncd59abf2007-09-21 15:36:56 -0400733/*------------------------- Suspend routines -------------------------*/
734
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200735/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200736 * resume_event - Return a "resume" message for given "suspend" sleep state.
737 * @sleep_state: PM message representing a sleep state.
738 *
739 * Return a PM message representing the resume event corresponding to given
740 * sleep state.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200741 */
742static pm_message_t resume_event(pm_message_t sleep_state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400743{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200744 switch (sleep_state.event) {
745 case PM_EVENT_SUSPEND:
746 return PMSG_RESUME;
747 case PM_EVENT_FREEZE:
748 case PM_EVENT_QUIESCE:
749 return PMSG_RECOVER;
750 case PM_EVENT_HIBERNATE:
751 return PMSG_RESTORE;
Alan Sterncd59abf2007-09-21 15:36:56 -0400752 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200753 return PMSG_ON;
Alan Sterncd59abf2007-09-21 15:36:56 -0400754}
755
756/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200757 * device_suspend_noirq - Execute a "late suspend" callback for given device.
758 * @dev: Device to handle.
759 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100760 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200761 * The driver of @dev will not receive interrupts while this function is being
762 * executed.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100763 */
Alan Sternd1616302009-05-24 22:05:42 +0200764static int device_suspend_noirq(struct device *dev, pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100765{
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100766 int error;
Dominik Brodowskie7176a32010-03-15 21:43:11 +0100767
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200768 if (dev->pwr_domain) {
769 pm_dev_dbg(dev, state, "LATE power domain ");
770 error = pm_noirq_op(dev, &dev->pwr_domain->ops, state);
771 if (error)
772 return error;
773 } else if (dev->type && dev->type->pm) {
Dominik Brodowskie7176a32010-03-15 21:43:11 +0100774 pm_dev_dbg(dev, state, "LATE type ");
775 error = pm_noirq_op(dev, dev->type->pm, state);
776 if (error)
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100777 return error;
778 } else if (dev->class && dev->class->pm) {
779 pm_dev_dbg(dev, state, "LATE class ");
780 error = pm_noirq_op(dev, dev->class->pm, state);
781 if (error)
782 return error;
783 } else if (dev->bus && dev->bus->pm) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200784 pm_dev_dbg(dev, state, "LATE ");
785 error = pm_noirq_op(dev, dev->bus->pm, state);
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +0100786 if (error)
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100787 return error;
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +0100788 }
789
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100790 return 0;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100791}
792
793/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200794 * dpm_suspend_noirq - Execute "late suspend" callbacks for non-sysdev devices.
795 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100796 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200797 * Prevent device drivers from receiving interrupts and call the "noirq" suspend
798 * handlers for all non-sysdev devices.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100799 */
Alan Sternd1616302009-05-24 22:05:42 +0200800int dpm_suspend_noirq(pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100801{
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100802 ktime_t starttime = ktime_get();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100803 int error = 0;
804
Rafael J. Wysocki2ed8d2b2009-03-16 22:34:06 +0100805 suspend_device_irqs();
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200806 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100807 while (!list_empty(&dpm_suspended_list)) {
808 struct device *dev = to_device(dpm_suspended_list.prev);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100809
810 get_device(dev);
811 mutex_unlock(&dpm_list_mtx);
812
Alan Sternd1616302009-05-24 22:05:42 +0200813 error = device_suspend_noirq(dev, state);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100814
815 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100816 if (error) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200817 pm_dev_err(dev, state, " late", error);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100818 put_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100819 break;
820 }
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100821 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100822 list_move(&dev->power.entry, &dpm_noirq_list);
Rafael J. Wysockid08a5ac2010-11-11 01:50:53 +0100823 put_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100824 }
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200825 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100826 if (error)
Alan Sternd1616302009-05-24 22:05:42 +0200827 dpm_resume_noirq(resume_event(state));
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100828 else
829 dpm_show_time(starttime, state, "late");
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100830 return error;
831}
Alan Sternd1616302009-05-24 22:05:42 +0200832EXPORT_SYMBOL_GPL(dpm_suspend_noirq);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100833
834/**
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100835 * legacy_suspend - Execute a legacy (bus or class) suspend callback for device.
Randy Dunlap0a884222010-01-08 14:42:57 -0800836 * @dev: Device to suspend.
837 * @state: PM transition of the system being carried out.
838 * @cb: Suspend callback to execute.
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100839 */
840static int legacy_suspend(struct device *dev, pm_message_t state,
841 int (*cb)(struct device *dev, pm_message_t state))
842{
843 int error;
844 ktime_t calltime;
845
846 calltime = initcall_debug_start(dev);
847
848 error = cb(dev, state);
849 suspend_report_result(cb, error);
850
851 initcall_debug_report(dev, calltime, error);
852
853 return error;
854}
855
856/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200857 * device_suspend - Execute "suspend" callbacks for given device.
858 * @dev: Device to handle.
859 * @state: PM transition of the system being carried out.
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100860 * @async: If true, the device is being suspended asynchronously.
Alan Sterncd59abf2007-09-21 15:36:56 -0400861 */
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100862static int __device_suspend(struct device *dev, pm_message_t state, bool async)
Alan Sterncd59abf2007-09-21 15:36:56 -0400863{
864 int error = 0;
Benoit Goby8e42bee2011-01-26 18:28:33 -0800865 struct timer_list timer;
866 struct dpm_drv_wd_data data;
Alan Sterncd59abf2007-09-21 15:36:56 -0400867
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100868 dpm_wait_for_children(dev, async);
Benoit Goby8e42bee2011-01-26 18:28:33 -0800869
870 data.dev = dev;
871 data.tsk = get_current();
872 init_timer_on_stack(&timer);
873 timer.expires = jiffies + HZ * 3;
874 timer.function = dpm_drv_timeout;
875 timer.data = (unsigned long)&data;
876 add_timer(&timer);
877
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800878 device_lock(dev);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100879
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100880 if (async_error)
881 goto End;
882
Rafael J. Wysockid83f9052010-12-03 23:14:26 +0100883 if (pm_wakeup_pending()) {
884 async_error = -EBUSY;
885 goto End;
886 }
887
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200888 if (dev->pwr_domain) {
889 pm_dev_dbg(dev, state, "power domain ");
890 error = pm_op(dev, &dev->pwr_domain->ops, state);
891 goto End;
892 }
893
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100894 if (dev->type && dev->type->pm) {
895 pm_dev_dbg(dev, state, "type ");
896 error = pm_op(dev, dev->type->pm, state);
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200897 goto End;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +0100898 }
899
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200900 if (dev->class) {
901 if (dev->class->pm) {
902 pm_dev_dbg(dev, state, "class ");
903 error = pm_op(dev, dev->class->pm, state);
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200904 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200905 } else if (dev->class->suspend) {
906 pm_dev_dbg(dev, state, "legacy class ");
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100907 error = legacy_suspend(dev, state, dev->class->suspend);
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +0200908 goto End;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200909 }
Alan Sterncd59abf2007-09-21 15:36:56 -0400910 }
911
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200912 if (dev->bus) {
913 if (dev->bus->pm) {
914 pm_dev_dbg(dev, state, "");
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200915 error = pm_op(dev, dev->bus->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200916 } else if (dev->bus->suspend) {
917 pm_dev_dbg(dev, state, "legacy ");
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100918 error = legacy_suspend(dev, state, dev->bus->suspend);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200919 }
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +0100920 }
921
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200922 End:
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800923 device_unlock(dev);
Benoit Goby8e42bee2011-01-26 18:28:33 -0800924
925 del_timer_sync(&timer);
926 destroy_timer_on_stack(&timer);
927
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100928 complete_all(&dev->power.completion);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100929
Rafael J. Wysocki098dff72010-09-22 22:10:57 +0200930 if (error)
931 async_error = error;
932
Alan Sterncd59abf2007-09-21 15:36:56 -0400933 return error;
934}
935
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100936static void async_suspend(void *data, async_cookie_t cookie)
937{
938 struct device *dev = (struct device *)data;
939 int error;
940
941 error = __device_suspend(dev, pm_transition, true);
Rafael J. Wysocki098dff72010-09-22 22:10:57 +0200942 if (error)
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100943 pm_dev_err(dev, pm_transition, " async", error);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100944
945 put_device(dev);
946}
947
948static int device_suspend(struct device *dev)
949{
950 INIT_COMPLETION(dev->power.completion);
951
Rafael J. Wysocki0e06b4a2010-01-23 22:25:15 +0100952 if (pm_async_enabled && dev->power.async_suspend) {
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100953 get_device(dev);
954 async_schedule(async_suspend, dev);
955 return 0;
956 }
957
958 return __device_suspend(dev, pm_transition, false);
959}
960
Alan Sterncd59abf2007-09-21 15:36:56 -0400961/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200962 * dpm_suspend - Execute "suspend" callbacks for all non-sysdev devices.
963 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -0400964 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200965int dpm_suspend(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400966{
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100967 ktime_t starttime = ktime_get();
Alan Sterncd59abf2007-09-21 15:36:56 -0400968 int error = 0;
969
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +0200970 might_sleep();
971
Alan Sterncd59abf2007-09-21 15:36:56 -0400972 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100973 pm_transition = state;
974 async_error = 0;
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100975 while (!list_empty(&dpm_prepared_list)) {
976 struct device *dev = to_device(dpm_prepared_list.prev);
Alan Sterncd59abf2007-09-21 15:36:56 -0400977
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200978 get_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100979 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200980
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100981 error = device_suspend(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200982
Alan Stern1b3cbec2008-02-29 11:50:22 -0500983 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100984 if (error) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200985 pm_dev_err(dev, state, "", error);
986 put_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100987 break;
988 }
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100989 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +0100990 list_move(&dev->power.entry, &dpm_suspended_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200991 put_device(dev);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100992 if (async_error)
993 break;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100994 }
995 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100996 async_synchronize_full();
997 if (!error)
998 error = async_error;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100999 if (!error)
1000 dpm_show_time(starttime, state, NULL);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001001 return error;
1002}
1003
1004/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001005 * device_prepare - Prepare a device for system power transition.
1006 * @dev: Device to handle.
1007 * @state: PM transition of the system being carried out.
1008 *
1009 * Execute the ->prepare() callback(s) for given device. No new children of the
1010 * device may be registered after this function has returned.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001011 */
Alan Sternd1616302009-05-24 22:05:42 +02001012static int device_prepare(struct device *dev, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001013{
1014 int error = 0;
1015
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001016 device_lock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001017
Rafael J. Wysocki4d27e9d2011-04-29 00:35:50 +02001018 if (dev->pwr_domain) {
1019 pm_dev_dbg(dev, state, "preparing power domain ");
1020 if (dev->pwr_domain->ops.prepare)
1021 error = dev->pwr_domain->ops.prepare(dev);
1022 suspend_report_result(dev->pwr_domain->ops.prepare, error);
1023 if (error)
1024 goto End;
1025 } else if (dev->type && dev->type->pm) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001026 pm_dev_dbg(dev, state, "preparing type ");
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001027 if (dev->type->pm->prepare)
1028 error = dev->type->pm->prepare(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001029 suspend_report_result(dev->type->pm->prepare, error);
1030 if (error)
1031 goto End;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001032 } else if (dev->class && dev->class->pm) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001033 pm_dev_dbg(dev, state, "preparing class ");
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001034 if (dev->class->pm->prepare)
1035 error = dev->class->pm->prepare(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001036 suspend_report_result(dev->class->pm->prepare, error);
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001037 if (error)
1038 goto End;
Rafael J. Wysocki9659cc02011-02-18 23:20:21 +01001039 } else if (dev->bus && dev->bus->pm) {
1040 pm_dev_dbg(dev, state, "preparing ");
1041 if (dev->bus->pm->prepare)
1042 error = dev->bus->pm->prepare(dev);
1043 suspend_report_result(dev->bus->pm->prepare, error);
Rafael J. Wysocki7538e3d2011-02-16 21:53:17 +01001044 }
1045
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001046 End:
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -08001047 device_unlock(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001048
1049 return error;
1050}
1051
1052/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001053 * dpm_prepare - Prepare all non-sysdev devices for a system PM transition.
1054 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -04001055 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001056 * Execute the ->prepare() callback(s) for all devices.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001057 */
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001058int dpm_prepare(pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001059{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001060 int error = 0;
1061
Rafael J. Wysocki91e7c752011-05-17 23:26:00 +02001062 might_sleep();
1063
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001064 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001065 while (!list_empty(&dpm_list)) {
1066 struct device *dev = to_device(dpm_list.next);
1067
1068 get_device(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001069 mutex_unlock(&dpm_list_mtx);
1070
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +02001071 pm_runtime_get_noresume(dev);
Rafael J. Wysocki1e752272010-12-03 22:58:05 +01001072 if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
1073 pm_wakeup_event(dev, 0);
1074
Rafael J. Wysockie8665002011-02-12 01:42:41 +01001075 pm_runtime_put_sync(dev);
1076 error = pm_wakeup_pending() ?
1077 -EBUSY : device_prepare(dev, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001078
1079 mutex_lock(&dpm_list_mtx);
1080 if (error) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001081 if (error == -EAGAIN) {
1082 put_device(dev);
Sebastian Ott886a7a32009-07-08 13:26:05 +02001083 error = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001084 continue;
1085 }
Rafael J. Wysocki1e752272010-12-03 22:58:05 +01001086 printk(KERN_INFO "PM: Device %s not prepared "
1087 "for power transition: code %d\n",
Rafael J. Wysocki5c1a07a2010-12-24 15:03:34 +01001088 dev_name(dev), error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001089 put_device(dev);
1090 break;
1091 }
Rafael J. Wysockib8c76f62010-12-16 00:51:21 +01001092 dev->power.in_suspend = true;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001093 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki8a43a9a2010-12-16 00:50:30 +01001094 list_move_tail(&dev->power.entry, &dpm_prepared_list);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001095 put_device(dev);
1096 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001097 mutex_unlock(&dpm_list_mtx);
1098 return error;
1099}
1100
1101/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001102 * dpm_suspend_start - Prepare devices for PM transition and suspend them.
1103 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001104 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001105 * Prepare all non-sysdev devices for system PM transition and execute "suspend"
1106 * callbacks for them.
Alan Sterncd59abf2007-09-21 15:36:56 -04001107 */
Alan Sternd1616302009-05-24 22:05:42 +02001108int dpm_suspend_start(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001109{
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001110 int error;
Alan Sterncd59abf2007-09-21 15:36:56 -04001111
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001112 error = dpm_prepare(state);
1113 if (!error)
1114 error = dpm_suspend(state);
Alan Sterncd59abf2007-09-21 15:36:56 -04001115 return error;
Alan Sterncd59abf2007-09-21 15:36:56 -04001116}
Alan Sternd1616302009-05-24 22:05:42 +02001117EXPORT_SYMBOL_GPL(dpm_suspend_start);
Alan Sterncd59abf2007-09-21 15:36:56 -04001118
1119void __suspend_report_result(const char *function, void *fn, int ret)
1120{
Bjorn Helgaasc80cfb02008-10-15 22:01:35 -07001121 if (ret)
1122 printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret);
Alan Sterncd59abf2007-09-21 15:36:56 -04001123}
1124EXPORT_SYMBOL_GPL(__suspend_report_result);
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001125
1126/**
1127 * device_pm_wait_for_dev - Wait for suspend/resume of a device to complete.
1128 * @dev: Device to wait for.
1129 * @subordinate: Device that needs to wait for @dev.
1130 */
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001131int device_pm_wait_for_dev(struct device *subordinate, struct device *dev)
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001132{
1133 dpm_wait(dev, subordinate->power.async_suspend);
Rafael J. Wysocki098dff72010-09-22 22:10:57 +02001134 return async_error;
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001135}
1136EXPORT_SYMBOL_GPL(device_pm_wait_for_dev);