diff options
Diffstat (limited to 'drivers/base/power/main.c')
-rw-r--r-- | drivers/base/power/main.c | 413 |
1 files changed, 212 insertions, 201 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 276d5a701dc3..06f09bf89cb2 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c | |||
@@ -8,7 +8,7 @@ | |||
8 | * | 8 | * |
9 | * | 9 | * |
10 | * The driver model core calls device_pm_add() when a device is registered. | 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 | 11 | * This will initialize the embedded device_pm_info object in the device |
12 | * and add it to the list of power-controlled devices. sysfs entries for | 12 | * and add it to the list of power-controlled devices. sysfs entries for |
13 | * controlling device power management will also be added. | 13 | * controlling device power management will also be added. |
14 | * | 14 | * |
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/interrupt.h> | 26 | #include <linux/interrupt.h> |
27 | #include <linux/sched.h> | 27 | #include <linux/sched.h> |
28 | #include <linux/async.h> | 28 | #include <linux/async.h> |
29 | #include <linux/suspend.h> | ||
29 | 30 | ||
30 | #include "../base.h" | 31 | #include "../base.h" |
31 | #include "power.h" | 32 | #include "power.h" |
@@ -41,15 +42,14 @@ | |||
41 | */ | 42 | */ |
42 | 43 | ||
43 | LIST_HEAD(dpm_list); | 44 | LIST_HEAD(dpm_list); |
45 | LIST_HEAD(dpm_prepared_list); | ||
46 | LIST_HEAD(dpm_suspended_list); | ||
47 | LIST_HEAD(dpm_noirq_list); | ||
44 | 48 | ||
45 | static DEFINE_MUTEX(dpm_list_mtx); | 49 | static DEFINE_MUTEX(dpm_list_mtx); |
46 | static pm_message_t pm_transition; | 50 | static pm_message_t pm_transition; |
47 | 51 | ||
48 | /* | 52 | static int async_error; |
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 | */ | ||
52 | static bool transition_started; | ||
53 | 53 | ||
54 | /** | 54 | /** |
55 | * device_pm_init - Initialize the PM-related part of a device object. | 55 | * device_pm_init - Initialize the PM-related part of a device object. |
@@ -57,11 +57,14 @@ static bool transition_started; | |||
57 | */ | 57 | */ |
58 | void device_pm_init(struct device *dev) | 58 | void device_pm_init(struct device *dev) |
59 | { | 59 | { |
60 | dev->power.status = DPM_ON; | 60 | dev->power.is_prepared = false; |
61 | dev->power.is_suspended = false; | ||
61 | init_completion(&dev->power.completion); | 62 | init_completion(&dev->power.completion); |
62 | complete_all(&dev->power.completion); | 63 | complete_all(&dev->power.completion); |
63 | dev->power.wakeup_count = 0; | 64 | dev->power.wakeup = NULL; |
65 | spin_lock_init(&dev->power.lock); | ||
64 | pm_runtime_init(dev); | 66 | pm_runtime_init(dev); |
67 | INIT_LIST_HEAD(&dev->power.entry); | ||
65 | } | 68 | } |
66 | 69 | ||
67 | /** | 70 | /** |
@@ -87,22 +90,11 @@ void device_pm_unlock(void) | |||
87 | void device_pm_add(struct device *dev) | 90 | void device_pm_add(struct device *dev) |
88 | { | 91 | { |
89 | pr_debug("PM: Adding info for %s:%s\n", | 92 | pr_debug("PM: Adding info for %s:%s\n", |
90 | dev->bus ? dev->bus->name : "No Bus", | 93 | dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); |
91 | kobject_name(&dev->kobj)); | ||
92 | mutex_lock(&dpm_list_mtx); | 94 | mutex_lock(&dpm_list_mtx); |
93 | if (dev->parent) { | 95 | if (dev->parent && dev->parent->power.is_prepared) |
94 | if (dev->parent->power.status >= DPM_SUSPENDING) | 96 | dev_warn(dev, "parent %s should not be sleeping\n", |
95 | dev_warn(dev, "parent %s should not be sleeping\n", | 97 | dev_name(dev->parent)); |
96 | dev_name(dev->parent)); | ||
97 | } else if (transition_started) { | ||
98 | /* | ||
99 | * We refuse to register parentless devices while a PM | ||
100 | * transition is in progress in order to avoid leaving them | ||
101 | * unhandled down the road | ||
102 | */ | ||
103 | dev_WARN(dev, "Parentless device registered during a PM transaction\n"); | ||
104 | } | ||
105 | |||
106 | list_add_tail(&dev->power.entry, &dpm_list); | 98 | list_add_tail(&dev->power.entry, &dpm_list); |
107 | mutex_unlock(&dpm_list_mtx); | 99 | mutex_unlock(&dpm_list_mtx); |
108 | } | 100 | } |
@@ -114,12 +106,12 @@ void device_pm_add(struct device *dev) | |||
114 | void device_pm_remove(struct device *dev) | 106 | void device_pm_remove(struct device *dev) |
115 | { | 107 | { |
116 | pr_debug("PM: Removing info for %s:%s\n", | 108 | pr_debug("PM: Removing info for %s:%s\n", |
117 | dev->bus ? dev->bus->name : "No Bus", | 109 | dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); |
118 | kobject_name(&dev->kobj)); | ||
119 | complete_all(&dev->power.completion); | 110 | complete_all(&dev->power.completion); |
120 | mutex_lock(&dpm_list_mtx); | 111 | mutex_lock(&dpm_list_mtx); |
121 | list_del_init(&dev->power.entry); | 112 | list_del_init(&dev->power.entry); |
122 | mutex_unlock(&dpm_list_mtx); | 113 | mutex_unlock(&dpm_list_mtx); |
114 | device_wakeup_disable(dev); | ||
123 | pm_runtime_remove(dev); | 115 | pm_runtime_remove(dev); |
124 | } | 116 | } |
125 | 117 | ||
@@ -131,10 +123,8 @@ void device_pm_remove(struct device *dev) | |||
131 | void device_pm_move_before(struct device *deva, struct device *devb) | 123 | void device_pm_move_before(struct device *deva, struct device *devb) |
132 | { | 124 | { |
133 | pr_debug("PM: Moving %s:%s before %s:%s\n", | 125 | pr_debug("PM: Moving %s:%s before %s:%s\n", |
134 | deva->bus ? deva->bus->name : "No Bus", | 126 | deva->bus ? deva->bus->name : "No Bus", dev_name(deva), |
135 | kobject_name(&deva->kobj), | 127 | devb->bus ? devb->bus->name : "No Bus", dev_name(devb)); |
136 | devb->bus ? devb->bus->name : "No Bus", | ||
137 | kobject_name(&devb->kobj)); | ||
138 | /* Delete deva from dpm_list and reinsert before devb. */ | 128 | /* Delete deva from dpm_list and reinsert before devb. */ |
139 | list_move_tail(&deva->power.entry, &devb->power.entry); | 129 | list_move_tail(&deva->power.entry, &devb->power.entry); |
140 | } | 130 | } |
@@ -147,10 +137,8 @@ void device_pm_move_before(struct device *deva, struct device *devb) | |||
147 | void device_pm_move_after(struct device *deva, struct device *devb) | 137 | void device_pm_move_after(struct device *deva, struct device *devb) |
148 | { | 138 | { |
149 | pr_debug("PM: Moving %s:%s after %s:%s\n", | 139 | pr_debug("PM: Moving %s:%s after %s:%s\n", |
150 | deva->bus ? deva->bus->name : "No Bus", | 140 | deva->bus ? deva->bus->name : "No Bus", dev_name(deva), |
151 | kobject_name(&deva->kobj), | 141 | devb->bus ? devb->bus->name : "No Bus", dev_name(devb)); |
152 | devb->bus ? devb->bus->name : "No Bus", | ||
153 | kobject_name(&devb->kobj)); | ||
154 | /* Delete deva from dpm_list and reinsert after devb. */ | 142 | /* Delete deva from dpm_list and reinsert after devb. */ |
155 | list_move(&deva->power.entry, &devb->power.entry); | 143 | list_move(&deva->power.entry, &devb->power.entry); |
156 | } | 144 | } |
@@ -162,8 +150,7 @@ void device_pm_move_after(struct device *deva, struct device *devb) | |||
162 | void device_pm_move_last(struct device *dev) | 150 | void device_pm_move_last(struct device *dev) |
163 | { | 151 | { |
164 | pr_debug("PM: Moving %s:%s to end of list\n", | 152 | pr_debug("PM: Moving %s:%s to end of list\n", |
165 | dev->bus ? dev->bus->name : "No Bus", | 153 | dev->bus ? dev->bus->name : "No Bus", dev_name(dev)); |
166 | kobject_name(&dev->kobj)); | ||
167 | list_move_tail(&dev->power.entry, &dpm_list); | 154 | list_move_tail(&dev->power.entry, &dpm_list); |
168 | } | 155 | } |
169 | 156 | ||
@@ -248,7 +235,7 @@ static int pm_op(struct device *dev, | |||
248 | } | 235 | } |
249 | break; | 236 | break; |
250 | #endif /* CONFIG_SUSPEND */ | 237 | #endif /* CONFIG_SUSPEND */ |
251 | #ifdef CONFIG_HIBERNATION | 238 | #ifdef CONFIG_HIBERNATE_CALLBACKS |
252 | case PM_EVENT_FREEZE: | 239 | case PM_EVENT_FREEZE: |
253 | case PM_EVENT_QUIESCE: | 240 | case PM_EVENT_QUIESCE: |
254 | if (ops->freeze) { | 241 | if (ops->freeze) { |
@@ -275,7 +262,7 @@ static int pm_op(struct device *dev, | |||
275 | suspend_report_result(ops->restore, error); | 262 | suspend_report_result(ops->restore, error); |
276 | } | 263 | } |
277 | break; | 264 | break; |
278 | #endif /* CONFIG_HIBERNATION */ | 265 | #endif /* CONFIG_HIBERNATE_CALLBACKS */ |
279 | default: | 266 | default: |
280 | error = -EINVAL; | 267 | error = -EINVAL; |
281 | } | 268 | } |
@@ -299,7 +286,7 @@ static int pm_noirq_op(struct device *dev, | |||
299 | pm_message_t state) | 286 | pm_message_t state) |
300 | { | 287 | { |
301 | int error = 0; | 288 | int error = 0; |
302 | ktime_t calltime, delta, rettime; | 289 | ktime_t calltime = ktime_set(0, 0), delta, rettime; |
303 | 290 | ||
304 | if (initcall_debug) { | 291 | if (initcall_debug) { |
305 | pr_info("calling %s+ @ %i, parent: %s\n", | 292 | pr_info("calling %s+ @ %i, parent: %s\n", |
@@ -323,7 +310,7 @@ static int pm_noirq_op(struct device *dev, | |||
323 | } | 310 | } |
324 | break; | 311 | break; |
325 | #endif /* CONFIG_SUSPEND */ | 312 | #endif /* CONFIG_SUSPEND */ |
326 | #ifdef CONFIG_HIBERNATION | 313 | #ifdef CONFIG_HIBERNATE_CALLBACKS |
327 | case PM_EVENT_FREEZE: | 314 | case PM_EVENT_FREEZE: |
328 | case PM_EVENT_QUIESCE: | 315 | case PM_EVENT_QUIESCE: |
329 | if (ops->freeze_noirq) { | 316 | if (ops->freeze_noirq) { |
@@ -350,7 +337,7 @@ static int pm_noirq_op(struct device *dev, | |||
350 | suspend_report_result(ops->restore_noirq, error); | 337 | suspend_report_result(ops->restore_noirq, error); |
351 | } | 338 | } |
352 | break; | 339 | break; |
353 | #endif /* CONFIG_HIBERNATION */ | 340 | #endif /* CONFIG_HIBERNATE_CALLBACKS */ |
354 | default: | 341 | default: |
355 | error = -EINVAL; | 342 | error = -EINVAL; |
356 | } | 343 | } |
@@ -401,13 +388,13 @@ static void pm_dev_err(struct device *dev, pm_message_t state, char *info, | |||
401 | int error) | 388 | int error) |
402 | { | 389 | { |
403 | printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n", | 390 | printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n", |
404 | kobject_name(&dev->kobj), pm_verb(state.event), info, error); | 391 | dev_name(dev), pm_verb(state.event), info, error); |
405 | } | 392 | } |
406 | 393 | ||
407 | static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info) | 394 | static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info) |
408 | { | 395 | { |
409 | ktime_t calltime; | 396 | ktime_t calltime; |
410 | s64 usecs64; | 397 | u64 usecs64; |
411 | int usecs; | 398 | int usecs; |
412 | 399 | ||
413 | calltime = ktime_get(); | 400 | calltime = ktime_get(); |
@@ -438,26 +425,20 @@ static int device_resume_noirq(struct device *dev, pm_message_t state) | |||
438 | TRACE_DEVICE(dev); | 425 | TRACE_DEVICE(dev); |
439 | TRACE_RESUME(0); | 426 | TRACE_RESUME(0); |
440 | 427 | ||
441 | if (dev->bus && dev->bus->pm) { | 428 | if (dev->pwr_domain) { |
442 | pm_dev_dbg(dev, state, "EARLY "); | 429 | pm_dev_dbg(dev, state, "EARLY power domain "); |
443 | error = pm_noirq_op(dev, dev->bus->pm, state); | 430 | error = pm_noirq_op(dev, &dev->pwr_domain->ops, state); |
444 | if (error) | 431 | } else if (dev->type && dev->type->pm) { |
445 | goto End; | ||
446 | } | ||
447 | |||
448 | if (dev->type && dev->type->pm) { | ||
449 | pm_dev_dbg(dev, state, "EARLY type "); | 432 | pm_dev_dbg(dev, state, "EARLY type "); |
450 | error = pm_noirq_op(dev, dev->type->pm, state); | 433 | error = pm_noirq_op(dev, dev->type->pm, state); |
451 | if (error) | 434 | } else if (dev->class && dev->class->pm) { |
452 | goto End; | ||
453 | } | ||
454 | |||
455 | if (dev->class && dev->class->pm) { | ||
456 | pm_dev_dbg(dev, state, "EARLY class "); | 435 | pm_dev_dbg(dev, state, "EARLY class "); |
457 | error = pm_noirq_op(dev, dev->class->pm, state); | 436 | error = pm_noirq_op(dev, dev->class->pm, state); |
437 | } else if (dev->bus && dev->bus->pm) { | ||
438 | pm_dev_dbg(dev, state, "EARLY "); | ||
439 | error = pm_noirq_op(dev, dev->bus->pm, state); | ||
458 | } | 440 | } |
459 | 441 | ||
460 | End: | ||
461 | TRACE_RESUME(error); | 442 | TRACE_RESUME(error); |
462 | return error; | 443 | return error; |
463 | } | 444 | } |
@@ -471,20 +452,24 @@ End: | |||
471 | */ | 452 | */ |
472 | void dpm_resume_noirq(pm_message_t state) | 453 | void dpm_resume_noirq(pm_message_t state) |
473 | { | 454 | { |
474 | struct device *dev; | ||
475 | ktime_t starttime = ktime_get(); | 455 | ktime_t starttime = ktime_get(); |
476 | 456 | ||
477 | mutex_lock(&dpm_list_mtx); | 457 | mutex_lock(&dpm_list_mtx); |
478 | transition_started = false; | 458 | while (!list_empty(&dpm_noirq_list)) { |
479 | list_for_each_entry(dev, &dpm_list, power.entry) | 459 | struct device *dev = to_device(dpm_noirq_list.next); |
480 | if (dev->power.status > DPM_OFF) { | 460 | int error; |
481 | int error; | ||
482 | 461 | ||
483 | dev->power.status = DPM_OFF; | 462 | get_device(dev); |
484 | error = device_resume_noirq(dev, state); | 463 | list_move_tail(&dev->power.entry, &dpm_suspended_list); |
485 | if (error) | 464 | mutex_unlock(&dpm_list_mtx); |
486 | pm_dev_err(dev, state, " early", error); | 465 | |
487 | } | 466 | error = device_resume_noirq(dev, state); |
467 | if (error) | ||
468 | pm_dev_err(dev, state, " early", error); | ||
469 | |||
470 | mutex_lock(&dpm_list_mtx); | ||
471 | put_device(dev); | ||
472 | } | ||
488 | mutex_unlock(&dpm_list_mtx); | 473 | mutex_unlock(&dpm_list_mtx); |
489 | dpm_show_time(starttime, state, "early"); | 474 | dpm_show_time(starttime, state, "early"); |
490 | resume_device_irqs(); | 475 | resume_device_irqs(); |
@@ -527,39 +512,53 @@ static int device_resume(struct device *dev, pm_message_t state, bool async) | |||
527 | dpm_wait(dev->parent, async); | 512 | dpm_wait(dev->parent, async); |
528 | device_lock(dev); | 513 | device_lock(dev); |
529 | 514 | ||
530 | dev->power.status = DPM_RESUMING; | 515 | /* |
516 | * This is a fib. But we'll allow new children to be added below | ||
517 | * a resumed device, even if the device hasn't been completed yet. | ||
518 | */ | ||
519 | dev->power.is_prepared = false; | ||
531 | 520 | ||
532 | if (dev->bus) { | 521 | if (!dev->power.is_suspended) |
533 | if (dev->bus->pm) { | 522 | goto Unlock; |
534 | pm_dev_dbg(dev, state, ""); | 523 | |
535 | error = pm_op(dev, dev->bus->pm, state); | 524 | if (dev->pwr_domain) { |
536 | } else if (dev->bus->resume) { | 525 | pm_dev_dbg(dev, state, "power domain "); |
537 | pm_dev_dbg(dev, state, "legacy "); | 526 | error = pm_op(dev, &dev->pwr_domain->ops, state); |
538 | error = legacy_resume(dev, dev->bus->resume); | 527 | goto End; |
539 | } | ||
540 | if (error) | ||
541 | goto End; | ||
542 | } | 528 | } |
543 | 529 | ||
544 | if (dev->type) { | 530 | if (dev->type && dev->type->pm) { |
545 | if (dev->type->pm) { | 531 | pm_dev_dbg(dev, state, "type "); |
546 | pm_dev_dbg(dev, state, "type "); | 532 | error = pm_op(dev, dev->type->pm, state); |
547 | error = pm_op(dev, dev->type->pm, state); | 533 | goto End; |
548 | } | ||
549 | if (error) | ||
550 | goto End; | ||
551 | } | 534 | } |
552 | 535 | ||
553 | if (dev->class) { | 536 | if (dev->class) { |
554 | if (dev->class->pm) { | 537 | if (dev->class->pm) { |
555 | pm_dev_dbg(dev, state, "class "); | 538 | pm_dev_dbg(dev, state, "class "); |
556 | error = pm_op(dev, dev->class->pm, state); | 539 | error = pm_op(dev, dev->class->pm, state); |
540 | goto End; | ||
557 | } else if (dev->class->resume) { | 541 | } else if (dev->class->resume) { |
558 | pm_dev_dbg(dev, state, "legacy class "); | 542 | pm_dev_dbg(dev, state, "legacy class "); |
559 | error = legacy_resume(dev, dev->class->resume); | 543 | error = legacy_resume(dev, dev->class->resume); |
544 | goto End; | ||
560 | } | 545 | } |
561 | } | 546 | } |
547 | |||
548 | if (dev->bus) { | ||
549 | if (dev->bus->pm) { | ||
550 | pm_dev_dbg(dev, state, ""); | ||
551 | error = pm_op(dev, dev->bus->pm, state); | ||
552 | } else if (dev->bus->resume) { | ||
553 | pm_dev_dbg(dev, state, "legacy "); | ||
554 | error = legacy_resume(dev, dev->bus->resume); | ||
555 | } | ||
556 | } | ||
557 | |||
562 | End: | 558 | End: |
559 | dev->power.is_suspended = false; | ||
560 | |||
561 | Unlock: | ||
563 | device_unlock(dev); | 562 | device_unlock(dev); |
564 | complete_all(&dev->power.completion); | 563 | complete_all(&dev->power.completion); |
565 | 564 | ||
@@ -591,20 +590,18 @@ static bool is_async(struct device *dev) | |||
591 | * Execute the appropriate "resume" callback for all devices whose status | 590 | * Execute the appropriate "resume" callback for all devices whose status |
592 | * indicates that they are suspended. | 591 | * indicates that they are suspended. |
593 | */ | 592 | */ |
594 | static void dpm_resume(pm_message_t state) | 593 | void dpm_resume(pm_message_t state) |
595 | { | 594 | { |
596 | struct list_head list; | ||
597 | struct device *dev; | 595 | struct device *dev; |
598 | ktime_t starttime = ktime_get(); | 596 | ktime_t starttime = ktime_get(); |
599 | 597 | ||
600 | INIT_LIST_HEAD(&list); | 598 | might_sleep(); |
599 | |||
601 | mutex_lock(&dpm_list_mtx); | 600 | mutex_lock(&dpm_list_mtx); |
602 | pm_transition = state; | 601 | pm_transition = state; |
602 | async_error = 0; | ||
603 | 603 | ||
604 | list_for_each_entry(dev, &dpm_list, power.entry) { | 604 | list_for_each_entry(dev, &dpm_suspended_list, power.entry) { |
605 | if (dev->power.status < DPM_OFF) | ||
606 | continue; | ||
607 | |||
608 | INIT_COMPLETION(dev->power.completion); | 605 | INIT_COMPLETION(dev->power.completion); |
609 | if (is_async(dev)) { | 606 | if (is_async(dev)) { |
610 | get_device(dev); | 607 | get_device(dev); |
@@ -612,28 +609,24 @@ static void dpm_resume(pm_message_t state) | |||
612 | } | 609 | } |
613 | } | 610 | } |
614 | 611 | ||
615 | while (!list_empty(&dpm_list)) { | 612 | while (!list_empty(&dpm_suspended_list)) { |
616 | dev = to_device(dpm_list.next); | 613 | dev = to_device(dpm_suspended_list.next); |
617 | get_device(dev); | 614 | get_device(dev); |
618 | if (dev->power.status >= DPM_OFF && !is_async(dev)) { | 615 | if (!is_async(dev)) { |
619 | int error; | 616 | int error; |
620 | 617 | ||
621 | mutex_unlock(&dpm_list_mtx); | 618 | mutex_unlock(&dpm_list_mtx); |
622 | 619 | ||
623 | error = device_resume(dev, state, false); | 620 | error = device_resume(dev, state, false); |
624 | |||
625 | mutex_lock(&dpm_list_mtx); | ||
626 | if (error) | 621 | if (error) |
627 | pm_dev_err(dev, state, "", error); | 622 | pm_dev_err(dev, state, "", error); |
628 | } else if (dev->power.status == DPM_SUSPENDING) { | 623 | |
629 | /* Allow new children of the device to be registered */ | 624 | mutex_lock(&dpm_list_mtx); |
630 | dev->power.status = DPM_RESUMING; | ||
631 | } | 625 | } |
632 | if (!list_empty(&dev->power.entry)) | 626 | if (!list_empty(&dev->power.entry)) |
633 | list_move_tail(&dev->power.entry, &list); | 627 | list_move_tail(&dev->power.entry, &dpm_prepared_list); |
634 | put_device(dev); | 628 | put_device(dev); |
635 | } | 629 | } |
636 | list_splice(&list, &dpm_list); | ||
637 | mutex_unlock(&dpm_list_mtx); | 630 | mutex_unlock(&dpm_list_mtx); |
638 | async_synchronize_full(); | 631 | async_synchronize_full(); |
639 | dpm_show_time(starttime, state, NULL); | 632 | dpm_show_time(starttime, state, NULL); |
@@ -648,19 +641,22 @@ static void device_complete(struct device *dev, pm_message_t state) | |||
648 | { | 641 | { |
649 | device_lock(dev); | 642 | device_lock(dev); |
650 | 643 | ||
651 | if (dev->class && dev->class->pm && dev->class->pm->complete) { | 644 | if (dev->pwr_domain) { |
652 | pm_dev_dbg(dev, state, "completing class "); | 645 | pm_dev_dbg(dev, state, "completing power domain "); |
653 | dev->class->pm->complete(dev); | 646 | if (dev->pwr_domain->ops.complete) |
654 | } | 647 | dev->pwr_domain->ops.complete(dev); |
655 | 648 | } else if (dev->type && dev->type->pm) { | |
656 | if (dev->type && dev->type->pm && dev->type->pm->complete) { | ||
657 | pm_dev_dbg(dev, state, "completing type "); | 649 | pm_dev_dbg(dev, state, "completing type "); |
658 | dev->type->pm->complete(dev); | 650 | if (dev->type->pm->complete) |
659 | } | 651 | dev->type->pm->complete(dev); |
660 | 652 | } else if (dev->class && dev->class->pm) { | |
661 | if (dev->bus && dev->bus->pm && dev->bus->pm->complete) { | 653 | pm_dev_dbg(dev, state, "completing class "); |
654 | if (dev->class->pm->complete) | ||
655 | dev->class->pm->complete(dev); | ||
656 | } else if (dev->bus && dev->bus->pm) { | ||
662 | pm_dev_dbg(dev, state, "completing "); | 657 | pm_dev_dbg(dev, state, "completing "); |
663 | dev->bus->pm->complete(dev); | 658 | if (dev->bus->pm->complete) |
659 | dev->bus->pm->complete(dev); | ||
664 | } | 660 | } |
665 | 661 | ||
666 | device_unlock(dev); | 662 | device_unlock(dev); |
@@ -673,28 +669,25 @@ static void device_complete(struct device *dev, pm_message_t state) | |||
673 | * Execute the ->complete() callbacks for all devices whose PM status is not | 669 | * Execute the ->complete() callbacks for all devices whose PM status is not |
674 | * DPM_ON (this allows new devices to be registered). | 670 | * DPM_ON (this allows new devices to be registered). |
675 | */ | 671 | */ |
676 | static void dpm_complete(pm_message_t state) | 672 | void dpm_complete(pm_message_t state) |
677 | { | 673 | { |
678 | struct list_head list; | 674 | struct list_head list; |
679 | 675 | ||
676 | might_sleep(); | ||
677 | |||
680 | INIT_LIST_HEAD(&list); | 678 | INIT_LIST_HEAD(&list); |
681 | mutex_lock(&dpm_list_mtx); | 679 | mutex_lock(&dpm_list_mtx); |
682 | transition_started = false; | 680 | while (!list_empty(&dpm_prepared_list)) { |
683 | while (!list_empty(&dpm_list)) { | 681 | struct device *dev = to_device(dpm_prepared_list.prev); |
684 | struct device *dev = to_device(dpm_list.prev); | ||
685 | 682 | ||
686 | get_device(dev); | 683 | get_device(dev); |
687 | if (dev->power.status > DPM_ON) { | 684 | dev->power.is_prepared = false; |
688 | dev->power.status = DPM_ON; | 685 | list_move(&dev->power.entry, &list); |
689 | mutex_unlock(&dpm_list_mtx); | 686 | mutex_unlock(&dpm_list_mtx); |
690 | 687 | ||
691 | device_complete(dev, state); | 688 | device_complete(dev, state); |
692 | pm_runtime_put_sync(dev); | ||
693 | 689 | ||
694 | mutex_lock(&dpm_list_mtx); | 690 | mutex_lock(&dpm_list_mtx); |
695 | } | ||
696 | if (!list_empty(&dev->power.entry)) | ||
697 | list_move(&dev->power.entry, &list); | ||
698 | put_device(dev); | 691 | put_device(dev); |
699 | } | 692 | } |
700 | list_splice(&list, &dpm_list); | 693 | list_splice(&list, &dpm_list); |
@@ -710,7 +703,6 @@ static void dpm_complete(pm_message_t state) | |||
710 | */ | 703 | */ |
711 | void dpm_resume_end(pm_message_t state) | 704 | void dpm_resume_end(pm_message_t state) |
712 | { | 705 | { |
713 | might_sleep(); | ||
714 | dpm_resume(state); | 706 | dpm_resume(state); |
715 | dpm_complete(state); | 707 | dpm_complete(state); |
716 | } | 708 | } |
@@ -750,29 +742,31 @@ static pm_message_t resume_event(pm_message_t sleep_state) | |||
750 | */ | 742 | */ |
751 | static int device_suspend_noirq(struct device *dev, pm_message_t state) | 743 | static int device_suspend_noirq(struct device *dev, pm_message_t state) |
752 | { | 744 | { |
753 | int error = 0; | 745 | int error; |
754 | 746 | ||
755 | if (dev->class && dev->class->pm) { | 747 | if (dev->pwr_domain) { |
756 | pm_dev_dbg(dev, state, "LATE class "); | 748 | pm_dev_dbg(dev, state, "LATE power domain "); |
757 | error = pm_noirq_op(dev, dev->class->pm, state); | 749 | error = pm_noirq_op(dev, &dev->pwr_domain->ops, state); |
758 | if (error) | 750 | if (error) |
759 | goto End; | 751 | return error; |
760 | } | 752 | } else if (dev->type && dev->type->pm) { |
761 | |||
762 | if (dev->type && dev->type->pm) { | ||
763 | pm_dev_dbg(dev, state, "LATE type "); | 753 | pm_dev_dbg(dev, state, "LATE type "); |
764 | error = pm_noirq_op(dev, dev->type->pm, state); | 754 | error = pm_noirq_op(dev, dev->type->pm, state); |
765 | if (error) | 755 | if (error) |
766 | goto End; | 756 | return error; |
767 | } | 757 | } else if (dev->class && dev->class->pm) { |
768 | 758 | pm_dev_dbg(dev, state, "LATE class "); | |
769 | if (dev->bus && dev->bus->pm) { | 759 | error = pm_noirq_op(dev, dev->class->pm, state); |
760 | if (error) | ||
761 | return error; | ||
762 | } else if (dev->bus && dev->bus->pm) { | ||
770 | pm_dev_dbg(dev, state, "LATE "); | 763 | pm_dev_dbg(dev, state, "LATE "); |
771 | error = pm_noirq_op(dev, dev->bus->pm, state); | 764 | error = pm_noirq_op(dev, dev->bus->pm, state); |
765 | if (error) | ||
766 | return error; | ||
772 | } | 767 | } |
773 | 768 | ||
774 | End: | 769 | return 0; |
775 | return error; | ||
776 | } | 770 | } |
777 | 771 | ||
778 | /** | 772 | /** |
@@ -784,19 +778,28 @@ End: | |||
784 | */ | 778 | */ |
785 | int dpm_suspend_noirq(pm_message_t state) | 779 | int dpm_suspend_noirq(pm_message_t state) |
786 | { | 780 | { |
787 | struct device *dev; | ||
788 | ktime_t starttime = ktime_get(); | 781 | ktime_t starttime = ktime_get(); |
789 | int error = 0; | 782 | int error = 0; |
790 | 783 | ||
791 | suspend_device_irqs(); | 784 | suspend_device_irqs(); |
792 | mutex_lock(&dpm_list_mtx); | 785 | mutex_lock(&dpm_list_mtx); |
793 | list_for_each_entry_reverse(dev, &dpm_list, power.entry) { | 786 | while (!list_empty(&dpm_suspended_list)) { |
787 | struct device *dev = to_device(dpm_suspended_list.prev); | ||
788 | |||
789 | get_device(dev); | ||
790 | mutex_unlock(&dpm_list_mtx); | ||
791 | |||
794 | error = device_suspend_noirq(dev, state); | 792 | error = device_suspend_noirq(dev, state); |
793 | |||
794 | mutex_lock(&dpm_list_mtx); | ||
795 | if (error) { | 795 | if (error) { |
796 | pm_dev_err(dev, state, " late", error); | 796 | pm_dev_err(dev, state, " late", error); |
797 | put_device(dev); | ||
797 | break; | 798 | break; |
798 | } | 799 | } |
799 | dev->power.status = DPM_OFF_IRQ; | 800 | if (!list_empty(&dev->power.entry)) |
801 | list_move(&dev->power.entry, &dpm_noirq_list); | ||
802 | put_device(dev); | ||
800 | } | 803 | } |
801 | mutex_unlock(&dpm_list_mtx); | 804 | mutex_unlock(&dpm_list_mtx); |
802 | if (error) | 805 | if (error) |
@@ -829,8 +832,6 @@ static int legacy_suspend(struct device *dev, pm_message_t state, | |||
829 | return error; | 832 | return error; |
830 | } | 833 | } |
831 | 834 | ||
832 | static int async_error; | ||
833 | |||
834 | /** | 835 | /** |
835 | * device_suspend - Execute "suspend" callbacks for given device. | 836 | * device_suspend - Execute "suspend" callbacks for given device. |
836 | * @dev: Device to handle. | 837 | * @dev: Device to handle. |
@@ -845,27 +846,35 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
845 | device_lock(dev); | 846 | device_lock(dev); |
846 | 847 | ||
847 | if (async_error) | 848 | if (async_error) |
849 | goto Unlock; | ||
850 | |||
851 | if (pm_wakeup_pending()) { | ||
852 | async_error = -EBUSY; | ||
853 | goto Unlock; | ||
854 | } | ||
855 | |||
856 | if (dev->pwr_domain) { | ||
857 | pm_dev_dbg(dev, state, "power domain "); | ||
858 | error = pm_op(dev, &dev->pwr_domain->ops, state); | ||
848 | goto End; | 859 | goto End; |
860 | } | ||
861 | |||
862 | if (dev->type && dev->type->pm) { | ||
863 | pm_dev_dbg(dev, state, "type "); | ||
864 | error = pm_op(dev, dev->type->pm, state); | ||
865 | goto End; | ||
866 | } | ||
849 | 867 | ||
850 | if (dev->class) { | 868 | if (dev->class) { |
851 | if (dev->class->pm) { | 869 | if (dev->class->pm) { |
852 | pm_dev_dbg(dev, state, "class "); | 870 | pm_dev_dbg(dev, state, "class "); |
853 | error = pm_op(dev, dev->class->pm, state); | 871 | error = pm_op(dev, dev->class->pm, state); |
872 | goto End; | ||
854 | } else if (dev->class->suspend) { | 873 | } else if (dev->class->suspend) { |
855 | pm_dev_dbg(dev, state, "legacy class "); | 874 | pm_dev_dbg(dev, state, "legacy class "); |
856 | error = legacy_suspend(dev, state, dev->class->suspend); | 875 | error = legacy_suspend(dev, state, dev->class->suspend); |
857 | } | ||
858 | if (error) | ||
859 | goto End; | 876 | goto End; |
860 | } | ||
861 | |||
862 | if (dev->type) { | ||
863 | if (dev->type->pm) { | ||
864 | pm_dev_dbg(dev, state, "type "); | ||
865 | error = pm_op(dev, dev->type->pm, state); | ||
866 | } | 877 | } |
867 | if (error) | ||
868 | goto End; | ||
869 | } | 878 | } |
870 | 879 | ||
871 | if (dev->bus) { | 880 | if (dev->bus) { |
@@ -878,13 +887,16 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) | |||
878 | } | 887 | } |
879 | } | 888 | } |
880 | 889 | ||
881 | if (!error) | ||
882 | dev->power.status = DPM_OFF; | ||
883 | |||
884 | End: | 890 | End: |
891 | dev->power.is_suspended = !error; | ||
892 | |||
893 | Unlock: | ||
885 | device_unlock(dev); | 894 | device_unlock(dev); |
886 | complete_all(&dev->power.completion); | 895 | complete_all(&dev->power.completion); |
887 | 896 | ||
897 | if (error) | ||
898 | async_error = error; | ||
899 | |||
888 | return error; | 900 | return error; |
889 | } | 901 | } |
890 | 902 | ||
@@ -894,10 +906,8 @@ static void async_suspend(void *data, async_cookie_t cookie) | |||
894 | int error; | 906 | int error; |
895 | 907 | ||
896 | error = __device_suspend(dev, pm_transition, true); | 908 | error = __device_suspend(dev, pm_transition, true); |
897 | if (error) { | 909 | if (error) |
898 | pm_dev_err(dev, pm_transition, " async", error); | 910 | pm_dev_err(dev, pm_transition, " async", error); |
899 | async_error = error; | ||
900 | } | ||
901 | 911 | ||
902 | put_device(dev); | 912 | put_device(dev); |
903 | } | 913 | } |
@@ -919,18 +929,18 @@ static int device_suspend(struct device *dev) | |||
919 | * dpm_suspend - Execute "suspend" callbacks for all non-sysdev devices. | 929 | * dpm_suspend - Execute "suspend" callbacks for all non-sysdev devices. |
920 | * @state: PM transition of the system being carried out. | 930 | * @state: PM transition of the system being carried out. |
921 | */ | 931 | */ |
922 | static int dpm_suspend(pm_message_t state) | 932 | int dpm_suspend(pm_message_t state) |
923 | { | 933 | { |
924 | struct list_head list; | ||
925 | ktime_t starttime = ktime_get(); | 934 | ktime_t starttime = ktime_get(); |
926 | int error = 0; | 935 | int error = 0; |
927 | 936 | ||
928 | INIT_LIST_HEAD(&list); | 937 | might_sleep(); |
938 | |||
929 | mutex_lock(&dpm_list_mtx); | 939 | mutex_lock(&dpm_list_mtx); |
930 | pm_transition = state; | 940 | pm_transition = state; |
931 | async_error = 0; | 941 | async_error = 0; |
932 | while (!list_empty(&dpm_list)) { | 942 | while (!list_empty(&dpm_prepared_list)) { |
933 | struct device *dev = to_device(dpm_list.prev); | 943 | struct device *dev = to_device(dpm_prepared_list.prev); |
934 | 944 | ||
935 | get_device(dev); | 945 | get_device(dev); |
936 | mutex_unlock(&dpm_list_mtx); | 946 | mutex_unlock(&dpm_list_mtx); |
@@ -944,12 +954,11 @@ static int dpm_suspend(pm_message_t state) | |||
944 | break; | 954 | break; |
945 | } | 955 | } |
946 | if (!list_empty(&dev->power.entry)) | 956 | if (!list_empty(&dev->power.entry)) |
947 | list_move(&dev->power.entry, &list); | 957 | list_move(&dev->power.entry, &dpm_suspended_list); |
948 | put_device(dev); | 958 | put_device(dev); |
949 | if (async_error) | 959 | if (async_error) |
950 | break; | 960 | break; |
951 | } | 961 | } |
952 | list_splice(&list, dpm_list.prev); | ||
953 | mutex_unlock(&dpm_list_mtx); | 962 | mutex_unlock(&dpm_list_mtx); |
954 | async_synchronize_full(); | 963 | async_synchronize_full(); |
955 | if (!error) | 964 | if (!error) |
@@ -973,27 +982,34 @@ static int device_prepare(struct device *dev, pm_message_t state) | |||
973 | 982 | ||
974 | device_lock(dev); | 983 | device_lock(dev); |
975 | 984 | ||
976 | if (dev->bus && dev->bus->pm && dev->bus->pm->prepare) { | 985 | if (dev->pwr_domain) { |
977 | pm_dev_dbg(dev, state, "preparing "); | 986 | pm_dev_dbg(dev, state, "preparing power domain "); |
978 | error = dev->bus->pm->prepare(dev); | 987 | if (dev->pwr_domain->ops.prepare) |
979 | suspend_report_result(dev->bus->pm->prepare, error); | 988 | error = dev->pwr_domain->ops.prepare(dev); |
989 | suspend_report_result(dev->pwr_domain->ops.prepare, error); | ||
980 | if (error) | 990 | if (error) |
981 | goto End; | 991 | goto End; |
982 | } | 992 | } else if (dev->type && dev->type->pm) { |
983 | |||
984 | if (dev->type && dev->type->pm && dev->type->pm->prepare) { | ||
985 | pm_dev_dbg(dev, state, "preparing type "); | 993 | pm_dev_dbg(dev, state, "preparing type "); |
986 | error = dev->type->pm->prepare(dev); | 994 | if (dev->type->pm->prepare) |
995 | error = dev->type->pm->prepare(dev); | ||
987 | suspend_report_result(dev->type->pm->prepare, error); | 996 | suspend_report_result(dev->type->pm->prepare, error); |
988 | if (error) | 997 | if (error) |
989 | goto End; | 998 | goto End; |
990 | } | 999 | } else if (dev->class && dev->class->pm) { |
991 | |||
992 | if (dev->class && dev->class->pm && dev->class->pm->prepare) { | ||
993 | pm_dev_dbg(dev, state, "preparing class "); | 1000 | pm_dev_dbg(dev, state, "preparing class "); |
994 | error = dev->class->pm->prepare(dev); | 1001 | if (dev->class->pm->prepare) |
1002 | error = dev->class->pm->prepare(dev); | ||
995 | suspend_report_result(dev->class->pm->prepare, error); | 1003 | suspend_report_result(dev->class->pm->prepare, error); |
1004 | if (error) | ||
1005 | goto End; | ||
1006 | } else if (dev->bus && dev->bus->pm) { | ||
1007 | pm_dev_dbg(dev, state, "preparing "); | ||
1008 | if (dev->bus->pm->prepare) | ||
1009 | error = dev->bus->pm->prepare(dev); | ||
1010 | suspend_report_result(dev->bus->pm->prepare, error); | ||
996 | } | 1011 | } |
1012 | |||
997 | End: | 1013 | End: |
998 | device_unlock(dev); | 1014 | device_unlock(dev); |
999 | 1015 | ||
@@ -1006,50 +1022,45 @@ static int device_prepare(struct device *dev, pm_message_t state) | |||
1006 | * | 1022 | * |
1007 | * Execute the ->prepare() callback(s) for all devices. | 1023 | * Execute the ->prepare() callback(s) for all devices. |
1008 | */ | 1024 | */ |
1009 | static int dpm_prepare(pm_message_t state) | 1025 | int dpm_prepare(pm_message_t state) |
1010 | { | 1026 | { |
1011 | struct list_head list; | ||
1012 | int error = 0; | 1027 | int error = 0; |
1013 | 1028 | ||
1014 | INIT_LIST_HEAD(&list); | 1029 | might_sleep(); |
1030 | |||
1015 | mutex_lock(&dpm_list_mtx); | 1031 | mutex_lock(&dpm_list_mtx); |
1016 | transition_started = true; | ||
1017 | while (!list_empty(&dpm_list)) { | 1032 | while (!list_empty(&dpm_list)) { |
1018 | struct device *dev = to_device(dpm_list.next); | 1033 | struct device *dev = to_device(dpm_list.next); |
1019 | 1034 | ||
1020 | get_device(dev); | 1035 | get_device(dev); |
1021 | dev->power.status = DPM_PREPARING; | ||
1022 | mutex_unlock(&dpm_list_mtx); | 1036 | mutex_unlock(&dpm_list_mtx); |
1023 | 1037 | ||
1024 | pm_runtime_get_noresume(dev); | 1038 | pm_runtime_get_noresume(dev); |
1025 | if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) { | 1039 | if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) |
1026 | /* Wake-up requested during system sleep transition. */ | 1040 | pm_wakeup_event(dev, 0); |
1027 | pm_runtime_put_sync(dev); | 1041 | |
1028 | error = -EBUSY; | 1042 | pm_runtime_put_sync(dev); |
1029 | } else { | 1043 | error = pm_wakeup_pending() ? |
1030 | error = device_prepare(dev, state); | 1044 | -EBUSY : device_prepare(dev, state); |
1031 | } | ||
1032 | 1045 | ||
1033 | mutex_lock(&dpm_list_mtx); | 1046 | mutex_lock(&dpm_list_mtx); |
1034 | if (error) { | 1047 | if (error) { |
1035 | dev->power.status = DPM_ON; | ||
1036 | if (error == -EAGAIN) { | 1048 | if (error == -EAGAIN) { |
1037 | put_device(dev); | 1049 | put_device(dev); |
1038 | error = 0; | 1050 | error = 0; |
1039 | continue; | 1051 | continue; |
1040 | } | 1052 | } |
1041 | printk(KERN_ERR "PM: Failed to prepare device %s " | 1053 | printk(KERN_INFO "PM: Device %s not prepared " |
1042 | "for power transition: error %d\n", | 1054 | "for power transition: code %d\n", |
1043 | kobject_name(&dev->kobj), error); | 1055 | dev_name(dev), error); |
1044 | put_device(dev); | 1056 | put_device(dev); |
1045 | break; | 1057 | break; |
1046 | } | 1058 | } |
1047 | dev->power.status = DPM_SUSPENDING; | 1059 | dev->power.is_prepared = true; |
1048 | if (!list_empty(&dev->power.entry)) | 1060 | if (!list_empty(&dev->power.entry)) |
1049 | list_move_tail(&dev->power.entry, &list); | 1061 | list_move_tail(&dev->power.entry, &dpm_prepared_list); |
1050 | put_device(dev); | 1062 | put_device(dev); |
1051 | } | 1063 | } |
1052 | list_splice(&list, &dpm_list); | ||
1053 | mutex_unlock(&dpm_list_mtx); | 1064 | mutex_unlock(&dpm_list_mtx); |
1054 | return error; | 1065 | return error; |
1055 | } | 1066 | } |
@@ -1065,7 +1076,6 @@ int dpm_suspend_start(pm_message_t state) | |||
1065 | { | 1076 | { |
1066 | int error; | 1077 | int error; |
1067 | 1078 | ||
1068 | might_sleep(); | ||
1069 | error = dpm_prepare(state); | 1079 | error = dpm_prepare(state); |
1070 | if (!error) | 1080 | if (!error) |
1071 | error = dpm_suspend(state); | 1081 | error = dpm_suspend(state); |
@@ -1085,8 +1095,9 @@ EXPORT_SYMBOL_GPL(__suspend_report_result); | |||
1085 | * @dev: Device to wait for. | 1095 | * @dev: Device to wait for. |
1086 | * @subordinate: Device that needs to wait for @dev. | 1096 | * @subordinate: Device that needs to wait for @dev. |
1087 | */ | 1097 | */ |
1088 | void device_pm_wait_for_dev(struct device *subordinate, struct device *dev) | 1098 | int device_pm_wait_for_dev(struct device *subordinate, struct device *dev) |
1089 | { | 1099 | { |
1090 | dpm_wait(dev, subordinate->power.async_suspend); | 1100 | dpm_wait(dev, subordinate->power.async_suspend); |
1101 | return async_error; | ||
1091 | } | 1102 | } |
1092 | EXPORT_SYMBOL_GPL(device_pm_wait_for_dev); | 1103 | EXPORT_SYMBOL_GPL(device_pm_wait_for_dev); |