aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base/power/main.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-01-10 11:14:53 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-10 11:14:53 -0500
commitc8940eca75e6d1ea57f6c491a30bd1023c64c9ad (patch)
treed68944ab9fa8ba3c77b18edc2bd836c7e355b23e /drivers/base/power/main.c
parent78c92a9fd4b6abbbc1fe1ec335c697cb4e63f252 (diff)
parent3ae22e8c8ac39daf88ae32f047fb23825be7c646 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/suspend-2.6: spi / PM: Support dev_pm_ops PM: Prototype the pm_generic_ operations PM / Runtime: Generic resume shouldn't set RPM_ACTIVE unconditionally PM: Use dev_name() in core device suspend and resume routines PM: Permit registration of parentless devices during system suspend PM: Replace the device power.status field with a bit field PM: Remove redundant checks from core device resume routines PM: Use a different list of devices for each stage of device suspend PM: Avoid compiler warning in pm_noirq_op() PM: Use pm_wakeup_pending() in __device_suspend() PM / Wakeup: Replace pm_check_wakeup_events() with pm_wakeup_pending() PM: Prevent dpm_prepare() from returning errors unnecessarily PM: Fix references to basic-pm-debugging.txt in drivers-testing.txt PM / Runtime: Add synchronous runtime interface for interrupt handlers (v3) PM / Hibernate: When failed, in_suspend should be reset PM / Hibernate: hibernation_ops->leave should be checked too Freezer: Fix a race during freezing of TASK_STOPPED tasks PM: Use proper ccflag flag in kernel/power/Makefile PM / Runtime: Fix comments to match runtime callback code
Diffstat (limited to 'drivers/base/power/main.c')
-rw-r--r--drivers/base/power/main.c174
1 files changed, 62 insertions, 112 deletions
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index ead3e79d6fcf..2a52270aeb30 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -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,16 +42,13 @@
41 */ 42 */
42 43
43LIST_HEAD(dpm_list); 44LIST_HEAD(dpm_list);
45LIST_HEAD(dpm_prepared_list);
46LIST_HEAD(dpm_suspended_list);
47LIST_HEAD(dpm_noirq_list);
44 48
45static DEFINE_MUTEX(dpm_list_mtx); 49static DEFINE_MUTEX(dpm_list_mtx);
46static pm_message_t pm_transition; 50static pm_message_t pm_transition;
47 51
48/*
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
54static int async_error; 52static int async_error;
55 53
56/** 54/**
@@ -59,7 +57,7 @@ static int async_error;
59 */ 57 */
60void device_pm_init(struct device *dev) 58void device_pm_init(struct device *dev)
61{ 59{
62 dev->power.status = DPM_ON; 60 dev->power.in_suspend = false;
63 init_completion(&dev->power.completion); 61 init_completion(&dev->power.completion);
64 complete_all(&dev->power.completion); 62 complete_all(&dev->power.completion);
65 dev->power.wakeup = NULL; 63 dev->power.wakeup = NULL;
@@ -90,22 +88,11 @@ void device_pm_unlock(void)
90void device_pm_add(struct device *dev) 88void device_pm_add(struct device *dev)
91{ 89{
92 pr_debug("PM: Adding info for %s:%s\n", 90 pr_debug("PM: Adding info for %s:%s\n",
93 dev->bus ? dev->bus->name : "No Bus", 91 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
94 kobject_name(&dev->kobj));
95 mutex_lock(&dpm_list_mtx); 92 mutex_lock(&dpm_list_mtx);
96 if (dev->parent) { 93 if (dev->parent && dev->parent->power.in_suspend)
97 if (dev->parent->power.status >= DPM_SUSPENDING) 94 dev_warn(dev, "parent %s should not be sleeping\n",
98 dev_warn(dev, "parent %s should not be sleeping\n", 95 dev_name(dev->parent));
99 dev_name(dev->parent));
100 } else if (transition_started) {
101 /*
102 * We refuse to register parentless devices while a PM
103 * transition is in progress in order to avoid leaving them
104 * unhandled down the road
105 */
106 dev_WARN(dev, "Parentless device registered during a PM transaction\n");
107 }
108
109 list_add_tail(&dev->power.entry, &dpm_list); 96 list_add_tail(&dev->power.entry, &dpm_list);
110 mutex_unlock(&dpm_list_mtx); 97 mutex_unlock(&dpm_list_mtx);
111} 98}
@@ -117,8 +104,7 @@ void device_pm_add(struct device *dev)
117void device_pm_remove(struct device *dev) 104void device_pm_remove(struct device *dev)
118{ 105{
119 pr_debug("PM: Removing info for %s:%s\n", 106 pr_debug("PM: Removing info for %s:%s\n",
120 dev->bus ? dev->bus->name : "No Bus", 107 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
121 kobject_name(&dev->kobj));
122 complete_all(&dev->power.completion); 108 complete_all(&dev->power.completion);
123 mutex_lock(&dpm_list_mtx); 109 mutex_lock(&dpm_list_mtx);
124 list_del_init(&dev->power.entry); 110 list_del_init(&dev->power.entry);
@@ -135,10 +121,8 @@ void device_pm_remove(struct device *dev)
135void device_pm_move_before(struct device *deva, struct device *devb) 121void device_pm_move_before(struct device *deva, struct device *devb)
136{ 122{
137 pr_debug("PM: Moving %s:%s before %s:%s\n", 123 pr_debug("PM: Moving %s:%s before %s:%s\n",
138 deva->bus ? deva->bus->name : "No Bus", 124 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
139 kobject_name(&deva->kobj), 125 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
140 devb->bus ? devb->bus->name : "No Bus",
141 kobject_name(&devb->kobj));
142 /* Delete deva from dpm_list and reinsert before devb. */ 126 /* Delete deva from dpm_list and reinsert before devb. */
143 list_move_tail(&deva->power.entry, &devb->power.entry); 127 list_move_tail(&deva->power.entry, &devb->power.entry);
144} 128}
@@ -151,10 +135,8 @@ void device_pm_move_before(struct device *deva, struct device *devb)
151void device_pm_move_after(struct device *deva, struct device *devb) 135void device_pm_move_after(struct device *deva, struct device *devb)
152{ 136{
153 pr_debug("PM: Moving %s:%s after %s:%s\n", 137 pr_debug("PM: Moving %s:%s after %s:%s\n",
154 deva->bus ? deva->bus->name : "No Bus", 138 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),
155 kobject_name(&deva->kobj), 139 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));
156 devb->bus ? devb->bus->name : "No Bus",
157 kobject_name(&devb->kobj));
158 /* Delete deva from dpm_list and reinsert after devb. */ 140 /* Delete deva from dpm_list and reinsert after devb. */
159 list_move(&deva->power.entry, &devb->power.entry); 141 list_move(&deva->power.entry, &devb->power.entry);
160} 142}
@@ -166,8 +148,7 @@ void device_pm_move_after(struct device *deva, struct device *devb)
166void device_pm_move_last(struct device *dev) 148void device_pm_move_last(struct device *dev)
167{ 149{
168 pr_debug("PM: Moving %s:%s to end of list\n", 150 pr_debug("PM: Moving %s:%s to end of list\n",
169 dev->bus ? dev->bus->name : "No Bus", 151 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));
170 kobject_name(&dev->kobj));
171 list_move_tail(&dev->power.entry, &dpm_list); 152 list_move_tail(&dev->power.entry, &dpm_list);
172} 153}
173 154
@@ -303,7 +284,7 @@ static int pm_noirq_op(struct device *dev,
303 pm_message_t state) 284 pm_message_t state)
304{ 285{
305 int error = 0; 286 int error = 0;
306 ktime_t calltime, delta, rettime; 287 ktime_t calltime = ktime_set(0, 0), delta, rettime;
307 288
308 if (initcall_debug) { 289 if (initcall_debug) {
309 pr_info("calling %s+ @ %i, parent: %s\n", 290 pr_info("calling %s+ @ %i, parent: %s\n",
@@ -405,7 +386,7 @@ static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
405 int error) 386 int error)
406{ 387{
407 printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n", 388 printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n",
408 kobject_name(&dev->kobj), pm_verb(state.event), info, error); 389 dev_name(dev), pm_verb(state.event), info, error);
409} 390}
410 391
411static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info) 392static void dpm_show_time(ktime_t starttime, pm_message_t state, char *info)
@@ -475,33 +456,24 @@ End:
475 */ 456 */
476void dpm_resume_noirq(pm_message_t state) 457void dpm_resume_noirq(pm_message_t state)
477{ 458{
478 struct list_head list;
479 ktime_t starttime = ktime_get(); 459 ktime_t starttime = ktime_get();
480 460
481 INIT_LIST_HEAD(&list);
482 mutex_lock(&dpm_list_mtx); 461 mutex_lock(&dpm_list_mtx);
483 transition_started = false; 462 while (!list_empty(&dpm_noirq_list)) {
484 while (!list_empty(&dpm_list)) { 463 struct device *dev = to_device(dpm_noirq_list.next);
485 struct device *dev = to_device(dpm_list.next); 464 int error;
486 465
487 get_device(dev); 466 get_device(dev);
488 if (dev->power.status > DPM_OFF) { 467 list_move_tail(&dev->power.entry, &dpm_suspended_list);
489 int error; 468 mutex_unlock(&dpm_list_mtx);
490
491 dev->power.status = DPM_OFF;
492 mutex_unlock(&dpm_list_mtx);
493 469
494 error = device_resume_noirq(dev, state); 470 error = device_resume_noirq(dev, state);
471 if (error)
472 pm_dev_err(dev, state, " early", error);
495 473
496 mutex_lock(&dpm_list_mtx); 474 mutex_lock(&dpm_list_mtx);
497 if (error)
498 pm_dev_err(dev, state, " early", error);
499 }
500 if (!list_empty(&dev->power.entry))
501 list_move_tail(&dev->power.entry, &list);
502 put_device(dev); 475 put_device(dev);
503 } 476 }
504 list_splice(&list, &dpm_list);
505 mutex_unlock(&dpm_list_mtx); 477 mutex_unlock(&dpm_list_mtx);
506 dpm_show_time(starttime, state, "early"); 478 dpm_show_time(starttime, state, "early");
507 resume_device_irqs(); 479 resume_device_irqs();
@@ -544,7 +516,7 @@ static int device_resume(struct device *dev, pm_message_t state, bool async)
544 dpm_wait(dev->parent, async); 516 dpm_wait(dev->parent, async);
545 device_lock(dev); 517 device_lock(dev);
546 518
547 dev->power.status = DPM_RESUMING; 519 dev->power.in_suspend = false;
548 520
549 if (dev->bus) { 521 if (dev->bus) {
550 if (dev->bus->pm) { 522 if (dev->bus->pm) {
@@ -610,19 +582,14 @@ static bool is_async(struct device *dev)
610 */ 582 */
611static void dpm_resume(pm_message_t state) 583static void dpm_resume(pm_message_t state)
612{ 584{
613 struct list_head list;
614 struct device *dev; 585 struct device *dev;
615 ktime_t starttime = ktime_get(); 586 ktime_t starttime = ktime_get();
616 587
617 INIT_LIST_HEAD(&list);
618 mutex_lock(&dpm_list_mtx); 588 mutex_lock(&dpm_list_mtx);
619 pm_transition = state; 589 pm_transition = state;
620 async_error = 0; 590 async_error = 0;
621 591
622 list_for_each_entry(dev, &dpm_list, power.entry) { 592 list_for_each_entry(dev, &dpm_suspended_list, power.entry) {
623 if (dev->power.status < DPM_OFF)
624 continue;
625
626 INIT_COMPLETION(dev->power.completion); 593 INIT_COMPLETION(dev->power.completion);
627 if (is_async(dev)) { 594 if (is_async(dev)) {
628 get_device(dev); 595 get_device(dev);
@@ -630,28 +597,24 @@ static void dpm_resume(pm_message_t state)
630 } 597 }
631 } 598 }
632 599
633 while (!list_empty(&dpm_list)) { 600 while (!list_empty(&dpm_suspended_list)) {
634 dev = to_device(dpm_list.next); 601 dev = to_device(dpm_suspended_list.next);
635 get_device(dev); 602 get_device(dev);
636 if (dev->power.status >= DPM_OFF && !is_async(dev)) { 603 if (!is_async(dev)) {
637 int error; 604 int error;
638 605
639 mutex_unlock(&dpm_list_mtx); 606 mutex_unlock(&dpm_list_mtx);
640 607
641 error = device_resume(dev, state, false); 608 error = device_resume(dev, state, false);
642
643 mutex_lock(&dpm_list_mtx);
644 if (error) 609 if (error)
645 pm_dev_err(dev, state, "", error); 610 pm_dev_err(dev, state, "", error);
646 } else if (dev->power.status == DPM_SUSPENDING) { 611
647 /* Allow new children of the device to be registered */ 612 mutex_lock(&dpm_list_mtx);
648 dev->power.status = DPM_RESUMING;
649 } 613 }
650 if (!list_empty(&dev->power.entry)) 614 if (!list_empty(&dev->power.entry))
651 list_move_tail(&dev->power.entry, &list); 615 list_move_tail(&dev->power.entry, &dpm_prepared_list);
652 put_device(dev); 616 put_device(dev);
653 } 617 }
654 list_splice(&list, &dpm_list);
655 mutex_unlock(&dpm_list_mtx); 618 mutex_unlock(&dpm_list_mtx);
656 async_synchronize_full(); 619 async_synchronize_full();
657 dpm_show_time(starttime, state, NULL); 620 dpm_show_time(starttime, state, NULL);
@@ -697,22 +660,18 @@ static void dpm_complete(pm_message_t state)
697 660
698 INIT_LIST_HEAD(&list); 661 INIT_LIST_HEAD(&list);
699 mutex_lock(&dpm_list_mtx); 662 mutex_lock(&dpm_list_mtx);
700 transition_started = false; 663 while (!list_empty(&dpm_prepared_list)) {
701 while (!list_empty(&dpm_list)) { 664 struct device *dev = to_device(dpm_prepared_list.prev);
702 struct device *dev = to_device(dpm_list.prev);
703 665
704 get_device(dev); 666 get_device(dev);
705 if (dev->power.status > DPM_ON) { 667 dev->power.in_suspend = false;
706 dev->power.status = DPM_ON; 668 list_move(&dev->power.entry, &list);
707 mutex_unlock(&dpm_list_mtx); 669 mutex_unlock(&dpm_list_mtx);
708 670
709 device_complete(dev, state); 671 device_complete(dev, state);
710 pm_runtime_put_sync(dev); 672 pm_runtime_put_sync(dev);
711 673
712 mutex_lock(&dpm_list_mtx); 674 mutex_lock(&dpm_list_mtx);
713 }
714 if (!list_empty(&dev->power.entry))
715 list_move(&dev->power.entry, &list);
716 put_device(dev); 675 put_device(dev);
717 } 676 }
718 list_splice(&list, &dpm_list); 677 list_splice(&list, &dpm_list);
@@ -802,15 +761,13 @@ End:
802 */ 761 */
803int dpm_suspend_noirq(pm_message_t state) 762int dpm_suspend_noirq(pm_message_t state)
804{ 763{
805 struct list_head list;
806 ktime_t starttime = ktime_get(); 764 ktime_t starttime = ktime_get();
807 int error = 0; 765 int error = 0;
808 766
809 INIT_LIST_HEAD(&list);
810 suspend_device_irqs(); 767 suspend_device_irqs();
811 mutex_lock(&dpm_list_mtx); 768 mutex_lock(&dpm_list_mtx);
812 while (!list_empty(&dpm_list)) { 769 while (!list_empty(&dpm_suspended_list)) {
813 struct device *dev = to_device(dpm_list.prev); 770 struct device *dev = to_device(dpm_suspended_list.prev);
814 771
815 get_device(dev); 772 get_device(dev);
816 mutex_unlock(&dpm_list_mtx); 773 mutex_unlock(&dpm_list_mtx);
@@ -823,12 +780,10 @@ int dpm_suspend_noirq(pm_message_t state)
823 put_device(dev); 780 put_device(dev);
824 break; 781 break;
825 } 782 }
826 dev->power.status = DPM_OFF_IRQ;
827 if (!list_empty(&dev->power.entry)) 783 if (!list_empty(&dev->power.entry))
828 list_move(&dev->power.entry, &list); 784 list_move(&dev->power.entry, &dpm_noirq_list);
829 put_device(dev); 785 put_device(dev);
830 } 786 }
831 list_splice_tail(&list, &dpm_list);
832 mutex_unlock(&dpm_list_mtx); 787 mutex_unlock(&dpm_list_mtx);
833 if (error) 788 if (error)
834 dpm_resume_noirq(resume_event(state)); 789 dpm_resume_noirq(resume_event(state));
@@ -876,6 +831,11 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
876 if (async_error) 831 if (async_error)
877 goto End; 832 goto End;
878 833
834 if (pm_wakeup_pending()) {
835 async_error = -EBUSY;
836 goto End;
837 }
838
879 if (dev->class) { 839 if (dev->class) {
880 if (dev->class->pm) { 840 if (dev->class->pm) {
881 pm_dev_dbg(dev, state, "class "); 841 pm_dev_dbg(dev, state, "class ");
@@ -907,9 +867,6 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async)
907 } 867 }
908 } 868 }
909 869
910 if (!error)
911 dev->power.status = DPM_OFF;
912
913 End: 870 End:
914 device_unlock(dev); 871 device_unlock(dev);
915 complete_all(&dev->power.completion); 872 complete_all(&dev->power.completion);
@@ -951,16 +908,14 @@ static int device_suspend(struct device *dev)
951 */ 908 */
952static int dpm_suspend(pm_message_t state) 909static int dpm_suspend(pm_message_t state)
953{ 910{
954 struct list_head list;
955 ktime_t starttime = ktime_get(); 911 ktime_t starttime = ktime_get();
956 int error = 0; 912 int error = 0;
957 913
958 INIT_LIST_HEAD(&list);
959 mutex_lock(&dpm_list_mtx); 914 mutex_lock(&dpm_list_mtx);
960 pm_transition = state; 915 pm_transition = state;
961 async_error = 0; 916 async_error = 0;
962 while (!list_empty(&dpm_list)) { 917 while (!list_empty(&dpm_prepared_list)) {
963 struct device *dev = to_device(dpm_list.prev); 918 struct device *dev = to_device(dpm_prepared_list.prev);
964 919
965 get_device(dev); 920 get_device(dev);
966 mutex_unlock(&dpm_list_mtx); 921 mutex_unlock(&dpm_list_mtx);
@@ -974,12 +929,11 @@ static int dpm_suspend(pm_message_t state)
974 break; 929 break;
975 } 930 }
976 if (!list_empty(&dev->power.entry)) 931 if (!list_empty(&dev->power.entry))
977 list_move(&dev->power.entry, &list); 932 list_move(&dev->power.entry, &dpm_suspended_list);
978 put_device(dev); 933 put_device(dev);
979 if (async_error) 934 if (async_error)
980 break; 935 break;
981 } 936 }
982 list_splice(&list, dpm_list.prev);
983 mutex_unlock(&dpm_list_mtx); 937 mutex_unlock(&dpm_list_mtx);
984 async_synchronize_full(); 938 async_synchronize_full();
985 if (!error) 939 if (!error)
@@ -1038,22 +992,20 @@ static int device_prepare(struct device *dev, pm_message_t state)
1038 */ 992 */
1039static int dpm_prepare(pm_message_t state) 993static int dpm_prepare(pm_message_t state)
1040{ 994{
1041 struct list_head list;
1042 int error = 0; 995 int error = 0;
1043 996
1044 INIT_LIST_HEAD(&list);
1045 mutex_lock(&dpm_list_mtx); 997 mutex_lock(&dpm_list_mtx);
1046 transition_started = true;
1047 while (!list_empty(&dpm_list)) { 998 while (!list_empty(&dpm_list)) {
1048 struct device *dev = to_device(dpm_list.next); 999 struct device *dev = to_device(dpm_list.next);
1049 1000
1050 get_device(dev); 1001 get_device(dev);
1051 dev->power.status = DPM_PREPARING;
1052 mutex_unlock(&dpm_list_mtx); 1002 mutex_unlock(&dpm_list_mtx);
1053 1003
1054 pm_runtime_get_noresume(dev); 1004 pm_runtime_get_noresume(dev);
1055 if (pm_runtime_barrier(dev) && device_may_wakeup(dev)) { 1005 if (pm_runtime_barrier(dev) && device_may_wakeup(dev))
1056 /* Wake-up requested during system sleep transition. */ 1006 pm_wakeup_event(dev, 0);
1007
1008 if (pm_wakeup_pending()) {
1057 pm_runtime_put_sync(dev); 1009 pm_runtime_put_sync(dev);
1058 error = -EBUSY; 1010 error = -EBUSY;
1059 } else { 1011 } else {
@@ -1062,24 +1014,22 @@ static int dpm_prepare(pm_message_t state)
1062 1014
1063 mutex_lock(&dpm_list_mtx); 1015 mutex_lock(&dpm_list_mtx);
1064 if (error) { 1016 if (error) {
1065 dev->power.status = DPM_ON;
1066 if (error == -EAGAIN) { 1017 if (error == -EAGAIN) {
1067 put_device(dev); 1018 put_device(dev);
1068 error = 0; 1019 error = 0;
1069 continue; 1020 continue;
1070 } 1021 }
1071 printk(KERN_ERR "PM: Failed to prepare device %s " 1022 printk(KERN_INFO "PM: Device %s not prepared "
1072 "for power transition: error %d\n", 1023 "for power transition: code %d\n",
1073 kobject_name(&dev->kobj), error); 1024 dev_name(dev), error);
1074 put_device(dev); 1025 put_device(dev);
1075 break; 1026 break;
1076 } 1027 }
1077 dev->power.status = DPM_SUSPENDING; 1028 dev->power.in_suspend = true;
1078 if (!list_empty(&dev->power.entry)) 1029 if (!list_empty(&dev->power.entry))
1079 list_move_tail(&dev->power.entry, &list); 1030 list_move_tail(&dev->power.entry, &dpm_prepared_list);
1080 put_device(dev); 1031 put_device(dev);
1081 } 1032 }
1082 list_splice(&list, &dpm_list);
1083 mutex_unlock(&dpm_list_mtx); 1033 mutex_unlock(&dpm_list_mtx);
1084 return error; 1034 return error;
1085} 1035}