blob: 5419a49ff135121ce608004f40a211a9587b5cf5 [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.
11 * This will intialize the embedded device_pm_info object in the device
12 * 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>
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -070029
Alan Sterncd59abf2007-09-21 15:36:56 -040030#include "../base.h"
Linus Torvalds1da177e2005-04-16 15:20:36 -070031#include "power.h"
32
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010033/*
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020034 * The entries in the dpm_list list are in a depth first order, simply
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010035 * because children are guaranteed to be discovered after parents, and
36 * are inserted at the back of the list on discovery.
37 *
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -080038 * Since device_pm_add() may be called with a device lock held,
39 * we must never try to acquire a device lock while holding
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010040 * dpm_list_mutex.
41 */
42
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020043LIST_HEAD(dpm_list);
Linus Torvalds1da177e2005-04-16 15:20:36 -070044
Alan Sterncd59abf2007-09-21 15:36:56 -040045static DEFINE_MUTEX(dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +010046static pm_message_t pm_transition;
Linus Torvalds1da177e2005-04-16 15:20:36 -070047
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020048/*
49 * Set once the preparation of devices for a PM transition has started, reset
50 * before starting to resume devices. Protected by dpm_list_mtx.
51 */
52static bool transition_started;
53
54/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +020055 * device_pm_init - Initialize the PM-related part of a device object.
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +020056 * @dev: Device object being initialized.
57 */
58void device_pm_init(struct device *dev)
59{
60 dev->power.status = DPM_ON;
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +010061 init_completion(&dev->power.completion);
Rafael J. Wysockic125e962010-07-05 22:43:53 +020062 dev->power.wakeup_count = 0;
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +020063 pm_runtime_init(dev);
64}
65
66/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +020067 * device_pm_lock - Lock the list of active devices used by the PM core.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020068 */
69void device_pm_lock(void)
70{
71 mutex_lock(&dpm_list_mtx);
72}
73
74/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +020075 * device_pm_unlock - Unlock the list of active devices used by the PM core.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020076 */
77void device_pm_unlock(void)
78{
79 mutex_unlock(&dpm_list_mtx);
80}
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010081
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010082/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +020083 * device_pm_add - Add a device to the PM core's list of active devices.
84 * @dev: Device to add to the list.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +010085 */
Alan Stern3b98aea2008-08-07 13:06:12 -040086void device_pm_add(struct device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -070087{
Linus Torvalds1da177e2005-04-16 15:20:36 -070088 pr_debug("PM: Adding info for %s:%s\n",
Dmitry Torokhovc48ea602007-04-11 01:37:18 -040089 dev->bus ? dev->bus->name : "No Bus",
90 kobject_name(&dev->kobj));
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -070091 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020092 if (dev->parent) {
Rafael J. Wysockif5a6d952008-08-09 01:05:13 +020093 if (dev->parent->power.status >= DPM_SUSPENDING)
94 dev_warn(dev, "parent %s should not be sleeping\n",
Kay Sievers1e0b2cf2008-10-30 01:36:48 +010095 dev_name(dev->parent));
Rafael J. Wysocki1eede072008-05-20 23:00:01 +020096 } else if (transition_started) {
97 /*
98 * We refuse to register parentless devices while a PM
99 * transition is in progress in order to avoid leaving them
100 * unhandled down the road
101 */
Arjan van de Ven728f0892008-09-20 19:09:00 -0700102 dev_WARN(dev, "Parentless device registered during a PM transaction\n");
Rafael J. Wysocki58aca232008-03-12 00:57:22 +0100103 }
Alan Stern3b98aea2008-08-07 13:06:12 -0400104
105 list_add_tail(&dev->power.entry, &dpm_list);
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700106 mutex_unlock(&dpm_list_mtx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700107}
108
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100109/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200110 * device_pm_remove - Remove a device from the PM core's list of active devices.
111 * @dev: Device to be removed from the list.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100112 */
Rafael J. Wysocki9cddad72007-06-13 15:53:34 +0200113void device_pm_remove(struct device *dev)
Linus Torvalds1da177e2005-04-16 15:20:36 -0700114{
115 pr_debug("PM: Removing info for %s:%s\n",
Dmitry Torokhovc48ea602007-04-11 01:37:18 -0400116 dev->bus ? dev->bus->name : "No Bus",
117 kobject_name(&dev->kobj));
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100118 complete_all(&dev->power.completion);
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700119 mutex_lock(&dpm_list_mtx);
Linus Torvalds1da177e2005-04-16 15:20:36 -0700120 list_del_init(&dev->power.entry);
Matthias Kaehlcke11048dc2007-05-23 14:19:41 -0700121 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +0200122 pm_runtime_remove(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100123}
124
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200125/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200126 * device_pm_move_before - Move device in the PM core's list of active devices.
127 * @deva: Device to move in dpm_list.
128 * @devb: Device @deva should come before.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100129 */
130void device_pm_move_before(struct device *deva, struct device *devb)
131{
132 pr_debug("PM: Moving %s:%s before %s:%s\n",
133 deva->bus ? deva->bus->name : "No Bus",
134 kobject_name(&deva->kobj),
135 devb->bus ? devb->bus->name : "No Bus",
136 kobject_name(&devb->kobj));
137 /* Delete deva from dpm_list and reinsert before devb. */
138 list_move_tail(&deva->power.entry, &devb->power.entry);
139}
140
141/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200142 * device_pm_move_after - Move device in the PM core's list of active devices.
143 * @deva: Device to move in dpm_list.
144 * @devb: Device @deva should come after.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100145 */
146void device_pm_move_after(struct device *deva, struct device *devb)
147{
148 pr_debug("PM: Moving %s:%s after %s:%s\n",
149 deva->bus ? deva->bus->name : "No Bus",
150 kobject_name(&deva->kobj),
151 devb->bus ? devb->bus->name : "No Bus",
152 kobject_name(&devb->kobj));
153 /* Delete deva from dpm_list and reinsert after devb. */
154 list_move(&deva->power.entry, &devb->power.entry);
155}
156
157/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200158 * device_pm_move_last - Move device to end of the PM core's list of devices.
159 * @dev: Device to move in dpm_list.
Cornelia Huckffa6a702009-03-04 12:44:00 +0100160 */
161void device_pm_move_last(struct device *dev)
162{
163 pr_debug("PM: Moving %s:%s to end of list\n",
164 dev->bus ? dev->bus->name : "No Bus",
165 kobject_name(&dev->kobj));
166 list_move_tail(&dev->power.entry, &dpm_list);
167}
168
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100169static ktime_t initcall_debug_start(struct device *dev)
170{
171 ktime_t calltime = ktime_set(0, 0);
172
173 if (initcall_debug) {
174 pr_info("calling %s+ @ %i\n",
175 dev_name(dev), task_pid_nr(current));
176 calltime = ktime_get();
177 }
178
179 return calltime;
180}
181
182static void initcall_debug_report(struct device *dev, ktime_t calltime,
183 int error)
184{
185 ktime_t delta, rettime;
186
187 if (initcall_debug) {
188 rettime = ktime_get();
189 delta = ktime_sub(rettime, calltime);
190 pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev),
191 error, (unsigned long long)ktime_to_ns(delta) >> 10);
192 }
193}
194
Cornelia Huckffa6a702009-03-04 12:44:00 +0100195/**
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100196 * dpm_wait - Wait for a PM operation to complete.
197 * @dev: Device to wait for.
198 * @async: If unset, wait only if the device's power.async_suspend flag is set.
199 */
200static void dpm_wait(struct device *dev, bool async)
201{
202 if (!dev)
203 return;
204
Rafael J. Wysocki0e06b4a2010-01-23 22:25:15 +0100205 if (async || (pm_async_enabled && dev->power.async_suspend))
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100206 wait_for_completion(&dev->power.completion);
207}
208
209static int dpm_wait_fn(struct device *dev, void *async_ptr)
210{
211 dpm_wait(dev, *((bool *)async_ptr));
212 return 0;
213}
214
215static void dpm_wait_for_children(struct device *dev, bool async)
216{
217 device_for_each_child(dev, &async, dpm_wait_fn);
218}
219
220/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200221 * pm_op - Execute the PM operation appropriate for given PM event.
222 * @dev: Device to handle.
223 * @ops: PM operations to choose from.
224 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200225 */
Dmitry Torokhovd9ab7712009-07-22 00:37:25 +0200226static int pm_op(struct device *dev,
227 const struct dev_pm_ops *ops,
228 pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200229{
230 int error = 0;
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100231 ktime_t calltime;
Arjan van de Venf2511772009-12-13 20:29:01 +0100232
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100233 calltime = initcall_debug_start(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200234
235 switch (state.event) {
236#ifdef CONFIG_SUSPEND
237 case PM_EVENT_SUSPEND:
238 if (ops->suspend) {
239 error = ops->suspend(dev);
240 suspend_report_result(ops->suspend, error);
241 }
242 break;
243 case PM_EVENT_RESUME:
244 if (ops->resume) {
245 error = ops->resume(dev);
246 suspend_report_result(ops->resume, error);
247 }
248 break;
249#endif /* CONFIG_SUSPEND */
250#ifdef CONFIG_HIBERNATION
251 case PM_EVENT_FREEZE:
252 case PM_EVENT_QUIESCE:
253 if (ops->freeze) {
254 error = ops->freeze(dev);
255 suspend_report_result(ops->freeze, error);
256 }
257 break;
258 case PM_EVENT_HIBERNATE:
259 if (ops->poweroff) {
260 error = ops->poweroff(dev);
261 suspend_report_result(ops->poweroff, error);
262 }
263 break;
264 case PM_EVENT_THAW:
265 case PM_EVENT_RECOVER:
266 if (ops->thaw) {
267 error = ops->thaw(dev);
268 suspend_report_result(ops->thaw, error);
269 }
270 break;
271 case PM_EVENT_RESTORE:
272 if (ops->restore) {
273 error = ops->restore(dev);
274 suspend_report_result(ops->restore, error);
275 }
276 break;
277#endif /* CONFIG_HIBERNATION */
278 default:
279 error = -EINVAL;
280 }
Arjan van de Venf2511772009-12-13 20:29:01 +0100281
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100282 initcall_debug_report(dev, calltime, error);
Arjan van de Venf2511772009-12-13 20:29:01 +0100283
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200284 return error;
285}
286
287/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200288 * pm_noirq_op - Execute the PM operation appropriate for given PM event.
289 * @dev: Device to handle.
290 * @ops: PM operations to choose from.
291 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200292 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200293 * The driver of @dev will not receive interrupts while this function is being
294 * executed.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200295 */
Dmitry Torokhovd9ab7712009-07-22 00:37:25 +0200296static int pm_noirq_op(struct device *dev,
297 const struct dev_pm_ops *ops,
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200298 pm_message_t state)
299{
300 int error = 0;
Arjan van de Venf2511772009-12-13 20:29:01 +0100301 ktime_t calltime, delta, rettime;
302
303 if (initcall_debug) {
Rafael J. Wysocki8cc6b392010-01-23 22:03:29 +0100304 pr_info("calling %s+ @ %i, parent: %s\n",
305 dev_name(dev), task_pid_nr(current),
306 dev->parent ? dev_name(dev->parent) : "none");
Arjan van de Venf2511772009-12-13 20:29:01 +0100307 calltime = ktime_get();
308 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200309
310 switch (state.event) {
311#ifdef CONFIG_SUSPEND
312 case PM_EVENT_SUSPEND:
313 if (ops->suspend_noirq) {
314 error = ops->suspend_noirq(dev);
315 suspend_report_result(ops->suspend_noirq, error);
316 }
317 break;
318 case PM_EVENT_RESUME:
319 if (ops->resume_noirq) {
320 error = ops->resume_noirq(dev);
321 suspend_report_result(ops->resume_noirq, error);
322 }
323 break;
324#endif /* CONFIG_SUSPEND */
325#ifdef CONFIG_HIBERNATION
326 case PM_EVENT_FREEZE:
327 case PM_EVENT_QUIESCE:
328 if (ops->freeze_noirq) {
329 error = ops->freeze_noirq(dev);
330 suspend_report_result(ops->freeze_noirq, error);
331 }
332 break;
333 case PM_EVENT_HIBERNATE:
334 if (ops->poweroff_noirq) {
335 error = ops->poweroff_noirq(dev);
336 suspend_report_result(ops->poweroff_noirq, error);
337 }
338 break;
339 case PM_EVENT_THAW:
340 case PM_EVENT_RECOVER:
341 if (ops->thaw_noirq) {
342 error = ops->thaw_noirq(dev);
343 suspend_report_result(ops->thaw_noirq, error);
344 }
345 break;
346 case PM_EVENT_RESTORE:
347 if (ops->restore_noirq) {
348 error = ops->restore_noirq(dev);
349 suspend_report_result(ops->restore_noirq, error);
350 }
351 break;
352#endif /* CONFIG_HIBERNATION */
353 default:
354 error = -EINVAL;
355 }
Arjan van de Venf2511772009-12-13 20:29:01 +0100356
357 if (initcall_debug) {
358 rettime = ktime_get();
359 delta = ktime_sub(rettime, calltime);
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100360 printk("initcall %s_i+ returned %d after %Ld usecs\n",
361 dev_name(dev), error,
362 (unsigned long long)ktime_to_ns(delta) >> 10);
Arjan van de Venf2511772009-12-13 20:29:01 +0100363 }
364
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200365 return error;
366}
367
368static char *pm_verb(int event)
369{
370 switch (event) {
371 case PM_EVENT_SUSPEND:
372 return "suspend";
373 case PM_EVENT_RESUME:
374 return "resume";
375 case PM_EVENT_FREEZE:
376 return "freeze";
377 case PM_EVENT_QUIESCE:
378 return "quiesce";
379 case PM_EVENT_HIBERNATE:
380 return "hibernate";
381 case PM_EVENT_THAW:
382 return "thaw";
383 case PM_EVENT_RESTORE:
384 return "restore";
385 case PM_EVENT_RECOVER:
386 return "recover";
387 default:
388 return "(unknown PM event)";
389 }
390}
391
392static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info)
393{
394 dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event),
395 ((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ?
396 ", may wakeup" : "");
397}
398
399static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
400 int error)
401{
402 printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n",
403 kobject_name(&dev->kobj), pm_verb(state.event), info, error);
404}
405
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100406static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
407{
408 ktime_t calltime;
409 s64 usecs64;
410 int usecs;
411
412 calltime = ktime_get();
413 usecs64 = ktime_to_ns(ktime_sub(calltime, starttime));
414 do_div(usecs64, NSEC_PER_USEC);
415 usecs = usecs64;
416 if (usecs == 0)
417 usecs = 1;
418 pr_info("PM: %s%s%s of devices complete after %ld.%03ld msecs\n",
419 info ?: "", info ? " " : "", pm_verb(state.event),
420 usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);
421}
422
Alan Sterncd59abf2007-09-21 15:36:56 -0400423/*------------------------- Resume routines -------------------------*/
424
425/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200426 * device_resume_noirq - Execute an "early resume" callback for given device.
427 * @dev: Device to handle.
428 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -0400429 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200430 * The driver of @dev will not receive interrupts while this function is being
431 * executed.
Alan Sterncd59abf2007-09-21 15:36:56 -0400432 */
Alan Sternd1616302009-05-24 22:05:42 +0200433static int device_resume_noirq(struct device *dev, pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400434{
435 int error = 0;
436
437 TRACE_DEVICE(dev);
438 TRACE_RESUME(0);
439
Rafael J. Wysocki33c33742009-12-13 20:31:12 +0100440 if (dev->bus && dev->bus->pm) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200441 pm_dev_dbg(dev, state, "EARLY ");
442 error = pm_noirq_op(dev, dev->bus->pm, state);
Dominik Brodowskie7176a32010-03-15 21:43:11 +0100443 if (error)
444 goto End;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100445 }
Rafael J. Wysocki33c33742009-12-13 20:31:12 +0100446
Dominik Brodowskie7176a32010-03-15 21:43:11 +0100447 if (dev->type && dev->type->pm) {
448 pm_dev_dbg(dev, state, "EARLY type ");
449 error = pm_noirq_op(dev, dev->type->pm, state);
450 if (error)
451 goto End;
452 }
453
454 if (dev->class && dev->class->pm) {
455 pm_dev_dbg(dev, state, "EARLY class ");
456 error = pm_noirq_op(dev, dev->class->pm, state);
457 }
458
459End:
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100460 TRACE_RESUME(error);
461 return error;
462}
463
464/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200465 * dpm_resume_noirq - Execute "early resume" callbacks for non-sysdev devices.
466 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100467 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200468 * Call the "noirq" resume handlers for all devices marked as DPM_OFF_IRQ and
469 * enable device drivers to receive interrupts.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100470 */
Alan Sternd1616302009-05-24 22:05:42 +0200471void dpm_resume_noirq(pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100472{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200473 struct device *dev;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100474 ktime_t starttime = ktime_get();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100475
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200476 mutex_lock(&dpm_list_mtx);
Xiaotian Feng3eb132c2009-08-20 20:28:33 +0200477 transition_started = false;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200478 list_for_each_entry(dev, &dpm_list, power.entry)
479 if (dev->power.status > DPM_OFF) {
480 int error;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100481
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200482 dev->power.status = DPM_OFF;
Alan Sternd1616302009-05-24 22:05:42 +0200483 error = device_resume_noirq(dev, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200484 if (error)
485 pm_dev_err(dev, state, " early", error);
486 }
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200487 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100488 dpm_show_time(starttime, state, "early");
Rafael J. Wysocki2ed8d2b2009-03-16 22:34:06 +0100489 resume_device_irqs();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100490}
Alan Sternd1616302009-05-24 22:05:42 +0200491EXPORT_SYMBOL_GPL(dpm_resume_noirq);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100492
493/**
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100494 * legacy_resume - Execute a legacy (bus or class) resume callback for device.
Randy Dunlap0a884222010-01-08 14:42:57 -0800495 * @dev: Device to resume.
496 * @cb: Resume callback to execute.
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100497 */
498static int legacy_resume(struct device *dev, int (*cb)(struct device *dev))
499{
500 int error;
501 ktime_t calltime;
502
503 calltime = initcall_debug_start(dev);
504
505 error = cb(dev);
506 suspend_report_result(cb, error);
507
508 initcall_debug_report(dev, calltime, error);
509
510 return error;
511}
512
513/**
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100514 * device_resume - Execute "resume" callbacks for given device.
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200515 * @dev: Device to handle.
516 * @state: PM transition of the system being carried out.
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100517 * @async: If true, the device is being resumed asynchronously.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100518 */
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100519static int device_resume(struct device *dev, pm_message_t state, bool async)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100520{
521 int error = 0;
522
523 TRACE_DEVICE(dev);
524 TRACE_RESUME(0);
Alan Sterncd59abf2007-09-21 15:36:56 -0400525
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100526 dpm_wait(dev->parent, async);
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800527 device_lock(dev);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100528
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100529 dev->power.status = DPM_RESUMING;
530
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200531 if (dev->bus) {
532 if (dev->bus->pm) {
533 pm_dev_dbg(dev, state, "");
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200534 error = pm_op(dev, dev->bus->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200535 } else if (dev->bus->resume) {
536 pm_dev_dbg(dev, state, "legacy ");
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100537 error = legacy_resume(dev, dev->bus->resume);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200538 }
539 if (error)
540 goto End;
Alan Sterncd59abf2007-09-21 15:36:56 -0400541 }
542
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200543 if (dev->type) {
544 if (dev->type->pm) {
545 pm_dev_dbg(dev, state, "type ");
546 error = pm_op(dev, dev->type->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200547 }
548 if (error)
549 goto End;
Alan Sterncd59abf2007-09-21 15:36:56 -0400550 }
551
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200552 if (dev->class) {
553 if (dev->class->pm) {
554 pm_dev_dbg(dev, state, "class ");
555 error = pm_op(dev, dev->class->pm, state);
556 } else if (dev->class->resume) {
557 pm_dev_dbg(dev, state, "legacy class ");
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100558 error = legacy_resume(dev, dev->class->resume);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200559 }
Alan Sterncd59abf2007-09-21 15:36:56 -0400560 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200561 End:
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800562 device_unlock(dev);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100563 complete_all(&dev->power.completion);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100564
Alan Sterncd59abf2007-09-21 15:36:56 -0400565 TRACE_RESUME(error);
566 return error;
567}
568
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100569static void async_resume(void *data, async_cookie_t cookie)
570{
571 struct device *dev = (struct device *)data;
572 int error;
573
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100574 error = device_resume(dev, pm_transition, true);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100575 if (error)
576 pm_dev_err(dev, pm_transition, " async", error);
577 put_device(dev);
578}
579
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100580static bool is_async(struct device *dev)
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100581{
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100582 return dev->power.async_suspend && pm_async_enabled
583 && !pm_trace_is_enabled();
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100584}
585
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100586/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200587 * dpm_resume - Execute "resume" callbacks for non-sysdev devices.
588 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100589 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200590 * Execute the appropriate "resume" callback for all devices whose status
591 * indicates that they are suspended.
Alan Sterncd59abf2007-09-21 15:36:56 -0400592 */
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200593static void dpm_resume(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400594{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200595 struct list_head list;
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100596 struct device *dev;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100597 ktime_t starttime = ktime_get();
Alan Sterncd59abf2007-09-21 15:36:56 -0400598
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200599 INIT_LIST_HEAD(&list);
600 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100601 pm_transition = state;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200602
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100603 list_for_each_entry(dev, &dpm_list, power.entry) {
604 if (dev->power.status < DPM_OFF)
605 continue;
606
607 INIT_COMPLETION(dev->power.completion);
608 if (is_async(dev)) {
609 get_device(dev);
610 async_schedule(async_resume, dev);
611 }
612 }
613
614 while (!list_empty(&dpm_list)) {
615 dev = to_device(dpm_list.next);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200616 get_device(dev);
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100617 if (dev->power.status >= DPM_OFF && !is_async(dev)) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200618 int error;
619
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200620 mutex_unlock(&dpm_list_mtx);
621
Rafael J. Wysocki97df8c12010-01-23 22:25:31 +0100622 error = device_resume(dev, state, false);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200623
624 mutex_lock(&dpm_list_mtx);
625 if (error)
626 pm_dev_err(dev, state, "", error);
627 } else if (dev->power.status == DPM_SUSPENDING) {
628 /* Allow new children of the device to be registered */
629 dev->power.status = DPM_RESUMING;
630 }
631 if (!list_empty(&dev->power.entry))
632 list_move_tail(&dev->power.entry, &list);
633 put_device(dev);
Alan Sterncd59abf2007-09-21 15:36:56 -0400634 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200635 list_splice(&list, &dpm_list);
636 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100637 async_synchronize_full();
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100638 dpm_show_time(starttime, state, NULL);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200639}
640
641/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200642 * device_complete - Complete a PM transition for given device.
643 * @dev: Device to handle.
644 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200645 */
Alan Sternd1616302009-05-24 22:05:42 +0200646static void device_complete(struct device *dev, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200647{
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800648 device_lock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200649
650 if (dev->class && dev->class->pm && dev->class->pm->complete) {
651 pm_dev_dbg(dev, state, "completing class ");
652 dev->class->pm->complete(dev);
653 }
654
655 if (dev->type && dev->type->pm && dev->type->pm->complete) {
656 pm_dev_dbg(dev, state, "completing type ");
657 dev->type->pm->complete(dev);
658 }
659
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200660 if (dev->bus && dev->bus->pm && dev->bus->pm->complete) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200661 pm_dev_dbg(dev, state, "completing ");
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200662 dev->bus->pm->complete(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200663 }
664
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800665 device_unlock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200666}
667
668/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200669 * dpm_complete - Complete a PM transition for all non-sysdev devices.
670 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200671 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200672 * Execute the ->complete() callbacks for all devices whose PM status is not
673 * DPM_ON (this allows new devices to be registered).
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200674 */
675static void dpm_complete(pm_message_t state)
676{
677 struct list_head list;
678
679 INIT_LIST_HEAD(&list);
680 mutex_lock(&dpm_list_mtx);
Romit Dasguptae528e872009-10-28 22:56:02 +0100681 transition_started = false;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200682 while (!list_empty(&dpm_list)) {
683 struct device *dev = to_device(dpm_list.prev);
684
685 get_device(dev);
686 if (dev->power.status > DPM_ON) {
687 dev->power.status = DPM_ON;
688 mutex_unlock(&dpm_list_mtx);
689
Alan Sternd1616302009-05-24 22:05:42 +0200690 device_complete(dev, state);
Alan Sternaa0baae2009-12-21 02:46:11 +0100691 pm_runtime_put_sync(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200692
693 mutex_lock(&dpm_list_mtx);
694 }
695 if (!list_empty(&dev->power.entry))
696 list_move(&dev->power.entry, &list);
697 put_device(dev);
698 }
699 list_splice(&list, &dpm_list);
Alan Sterncd59abf2007-09-21 15:36:56 -0400700 mutex_unlock(&dpm_list_mtx);
701}
702
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100703/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200704 * dpm_resume_end - Execute "resume" callbacks and complete system transition.
705 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -0400706 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200707 * Execute "resume" callbacks for all devices and complete the PM transition of
708 * the system.
Alan Sterncd59abf2007-09-21 15:36:56 -0400709 */
Alan Sternd1616302009-05-24 22:05:42 +0200710void dpm_resume_end(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400711{
712 might_sleep();
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200713 dpm_resume(state);
714 dpm_complete(state);
Alan Sterncd59abf2007-09-21 15:36:56 -0400715}
Alan Sternd1616302009-05-24 22:05:42 +0200716EXPORT_SYMBOL_GPL(dpm_resume_end);
Alan Sterncd59abf2007-09-21 15:36:56 -0400717
718
Alan Sterncd59abf2007-09-21 15:36:56 -0400719/*------------------------- Suspend routines -------------------------*/
720
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200721/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200722 * resume_event - Return a "resume" message for given "suspend" sleep state.
723 * @sleep_state: PM message representing a sleep state.
724 *
725 * Return a PM message representing the resume event corresponding to given
726 * sleep state.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200727 */
728static pm_message_t resume_event(pm_message_t sleep_state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400729{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200730 switch (sleep_state.event) {
731 case PM_EVENT_SUSPEND:
732 return PMSG_RESUME;
733 case PM_EVENT_FREEZE:
734 case PM_EVENT_QUIESCE:
735 return PMSG_RECOVER;
736 case PM_EVENT_HIBERNATE:
737 return PMSG_RESTORE;
Alan Sterncd59abf2007-09-21 15:36:56 -0400738 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200739 return PMSG_ON;
Alan Sterncd59abf2007-09-21 15:36:56 -0400740}
741
742/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200743 * device_suspend_noirq - Execute a "late suspend" callback for given device.
744 * @dev: Device to handle.
745 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100746 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200747 * The driver of @dev will not receive interrupts while this function is being
748 * executed.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100749 */
Alan Sternd1616302009-05-24 22:05:42 +0200750static int device_suspend_noirq(struct device *dev, pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100751{
752 int error = 0;
753
Dominik Brodowskie7176a32010-03-15 21:43:11 +0100754 if (dev->class && dev->class->pm) {
755 pm_dev_dbg(dev, state, "LATE class ");
756 error = pm_noirq_op(dev, dev->class->pm, state);
757 if (error)
758 goto End;
759 }
760
761 if (dev->type && dev->type->pm) {
762 pm_dev_dbg(dev, state, "LATE type ");
763 error = pm_noirq_op(dev, dev->type->pm, state);
764 if (error)
765 goto End;
766 }
767
Rafael J. Wysocki33c33742009-12-13 20:31:12 +0100768 if (dev->bus && dev->bus->pm) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200769 pm_dev_dbg(dev, state, "LATE ");
770 error = pm_noirq_op(dev, dev->bus->pm, state);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100771 }
Dominik Brodowskie7176a32010-03-15 21:43:11 +0100772
773End:
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100774 return error;
775}
776
777/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200778 * dpm_suspend_noirq - Execute "late suspend" callbacks for non-sysdev devices.
779 * @state: PM transition of the system being carried out.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100780 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200781 * Prevent device drivers from receiving interrupts and call the "noirq" suspend
782 * handlers for all non-sysdev devices.
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100783 */
Alan Sternd1616302009-05-24 22:05:42 +0200784int dpm_suspend_noirq(pm_message_t state)
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100785{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200786 struct device *dev;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100787 ktime_t starttime = ktime_get();
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100788 int error = 0;
789
Rafael J. Wysocki2ed8d2b2009-03-16 22:34:06 +0100790 suspend_device_irqs();
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200791 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200792 list_for_each_entry_reverse(dev, &dpm_list, power.entry) {
Alan Sternd1616302009-05-24 22:05:42 +0200793 error = device_suspend_noirq(dev, state);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100794 if (error) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200795 pm_dev_err(dev, state, " late", error);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100796 break;
797 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200798 dev->power.status = DPM_OFF_IRQ;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100799 }
Rafael J. Wysocki32bdfac2009-05-24 21:15:07 +0200800 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100801 if (error)
Alan Sternd1616302009-05-24 22:05:42 +0200802 dpm_resume_noirq(resume_event(state));
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100803 else
804 dpm_show_time(starttime, state, "late");
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100805 return error;
806}
Alan Sternd1616302009-05-24 22:05:42 +0200807EXPORT_SYMBOL_GPL(dpm_suspend_noirq);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100808
809/**
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100810 * legacy_suspend - Execute a legacy (bus or class) suspend callback for device.
Randy Dunlap0a884222010-01-08 14:42:57 -0800811 * @dev: Device to suspend.
812 * @state: PM transition of the system being carried out.
813 * @cb: Suspend callback to execute.
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100814 */
815static int legacy_suspend(struct device *dev, pm_message_t state,
816 int (*cb)(struct device *dev, pm_message_t state))
817{
818 int error;
819 ktime_t calltime;
820
821 calltime = initcall_debug_start(dev);
822
823 error = cb(dev, state);
824 suspend_report_result(cb, error);
825
826 initcall_debug_report(dev, calltime, error);
827
828 return error;
829}
830
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100831static int async_error;
832
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100833/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200834 * device_suspend - Execute "suspend" callbacks for given device.
835 * @dev: Device to handle.
836 * @state: PM transition of the system being carried out.
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100837 * @async: If true, the device is being suspended asynchronously.
Alan Sterncd59abf2007-09-21 15:36:56 -0400838 */
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100839static int __device_suspend(struct device *dev, pm_message_t state, bool async)
Alan Sterncd59abf2007-09-21 15:36:56 -0400840{
841 int error = 0;
842
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100843 dpm_wait_for_children(dev, async);
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800844 device_lock(dev);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100845
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100846 if (async_error)
847 goto End;
848
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200849 if (dev->class) {
850 if (dev->class->pm) {
851 pm_dev_dbg(dev, state, "class ");
852 error = pm_op(dev, dev->class->pm, state);
853 } else if (dev->class->suspend) {
854 pm_dev_dbg(dev, state, "legacy class ");
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100855 error = legacy_suspend(dev, state, dev->class->suspend);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200856 }
857 if (error)
858 goto End;
Alan Sterncd59abf2007-09-21 15:36:56 -0400859 }
860
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200861 if (dev->type) {
862 if (dev->type->pm) {
863 pm_dev_dbg(dev, state, "type ");
864 error = pm_op(dev, dev->type->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200865 }
866 if (error)
867 goto End;
Alan Sterncd59abf2007-09-21 15:36:56 -0400868 }
869
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200870 if (dev->bus) {
871 if (dev->bus->pm) {
872 pm_dev_dbg(dev, state, "");
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200873 error = pm_op(dev, dev->bus->pm, state);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200874 } else if (dev->bus->suspend) {
875 pm_dev_dbg(dev, state, "legacy ");
Rafael J. Wysocki875ab0b2009-12-18 01:57:31 +0100876 error = legacy_suspend(dev, state, dev->bus->suspend);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200877 }
Alan Sterncd59abf2007-09-21 15:36:56 -0400878 }
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100879
880 if (!error)
881 dev->power.status = DPM_OFF;
882
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200883 End:
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800884 device_unlock(dev);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100885 complete_all(&dev->power.completion);
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100886
Alan Sterncd59abf2007-09-21 15:36:56 -0400887 return error;
888}
889
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100890static void async_suspend(void *data, async_cookie_t cookie)
891{
892 struct device *dev = (struct device *)data;
893 int error;
894
895 error = __device_suspend(dev, pm_transition, true);
896 if (error) {
897 pm_dev_err(dev, pm_transition, " async", error);
898 async_error = error;
899 }
900
901 put_device(dev);
902}
903
904static int device_suspend(struct device *dev)
905{
906 INIT_COMPLETION(dev->power.completion);
907
Rafael J. Wysocki0e06b4a2010-01-23 22:25:15 +0100908 if (pm_async_enabled && dev->power.async_suspend) {
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100909 get_device(dev);
910 async_schedule(async_suspend, dev);
911 return 0;
912 }
913
914 return __device_suspend(dev, pm_transition, false);
915}
916
Alan Sterncd59abf2007-09-21 15:36:56 -0400917/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200918 * dpm_suspend - Execute "suspend" callbacks for all non-sysdev devices.
919 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -0400920 */
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100921static int dpm_suspend(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -0400922{
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200923 struct list_head list;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100924 ktime_t starttime = ktime_get();
Alan Sterncd59abf2007-09-21 15:36:56 -0400925 int error = 0;
926
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200927 INIT_LIST_HEAD(&list);
Alan Sterncd59abf2007-09-21 15:36:56 -0400928 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100929 pm_transition = state;
930 async_error = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200931 while (!list_empty(&dpm_list)) {
932 struct device *dev = to_device(dpm_list.prev);
Alan Sterncd59abf2007-09-21 15:36:56 -0400933
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200934 get_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100935 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200936
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100937 error = device_suspend(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200938
Alan Stern1b3cbec2008-02-29 11:50:22 -0500939 mutex_lock(&dpm_list_mtx);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100940 if (error) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200941 pm_dev_err(dev, state, "", error);
942 put_device(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100943 break;
944 }
Rafael J. Wysocki7a8d37a2008-02-25 00:35:04 +0100945 if (!list_empty(&dev->power.entry))
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200946 list_move(&dev->power.entry, &list);
947 put_device(dev);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100948 if (async_error)
949 break;
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100950 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200951 list_splice(&list, dpm_list.prev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100952 mutex_unlock(&dpm_list_mtx);
Rafael J. Wysocki5af84b82010-01-23 22:23:32 +0100953 async_synchronize_full();
954 if (!error)
955 error = async_error;
Rafael J. Wysockiecf762b2009-12-18 01:57:47 +0100956 if (!error)
957 dpm_show_time(starttime, state, NULL);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200958 return error;
959}
960
961/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +0200962 * device_prepare - Prepare a device for system power transition.
963 * @dev: Device to handle.
964 * @state: PM transition of the system being carried out.
965 *
966 * Execute the ->prepare() callback(s) for given device. No new children of the
967 * device may be registered after this function has returned.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200968 */
Alan Sternd1616302009-05-24 22:05:42 +0200969static int device_prepare(struct device *dev, pm_message_t state)
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200970{
971 int error = 0;
972
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800973 device_lock(dev);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200974
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200975 if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) {
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200976 pm_dev_dbg(dev, state, "preparing ");
Rafael J. Wysockiadf09492008-10-06 22:46:05 +0200977 error = dev->bus->pm->prepare(dev);
978 suspend_report_result(dev->bus->pm->prepare, error);
Rafael J. Wysocki1eede072008-05-20 23:00:01 +0200979 if (error)
980 goto End;
981 }
982
983 if (dev->type && dev->type->pm && dev->type->pm->prepare) {
984 pm_dev_dbg(dev, state, "preparing type ");
985 error = dev->type->pm->prepare(dev);
986 suspend_report_result(dev->type->pm->prepare, error);
987 if (error)
988 goto End;
989 }
990
991 if (dev->class && dev->class->pm && dev->class->pm->prepare) {
992 pm_dev_dbg(dev, state, "preparing class ");
993 error = dev->class->pm->prepare(dev);
994 suspend_report_result(dev->class->pm->prepare, error);
995 }
996 End:
Greg Kroah-Hartman8e9394c2010-02-17 10:57:05 -0800997 device_unlock(dev);
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +0100998
999 return error;
1000}
1001
1002/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001003 * dpm_prepare - Prepare all non-sysdev devices for a system PM transition.
1004 * @state: PM transition of the system being carried out.
Alan Sterncd59abf2007-09-21 15:36:56 -04001005 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001006 * Execute the ->prepare() callback(s) for all devices.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001007 */
1008static int dpm_prepare(pm_message_t state)
1009{
1010 struct list_head list;
1011 int error = 0;
1012
1013 INIT_LIST_HEAD(&list);
1014 mutex_lock(&dpm_list_mtx);
1015 transition_started = true;
1016 while (!list_empty(&dpm_list)) {
1017 struct device *dev = to_device(dpm_list.next);
1018
1019 get_device(dev);
1020 dev->power.status = DPM_PREPARING;
1021 mutex_unlock(&dpm_list_mtx);
1022
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +02001023 pm_runtime_get_noresume(dev);
1024 if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) {
1025 /* Wake-up requested during system sleep transition. */
Alan Sternaa0baae2009-12-21 02:46:11 +01001026 pm_runtime_put_sync(dev);
Rafael J. Wysocki5e928f72009-08-18 23:38:32 +02001027 error = -EBUSY;
1028 } else {
1029 error = device_prepare(dev, state);
1030 }
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001031
1032 mutex_lock(&dpm_list_mtx);
1033 if (error) {
1034 dev->power.status = DPM_ON;
1035 if (error == -EAGAIN) {
1036 put_device(dev);
Sebastian Ott886a7a32009-07-08 13:26:05 +02001037 error = 0;
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001038 continue;
1039 }
1040 printk(KERN_ERR "PM: Failed to prepare device %s "
1041 "for power transition: error %d\n",
1042 kobject_name(&dev->kobj), error);
1043 put_device(dev);
1044 break;
1045 }
1046 dev->power.status = DPM_SUSPENDING;
1047 if (!list_empty(&dev->power.entry))
1048 list_move_tail(&dev->power.entry, &list);
1049 put_device(dev);
1050 }
1051 list_splice(&list, &dpm_list);
1052 mutex_unlock(&dpm_list_mtx);
1053 return error;
1054}
1055
1056/**
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001057 * dpm_suspend_start - Prepare devices for PM transition and suspend them.
1058 * @state: PM transition of the system being carried out.
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001059 *
Rafael J. Wysocki20d652d2009-08-20 20:25:52 +02001060 * Prepare all non-sysdev devices for system PM transition and execute "suspend"
1061 * callbacks for them.
Alan Sterncd59abf2007-09-21 15:36:56 -04001062 */
Alan Sternd1616302009-05-24 22:05:42 +02001063int dpm_suspend_start(pm_message_t state)
Alan Sterncd59abf2007-09-21 15:36:56 -04001064{
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001065 int error;
Alan Sterncd59abf2007-09-21 15:36:56 -04001066
Rafael J. Wysocki775b64d2008-01-12 20:40:46 +01001067 might_sleep();
Rafael J. Wysocki1eede072008-05-20 23:00:01 +02001068 error = dpm_prepare(state);
1069 if (!error)
1070 error = dpm_suspend(state);
Alan Sterncd59abf2007-09-21 15:36:56 -04001071 return error;
Alan Sterncd59abf2007-09-21 15:36:56 -04001072}
Alan Sternd1616302009-05-24 22:05:42 +02001073EXPORT_SYMBOL_GPL(dpm_suspend_start);
Alan Sterncd59abf2007-09-21 15:36:56 -04001074
1075void __suspend_report_result(const char *function, void *fn, int ret)
1076{
Bjorn Helgaasc80cfb02008-10-15 22:01:35 -07001077 if (ret)
1078 printk(KERN_ERR "%s(): %pF returns %d\n", function, fn, ret);
Alan Sterncd59abf2007-09-21 15:36:56 -04001079}
1080EXPORT_SYMBOL_GPL(__suspend_report_result);
Rafael J. Wysockif8824ce2010-01-27 23:47:38 +01001081
1082/**
1083 * device_pm_wait_for_dev - Wait for suspend/resume of a device to complete.
1084 * @dev: Device to wait for.
1085 * @subordinate: Device that needs to wait for @dev.
1086 */
1087void device_pm_wait_for_dev(struct device *subordinate, struct device *dev)
1088{
1089 dpm_wait(dev, subordinate->power.async_suspend);
1090}
1091EXPORT_SYMBOL_GPL(device_pm_wait_for_dev);