aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/base
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2008-07-18 06:20:23 -0400
committerIngo Molnar <mingo@elte.hu>2008-07-18 06:20:23 -0400
commitcd569ef5d6ff9f43e9504f1ffc7fdbe356518149 (patch)
tree9a4ab5e600fd09e991aa1fbb69adb1c7950898a4 /drivers/base
parent6879827f4e08da219c99b91e4e1d793a924103e3 (diff)
parent5b664cb235e97afbf34db9c4d77f08ebd725335e (diff)
Merge branch 'linus' into x86/urgent
Diffstat (limited to 'drivers/base')
-rw-r--r--drivers/base/platform.c296
-rw-r--r--drivers/base/power/main.c675
-rw-r--r--drivers/base/power/power.h2
-rw-r--r--drivers/base/power/sysfs.c3
-rw-r--r--drivers/base/power/trace.c4
5 files changed, 814 insertions, 166 deletions
diff --git a/drivers/base/platform.c b/drivers/base/platform.c
index 911ec600fe71..3f940393d6c7 100644
--- a/drivers/base/platform.c
+++ b/drivers/base/platform.c
@@ -453,6 +453,8 @@ int platform_driver_register(struct platform_driver *drv)
453 drv->driver.suspend = platform_drv_suspend; 453 drv->driver.suspend = platform_drv_suspend;
454 if (drv->resume) 454 if (drv->resume)
455 drv->driver.resume = platform_drv_resume; 455 drv->driver.resume = platform_drv_resume;
456 if (drv->pm)
457 drv->driver.pm = &drv->pm->base;
456 return driver_register(&drv->driver); 458 return driver_register(&drv->driver);
457} 459}
458EXPORT_SYMBOL_GPL(platform_driver_register); 460EXPORT_SYMBOL_GPL(platform_driver_register);
@@ -560,7 +562,9 @@ static int platform_match(struct device *dev, struct device_driver *drv)
560 return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0); 562 return (strncmp(pdev->name, drv->name, BUS_ID_SIZE) == 0);
561} 563}
562 564
563static int platform_suspend(struct device *dev, pm_message_t mesg) 565#ifdef CONFIG_PM_SLEEP
566
567static int platform_legacy_suspend(struct device *dev, pm_message_t mesg)
564{ 568{
565 int ret = 0; 569 int ret = 0;
566 570
@@ -570,7 +574,7 @@ static int platform_suspend(struct device *dev, pm_message_t mesg)
570 return ret; 574 return ret;
571} 575}
572 576
573static int platform_suspend_late(struct device *dev, pm_message_t mesg) 577static int platform_legacy_suspend_late(struct device *dev, pm_message_t mesg)
574{ 578{
575 struct platform_driver *drv = to_platform_driver(dev->driver); 579 struct platform_driver *drv = to_platform_driver(dev->driver);
576 struct platform_device *pdev; 580 struct platform_device *pdev;
@@ -583,7 +587,7 @@ static int platform_suspend_late(struct device *dev, pm_message_t mesg)
583 return ret; 587 return ret;
584} 588}
585 589
586static int platform_resume_early(struct device *dev) 590static int platform_legacy_resume_early(struct device *dev)
587{ 591{
588 struct platform_driver *drv = to_platform_driver(dev->driver); 592 struct platform_driver *drv = to_platform_driver(dev->driver);
589 struct platform_device *pdev; 593 struct platform_device *pdev;
@@ -596,7 +600,7 @@ static int platform_resume_early(struct device *dev)
596 return ret; 600 return ret;
597} 601}
598 602
599static int platform_resume(struct device *dev) 603static int platform_legacy_resume(struct device *dev)
600{ 604{
601 int ret = 0; 605 int ret = 0;
602 606
@@ -606,15 +610,291 @@ static int platform_resume(struct device *dev)
606 return ret; 610 return ret;
607} 611}
608 612
613static int platform_pm_prepare(struct device *dev)
614{
615 struct device_driver *drv = dev->driver;
616 int ret = 0;
617
618 if (drv && drv->pm && drv->pm->prepare)
619 ret = drv->pm->prepare(dev);
620
621 return ret;
622}
623
624static void platform_pm_complete(struct device *dev)
625{
626 struct device_driver *drv = dev->driver;
627
628 if (drv && drv->pm && drv->pm->complete)
629 drv->pm->complete(dev);
630}
631
632#ifdef CONFIG_SUSPEND
633
634static int platform_pm_suspend(struct device *dev)
635{
636 struct device_driver *drv = dev->driver;
637 int ret = 0;
638
639 if (drv && drv->pm) {
640 if (drv->pm->suspend)
641 ret = drv->pm->suspend(dev);
642 } else {
643 ret = platform_legacy_suspend(dev, PMSG_SUSPEND);
644 }
645
646 return ret;
647}
648
649static int platform_pm_suspend_noirq(struct device *dev)
650{
651 struct platform_driver *pdrv;
652 int ret = 0;
653
654 if (!dev->driver)
655 return 0;
656
657 pdrv = to_platform_driver(dev->driver);
658 if (pdrv->pm) {
659 if (pdrv->pm->suspend_noirq)
660 ret = pdrv->pm->suspend_noirq(dev);
661 } else {
662 ret = platform_legacy_suspend_late(dev, PMSG_SUSPEND);
663 }
664
665 return ret;
666}
667
668static int platform_pm_resume(struct device *dev)
669{
670 struct device_driver *drv = dev->driver;
671 int ret = 0;
672
673 if (drv && drv->pm) {
674 if (drv->pm->resume)
675 ret = drv->pm->resume(dev);
676 } else {
677 ret = platform_legacy_resume(dev);
678 }
679
680 return ret;
681}
682
683static int platform_pm_resume_noirq(struct device *dev)
684{
685 struct platform_driver *pdrv;
686 int ret = 0;
687
688 if (!dev->driver)
689 return 0;
690
691 pdrv = to_platform_driver(dev->driver);
692 if (pdrv->pm) {
693 if (pdrv->pm->resume_noirq)
694 ret = pdrv->pm->resume_noirq(dev);
695 } else {
696 ret = platform_legacy_resume_early(dev);
697 }
698
699 return ret;
700}
701
702#else /* !CONFIG_SUSPEND */
703
704#define platform_pm_suspend NULL
705#define platform_pm_resume NULL
706#define platform_pm_suspend_noirq NULL
707#define platform_pm_resume_noirq NULL
708
709#endif /* !CONFIG_SUSPEND */
710
711#ifdef CONFIG_HIBERNATION
712
713static int platform_pm_freeze(struct device *dev)
714{
715 struct device_driver *drv = dev->driver;
716 int ret = 0;
717
718 if (!drv)
719 return 0;
720
721 if (drv->pm) {
722 if (drv->pm->freeze)
723 ret = drv->pm->freeze(dev);
724 } else {
725 ret = platform_legacy_suspend(dev, PMSG_FREEZE);
726 }
727
728 return ret;
729}
730
731static int platform_pm_freeze_noirq(struct device *dev)
732{
733 struct platform_driver *pdrv;
734 int ret = 0;
735
736 if (!dev->driver)
737 return 0;
738
739 pdrv = to_platform_driver(dev->driver);
740 if (pdrv->pm) {
741 if (pdrv->pm->freeze_noirq)
742 ret = pdrv->pm->freeze_noirq(dev);
743 } else {
744 ret = platform_legacy_suspend_late(dev, PMSG_FREEZE);
745 }
746
747 return ret;
748}
749
750static int platform_pm_thaw(struct device *dev)
751{
752 struct device_driver *drv = dev->driver;
753 int ret = 0;
754
755 if (drv && drv->pm) {
756 if (drv->pm->thaw)
757 ret = drv->pm->thaw(dev);
758 } else {
759 ret = platform_legacy_resume(dev);
760 }
761
762 return ret;
763}
764
765static int platform_pm_thaw_noirq(struct device *dev)
766{
767 struct platform_driver *pdrv;
768 int ret = 0;
769
770 if (!dev->driver)
771 return 0;
772
773 pdrv = to_platform_driver(dev->driver);
774 if (pdrv->pm) {
775 if (pdrv->pm->thaw_noirq)
776 ret = pdrv->pm->thaw_noirq(dev);
777 } else {
778 ret = platform_legacy_resume_early(dev);
779 }
780
781 return ret;
782}
783
784static int platform_pm_poweroff(struct device *dev)
785{
786 struct device_driver *drv = dev->driver;
787 int ret = 0;
788
789 if (drv && drv->pm) {
790 if (drv->pm->poweroff)
791 ret = drv->pm->poweroff(dev);
792 } else {
793 ret = platform_legacy_suspend(dev, PMSG_HIBERNATE);
794 }
795
796 return ret;
797}
798
799static int platform_pm_poweroff_noirq(struct device *dev)
800{
801 struct platform_driver *pdrv;
802 int ret = 0;
803
804 if (!dev->driver)
805 return 0;
806
807 pdrv = to_platform_driver(dev->driver);
808 if (pdrv->pm) {
809 if (pdrv->pm->poweroff_noirq)
810 ret = pdrv->pm->poweroff_noirq(dev);
811 } else {
812 ret = platform_legacy_suspend_late(dev, PMSG_HIBERNATE);
813 }
814
815 return ret;
816}
817
818static int platform_pm_restore(struct device *dev)
819{
820 struct device_driver *drv = dev->driver;
821 int ret = 0;
822
823 if (drv && drv->pm) {
824 if (drv->pm->restore)
825 ret = drv->pm->restore(dev);
826 } else {
827 ret = platform_legacy_resume(dev);
828 }
829
830 return ret;
831}
832
833static int platform_pm_restore_noirq(struct device *dev)
834{
835 struct platform_driver *pdrv;
836 int ret = 0;
837
838 if (!dev->driver)
839 return 0;
840
841 pdrv = to_platform_driver(dev->driver);
842 if (pdrv->pm) {
843 if (pdrv->pm->restore_noirq)
844 ret = pdrv->pm->restore_noirq(dev);
845 } else {
846 ret = platform_legacy_resume_early(dev);
847 }
848
849 return ret;
850}
851
852#else /* !CONFIG_HIBERNATION */
853
854#define platform_pm_freeze NULL
855#define platform_pm_thaw NULL
856#define platform_pm_poweroff NULL
857#define platform_pm_restore NULL
858#define platform_pm_freeze_noirq NULL
859#define platform_pm_thaw_noirq NULL
860#define platform_pm_poweroff_noirq NULL
861#define platform_pm_restore_noirq NULL
862
863#endif /* !CONFIG_HIBERNATION */
864
865struct pm_ext_ops platform_pm_ops = {
866 .base = {
867 .prepare = platform_pm_prepare,
868 .complete = platform_pm_complete,
869 .suspend = platform_pm_suspend,
870 .resume = platform_pm_resume,
871 .freeze = platform_pm_freeze,
872 .thaw = platform_pm_thaw,
873 .poweroff = platform_pm_poweroff,
874 .restore = platform_pm_restore,
875 },
876 .suspend_noirq = platform_pm_suspend_noirq,
877 .resume_noirq = platform_pm_resume_noirq,
878 .freeze_noirq = platform_pm_freeze_noirq,
879 .thaw_noirq = platform_pm_thaw_noirq,
880 .poweroff_noirq = platform_pm_poweroff_noirq,
881 .restore_noirq = platform_pm_restore_noirq,
882};
883
884#define PLATFORM_PM_OPS_PTR &platform_pm_ops
885
886#else /* !CONFIG_PM_SLEEP */
887
888#define PLATFORM_PM_OPS_PTR NULL
889
890#endif /* !CONFIG_PM_SLEEP */
891
609struct bus_type platform_bus_type = { 892struct bus_type platform_bus_type = {
610 .name = "platform", 893 .name = "platform",
611 .dev_attrs = platform_dev_attrs, 894 .dev_attrs = platform_dev_attrs,
612 .match = platform_match, 895 .match = platform_match,
613 .uevent = platform_uevent, 896 .uevent = platform_uevent,
614 .suspend = platform_suspend, 897 .pm = PLATFORM_PM_OPS_PTR,
615 .suspend_late = platform_suspend_late,
616 .resume_early = platform_resume_early,
617 .resume = platform_resume,
618}; 898};
619EXPORT_SYMBOL_GPL(platform_bus_type); 899EXPORT_SYMBOL_GPL(platform_bus_type);
620 900
diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c
index 45cc3d9eacb8..3250c5257b74 100644
--- a/drivers/base/power/main.c
+++ b/drivers/base/power/main.c
@@ -12,11 +12,9 @@
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 *
15 * A different set of lists than the global subsystem list are used to 15 * A separate list is used for keeping track of power info, because the power
16 * keep track of power info because we use different lists to hold 16 * domain dependencies may differ from the ancestral dependencies that the
17 * devices based on what stage of the power management process they 17 * subsystem list maintains.
18 * are in. The power domain dependencies may also differ from the
19 * ancestral dependencies that the subsystem list maintains.
20 */ 18 */
21 19
22#include <linux/device.h> 20#include <linux/device.h>
@@ -30,31 +28,40 @@
30#include "power.h" 28#include "power.h"
31 29
32/* 30/*
33 * The entries in the dpm_active list are in a depth first order, simply 31 * The entries in the dpm_list list are in a depth first order, simply
34 * because children are guaranteed to be discovered after parents, and 32 * because children are guaranteed to be discovered after parents, and
35 * are inserted at the back of the list on discovery. 33 * are inserted at the back of the list on discovery.
36 * 34 *
37 * All the other lists are kept in the same order, for consistency.
38 * However the lists aren't always traversed in the same order.
39 * Semaphores must be acquired from the top (i.e., front) down
40 * and released in the opposite order. Devices must be suspended
41 * from the bottom (i.e., end) up and resumed in the opposite order.
42 * That way no parent will be suspended while it still has an active
43 * child.
44 *
45 * Since device_pm_add() may be called with a device semaphore held, 35 * Since device_pm_add() may be called with a device semaphore held,
46 * we must never try to acquire a device semaphore while holding 36 * we must never try to acquire a device semaphore while holding
47 * dpm_list_mutex. 37 * dpm_list_mutex.
48 */ 38 */
49 39
50LIST_HEAD(dpm_active); 40LIST_HEAD(dpm_list);
51static LIST_HEAD(dpm_off);
52static LIST_HEAD(dpm_off_irq);
53 41
54static DEFINE_MUTEX(dpm_list_mtx); 42static DEFINE_MUTEX(dpm_list_mtx);
55 43
56/* 'true' if all devices have been suspended, protected by dpm_list_mtx */ 44/*
57static bool all_sleeping; 45 * Set once the preparation of devices for a PM transition has started, reset
46 * before starting to resume devices. Protected by dpm_list_mtx.
47 */
48static bool transition_started;
49
50/**
51 * device_pm_lock - lock the list of active devices used by the PM core
52 */
53void device_pm_lock(void)
54{
55 mutex_lock(&dpm_list_mtx);
56}
57
58/**
59 * device_pm_unlock - unlock the list of active devices used by the PM core
60 */
61void device_pm_unlock(void)
62{
63 mutex_unlock(&dpm_list_mtx);
64}
58 65
59/** 66/**
60 * device_pm_add - add a device to the list of active devices 67 * device_pm_add - add a device to the list of active devices
@@ -68,17 +75,25 @@ int device_pm_add(struct device *dev)
68 dev->bus ? dev->bus->name : "No Bus", 75 dev->bus ? dev->bus->name : "No Bus",
69 kobject_name(&dev->kobj)); 76 kobject_name(&dev->kobj));
70 mutex_lock(&dpm_list_mtx); 77 mutex_lock(&dpm_list_mtx);
71 if ((dev->parent && dev->parent->power.sleeping) || all_sleeping) { 78 if (dev->parent) {
72 if (dev->parent->power.sleeping) 79 if (dev->parent->power.status >= DPM_SUSPENDING) {
73 dev_warn(dev, "parent %s is sleeping\n", 80 dev_warn(dev, "parent %s is sleeping, will not add\n",
74 dev->parent->bus_id); 81 dev->parent->bus_id);
75 else 82 WARN_ON(true);
76 dev_warn(dev, "all devices are sleeping\n"); 83 }
84 } else if (transition_started) {
85 /*
86 * We refuse to register parentless devices while a PM
87 * transition is in progress in order to avoid leaving them
88 * unhandled down the road
89 */
77 WARN_ON(true); 90 WARN_ON(true);
78 } 91 }
79 error = dpm_sysfs_add(dev); 92 error = dpm_sysfs_add(dev);
80 if (!error) 93 if (!error) {
81 list_add_tail(&dev->power.entry, &dpm_active); 94 dev->power.status = DPM_ON;
95 list_add_tail(&dev->power.entry, &dpm_list);
96 }
82 mutex_unlock(&dpm_list_mtx); 97 mutex_unlock(&dpm_list_mtx);
83 return error; 98 return error;
84} 99}
@@ -100,73 +115,243 @@ void device_pm_remove(struct device *dev)
100 mutex_unlock(&dpm_list_mtx); 115 mutex_unlock(&dpm_list_mtx);
101} 116}
102 117
118/**
119 * pm_op - execute the PM operation appropiate for given PM event
120 * @dev: Device.
121 * @ops: PM operations to choose from.
122 * @state: PM transition of the system being carried out.
123 */
124static int pm_op(struct device *dev, struct pm_ops *ops, pm_message_t state)
125{
126 int error = 0;
127
128 switch (state.event) {
129#ifdef CONFIG_SUSPEND
130 case PM_EVENT_SUSPEND:
131 if (ops->suspend) {
132 error = ops->suspend(dev);
133 suspend_report_result(ops->suspend, error);
134 }
135 break;
136 case PM_EVENT_RESUME:
137 if (ops->resume) {
138 error = ops->resume(dev);
139 suspend_report_result(ops->resume, error);
140 }
141 break;
142#endif /* CONFIG_SUSPEND */
143#ifdef CONFIG_HIBERNATION
144 case PM_EVENT_FREEZE:
145 case PM_EVENT_QUIESCE:
146 if (ops->freeze) {
147 error = ops->freeze(dev);
148 suspend_report_result(ops->freeze, error);
149 }
150 break;
151 case PM_EVENT_HIBERNATE:
152 if (ops->poweroff) {
153 error = ops->poweroff(dev);
154 suspend_report_result(ops->poweroff, error);
155 }
156 break;
157 case PM_EVENT_THAW:
158 case PM_EVENT_RECOVER:
159 if (ops->thaw) {
160 error = ops->thaw(dev);
161 suspend_report_result(ops->thaw, error);
162 }
163 break;
164 case PM_EVENT_RESTORE:
165 if (ops->restore) {
166 error = ops->restore(dev);
167 suspend_report_result(ops->restore, error);
168 }
169 break;
170#endif /* CONFIG_HIBERNATION */
171 default:
172 error = -EINVAL;
173 }
174 return error;
175}
176
177/**
178 * pm_noirq_op - execute the PM operation appropiate for given PM event
179 * @dev: Device.
180 * @ops: PM operations to choose from.
181 * @state: PM transition of the system being carried out.
182 *
183 * The operation is executed with interrupts disabled by the only remaining
184 * functional CPU in the system.
185 */
186static int pm_noirq_op(struct device *dev, struct pm_ext_ops *ops,
187 pm_message_t state)
188{
189 int error = 0;
190
191 switch (state.event) {
192#ifdef CONFIG_SUSPEND
193 case PM_EVENT_SUSPEND:
194 if (ops->suspend_noirq) {
195 error = ops->suspend_noirq(dev);
196 suspend_report_result(ops->suspend_noirq, error);
197 }
198 break;
199 case PM_EVENT_RESUME:
200 if (ops->resume_noirq) {
201 error = ops->resume_noirq(dev);
202 suspend_report_result(ops->resume_noirq, error);
203 }
204 break;
205#endif /* CONFIG_SUSPEND */
206#ifdef CONFIG_HIBERNATION
207 case PM_EVENT_FREEZE:
208 case PM_EVENT_QUIESCE:
209 if (ops->freeze_noirq) {
210 error = ops->freeze_noirq(dev);
211 suspend_report_result(ops->freeze_noirq, error);
212 }
213 break;
214 case PM_EVENT_HIBERNATE:
215 if (ops->poweroff_noirq) {
216 error = ops->poweroff_noirq(dev);
217 suspend_report_result(ops->poweroff_noirq, error);
218 }
219 break;
220 case PM_EVENT_THAW:
221 case PM_EVENT_RECOVER:
222 if (ops->thaw_noirq) {
223 error = ops->thaw_noirq(dev);
224 suspend_report_result(ops->thaw_noirq, error);
225 }
226 break;
227 case PM_EVENT_RESTORE:
228 if (ops->restore_noirq) {
229 error = ops->restore_noirq(dev);
230 suspend_report_result(ops->restore_noirq, error);
231 }
232 break;
233#endif /* CONFIG_HIBERNATION */
234 default:
235 error = -EINVAL;
236 }
237 return error;
238}
239
240static char *pm_verb(int event)
241{
242 switch (event) {
243 case PM_EVENT_SUSPEND:
244 return "suspend";
245 case PM_EVENT_RESUME:
246 return "resume";
247 case PM_EVENT_FREEZE:
248 return "freeze";
249 case PM_EVENT_QUIESCE:
250 return "quiesce";
251 case PM_EVENT_HIBERNATE:
252 return "hibernate";
253 case PM_EVENT_THAW:
254 return "thaw";
255 case PM_EVENT_RESTORE:
256 return "restore";
257 case PM_EVENT_RECOVER:
258 return "recover";
259 default:
260 return "(unknown PM event)";
261 }
262}
263
264static void pm_dev_dbg(struct device *dev, pm_message_t state, char *info)
265{
266 dev_dbg(dev, "%s%s%s\n", info, pm_verb(state.event),
267 ((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ?
268 ", may wakeup" : "");
269}
270
271static void pm_dev_err(struct device *dev, pm_message_t state, char *info,
272 int error)
273{
274 printk(KERN_ERR "PM: Device %s failed to %s%s: error %d\n",
275 kobject_name(&dev->kobj), pm_verb(state.event), info, error);
276}
277
103/*------------------------- Resume routines -------------------------*/ 278/*------------------------- Resume routines -------------------------*/
104 279
105/** 280/**
106 * resume_device_early - Power on one device (early resume). 281 * resume_device_noirq - Power on one device (early resume).
107 * @dev: Device. 282 * @dev: Device.
283 * @state: PM transition of the system being carried out.
108 * 284 *
109 * Must be called with interrupts disabled. 285 * Must be called with interrupts disabled.
110 */ 286 */
111static int resume_device_early(struct device *dev) 287static int resume_device_noirq(struct device *dev, pm_message_t state)
112{ 288{
113 int error = 0; 289 int error = 0;
114 290
115 TRACE_DEVICE(dev); 291 TRACE_DEVICE(dev);
116 TRACE_RESUME(0); 292 TRACE_RESUME(0);
117 293
118 if (dev->bus && dev->bus->resume_early) { 294 if (!dev->bus)
119 dev_dbg(dev, "EARLY resume\n"); 295 goto End;
296
297 if (dev->bus->pm) {
298 pm_dev_dbg(dev, state, "EARLY ");
299 error = pm_noirq_op(dev, dev->bus->pm, state);
300 } else if (dev->bus->resume_early) {
301 pm_dev_dbg(dev, state, "legacy EARLY ");
120 error = dev->bus->resume_early(dev); 302 error = dev->bus->resume_early(dev);
121 } 303 }
122 304 End:
123 TRACE_RESUME(error); 305 TRACE_RESUME(error);
124 return error; 306 return error;
125} 307}
126 308
127/** 309/**
128 * dpm_power_up - Power on all regular (non-sysdev) devices. 310 * dpm_power_up - Power on all regular (non-sysdev) devices.
311 * @state: PM transition of the system being carried out.
129 * 312 *
130 * Walk the dpm_off_irq list and power each device up. This 313 * Execute the appropriate "noirq resume" callback for all devices marked
131 * is used for devices that required they be powered down with 314 * as DPM_OFF_IRQ.
132 * interrupts disabled. As devices are powered on, they are moved
133 * to the dpm_off list.
134 * 315 *
135 * Must be called with interrupts disabled and only one CPU running. 316 * Must be called with interrupts disabled and only one CPU running.
136 */ 317 */
137static void dpm_power_up(void) 318static void dpm_power_up(pm_message_t state)
138{ 319{
320 struct device *dev;
139 321
140 while (!list_empty(&dpm_off_irq)) { 322 list_for_each_entry(dev, &dpm_list, power.entry)
141 struct list_head *entry = dpm_off_irq.next; 323 if (dev->power.status > DPM_OFF) {
142 struct device *dev = to_device(entry); 324 int error;
143 325
144 list_move_tail(entry, &dpm_off); 326 dev->power.status = DPM_OFF;
145 resume_device_early(dev); 327 error = resume_device_noirq(dev, state);
146 } 328 if (error)
329 pm_dev_err(dev, state, " early", error);
330 }
147} 331}
148 332
149/** 333/**
150 * device_power_up - Turn on all devices that need special attention. 334 * device_power_up - Turn on all devices that need special attention.
335 * @state: PM transition of the system being carried out.
151 * 336 *
152 * Power on system devices, then devices that required we shut them down 337 * Power on system devices, then devices that required we shut them down
153 * with interrupts disabled. 338 * with interrupts disabled.
154 * 339 *
155 * Must be called with interrupts disabled. 340 * Must be called with interrupts disabled.
156 */ 341 */
157void device_power_up(void) 342void device_power_up(pm_message_t state)
158{ 343{
159 sysdev_resume(); 344 sysdev_resume();
160 dpm_power_up(); 345 dpm_power_up(state);
161} 346}
162EXPORT_SYMBOL_GPL(device_power_up); 347EXPORT_SYMBOL_GPL(device_power_up);
163 348
164/** 349/**
165 * resume_device - Restore state for one device. 350 * resume_device - Restore state for one device.
166 * @dev: Device. 351 * @dev: Device.
167 * 352 * @state: PM transition of the system being carried out.
168 */ 353 */
169static int resume_device(struct device *dev) 354static int resume_device(struct device *dev, pm_message_t state)
170{ 355{
171 int error = 0; 356 int error = 0;
172 357
@@ -175,21 +360,40 @@ static int resume_device(struct device *dev)
175 360
176 down(&dev->sem); 361 down(&dev->sem);
177 362
178 if (dev->bus && dev->bus->resume) { 363 if (dev->bus) {
179 dev_dbg(dev,"resuming\n"); 364 if (dev->bus->pm) {
180 error = dev->bus->resume(dev); 365 pm_dev_dbg(dev, state, "");
366 error = pm_op(dev, &dev->bus->pm->base, state);
367 } else if (dev->bus->resume) {
368 pm_dev_dbg(dev, state, "legacy ");
369 error = dev->bus->resume(dev);
370 }
371 if (error)
372 goto End;
181 } 373 }
182 374
183 if (!error && dev->type && dev->type->resume) { 375 if (dev->type) {
184 dev_dbg(dev,"resuming\n"); 376 if (dev->type->pm) {
185 error = dev->type->resume(dev); 377 pm_dev_dbg(dev, state, "type ");
378 error = pm_op(dev, dev->type->pm, state);
379 } else if (dev->type->resume) {
380 pm_dev_dbg(dev, state, "legacy type ");
381 error = dev->type->resume(dev);
382 }
383 if (error)
384 goto End;
186 } 385 }
187 386
188 if (!error && dev->class && dev->class->resume) { 387 if (dev->class) {
189 dev_dbg(dev,"class resume\n"); 388 if (dev->class->pm) {
190 error = dev->class->resume(dev); 389 pm_dev_dbg(dev, state, "class ");
390 error = pm_op(dev, dev->class->pm, state);
391 } else if (dev->class->resume) {
392 pm_dev_dbg(dev, state, "legacy class ");
393 error = dev->class->resume(dev);
394 }
191 } 395 }
192 396 End:
193 up(&dev->sem); 397 up(&dev->sem);
194 398
195 TRACE_RESUME(error); 399 TRACE_RESUME(error);
@@ -198,78 +402,161 @@ static int resume_device(struct device *dev)
198 402
199/** 403/**
200 * dpm_resume - Resume every device. 404 * dpm_resume - Resume every device.
405 * @state: PM transition of the system being carried out.
201 * 406 *
202 * Resume the devices that have either not gone through 407 * Execute the appropriate "resume" callback for all devices the status of
203 * the late suspend, or that did go through it but also 408 * which indicates that they are inactive.
204 * went through the early resume. 409 */
410static void dpm_resume(pm_message_t state)
411{
412 struct list_head list;
413
414 INIT_LIST_HEAD(&list);
415 mutex_lock(&dpm_list_mtx);
416 transition_started = false;
417 while (!list_empty(&dpm_list)) {
418 struct device *dev = to_device(dpm_list.next);
419
420 get_device(dev);
421 if (dev->power.status >= DPM_OFF) {
422 int error;
423
424 dev->power.status = DPM_RESUMING;
425 mutex_unlock(&dpm_list_mtx);
426
427 error = resume_device(dev, state);
428
429 mutex_lock(&dpm_list_mtx);
430 if (error)
431 pm_dev_err(dev, state, "", error);
432 } else if (dev->power.status == DPM_SUSPENDING) {
433 /* Allow new children of the device to be registered */
434 dev->power.status = DPM_RESUMING;
435 }
436 if (!list_empty(&dev->power.entry))
437 list_move_tail(&dev->power.entry, &list);
438 put_device(dev);
439 }
440 list_splice(&list, &dpm_list);
441 mutex_unlock(&dpm_list_mtx);
442}
443
444/**
445 * complete_device - Complete a PM transition for given device
446 * @dev: Device.
447 * @state: PM transition of the system being carried out.
448 */
449static void complete_device(struct device *dev, pm_message_t state)
450{
451 down(&dev->sem);
452
453 if (dev->class && dev->class->pm && dev->class->pm->complete) {
454 pm_dev_dbg(dev, state, "completing class ");
455 dev->class->pm->complete(dev);
456 }
457
458 if (dev->type && dev->type->pm && dev->type->pm->complete) {
459 pm_dev_dbg(dev, state, "completing type ");
460 dev->type->pm->complete(dev);
461 }
462
463 if (dev->bus && dev->bus->pm && dev->bus->pm->base.complete) {
464 pm_dev_dbg(dev, state, "completing ");
465 dev->bus->pm->base.complete(dev);
466 }
467
468 up(&dev->sem);
469}
470
471/**
472 * dpm_complete - Complete a PM transition for all devices.
473 * @state: PM transition of the system being carried out.
205 * 474 *
206 * Take devices from the dpm_off_list, resume them, 475 * Execute the ->complete() callbacks for all devices that are not marked
207 * and put them on the dpm_locked list. 476 * as DPM_ON.
208 */ 477 */
209static void dpm_resume(void) 478static void dpm_complete(pm_message_t state)
210{ 479{
480 struct list_head list;
481
482 INIT_LIST_HEAD(&list);
211 mutex_lock(&dpm_list_mtx); 483 mutex_lock(&dpm_list_mtx);
212 all_sleeping = false; 484 while (!list_empty(&dpm_list)) {
213 while(!list_empty(&dpm_off)) { 485 struct device *dev = to_device(dpm_list.prev);
214 struct list_head *entry = dpm_off.next;
215 struct device *dev = to_device(entry);
216 486
217 list_move_tail(entry, &dpm_active); 487 get_device(dev);
218 dev->power.sleeping = false; 488 if (dev->power.status > DPM_ON) {
219 mutex_unlock(&dpm_list_mtx); 489 dev->power.status = DPM_ON;
220 resume_device(dev); 490 mutex_unlock(&dpm_list_mtx);
221 mutex_lock(&dpm_list_mtx); 491
492 complete_device(dev, state);
493
494 mutex_lock(&dpm_list_mtx);
495 }
496 if (!list_empty(&dev->power.entry))
497 list_move(&dev->power.entry, &list);
498 put_device(dev);
222 } 499 }
500 list_splice(&list, &dpm_list);
223 mutex_unlock(&dpm_list_mtx); 501 mutex_unlock(&dpm_list_mtx);
224} 502}
225 503
226/** 504/**
227 * device_resume - Restore state of each device in system. 505 * device_resume - Restore state of each device in system.
506 * @state: PM transition of the system being carried out.
228 * 507 *
229 * Resume all the devices, unlock them all, and allow new 508 * Resume all the devices, unlock them all, and allow new
230 * devices to be registered once again. 509 * devices to be registered once again.
231 */ 510 */
232void device_resume(void) 511void device_resume(pm_message_t state)
233{ 512{
234 might_sleep(); 513 might_sleep();
235 dpm_resume(); 514 dpm_resume(state);
515 dpm_complete(state);
236} 516}
237EXPORT_SYMBOL_GPL(device_resume); 517EXPORT_SYMBOL_GPL(device_resume);
238 518
239 519
240/*------------------------- Suspend routines -------------------------*/ 520/*------------------------- Suspend routines -------------------------*/
241 521
242static inline char *suspend_verb(u32 event) 522/**
523 * resume_event - return a PM message representing the resume event
524 * corresponding to given sleep state.
525 * @sleep_state: PM message representing a sleep state.
526 */
527static pm_message_t resume_event(pm_message_t sleep_state)
243{ 528{
244 switch (event) { 529 switch (sleep_state.event) {
245 case PM_EVENT_SUSPEND: return "suspend"; 530 case PM_EVENT_SUSPEND:
246 case PM_EVENT_FREEZE: return "freeze"; 531 return PMSG_RESUME;
247 case PM_EVENT_PRETHAW: return "prethaw"; 532 case PM_EVENT_FREEZE:
248 default: return "(unknown suspend event)"; 533 case PM_EVENT_QUIESCE:
534 return PMSG_RECOVER;
535 case PM_EVENT_HIBERNATE:
536 return PMSG_RESTORE;
249 } 537 }
250} 538 return PMSG_ON;
251
252static void
253suspend_device_dbg(struct device *dev, pm_message_t state, char *info)
254{
255 dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event),
256 ((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ?
257 ", may wakeup" : "");
258} 539}
259 540
260/** 541/**
261 * suspend_device_late - Shut down one device (late suspend). 542 * suspend_device_noirq - Shut down one device (late suspend).
262 * @dev: Device. 543 * @dev: Device.
263 * @state: Power state device is entering. 544 * @state: PM transition of the system being carried out.
264 * 545 *
265 * This is called with interrupts off and only a single CPU running. 546 * This is called with interrupts off and only a single CPU running.
266 */ 547 */
267static int suspend_device_late(struct device *dev, pm_message_t state) 548static int suspend_device_noirq(struct device *dev, pm_message_t state)
268{ 549{
269 int error = 0; 550 int error = 0;
270 551
271 if (dev->bus && dev->bus->suspend_late) { 552 if (!dev->bus)
272 suspend_device_dbg(dev, state, "LATE "); 553 return 0;
554
555 if (dev->bus->pm) {
556 pm_dev_dbg(dev, state, "LATE ");
557 error = pm_noirq_op(dev, dev->bus->pm, state);
558 } else if (dev->bus->suspend_late) {
559 pm_dev_dbg(dev, state, "legacy LATE ");
273 error = dev->bus->suspend_late(dev, state); 560 error = dev->bus->suspend_late(dev, state);
274 suspend_report_result(dev->bus->suspend_late, error); 561 suspend_report_result(dev->bus->suspend_late, error);
275 } 562 }
@@ -278,37 +565,30 @@ static int suspend_device_late(struct device *dev, pm_message_t state)
278 565
279/** 566/**
280 * device_power_down - Shut down special devices. 567 * device_power_down - Shut down special devices.
281 * @state: Power state to enter. 568 * @state: PM transition of the system being carried out.
282 * 569 *
283 * Power down devices that require interrupts to be disabled 570 * Power down devices that require interrupts to be disabled.
284 * and move them from the dpm_off list to the dpm_off_irq list.
285 * Then power down system devices. 571 * Then power down system devices.
286 * 572 *
287 * Must be called with interrupts disabled and only one CPU running. 573 * Must be called with interrupts disabled and only one CPU running.
288 */ 574 */
289int device_power_down(pm_message_t state) 575int device_power_down(pm_message_t state)
290{ 576{
577 struct device *dev;
291 int error = 0; 578 int error = 0;
292 579
293 while (!list_empty(&dpm_off)) { 580 list_for_each_entry_reverse(dev, &dpm_list, power.entry) {
294 struct list_head *entry = dpm_off.prev; 581 error = suspend_device_noirq(dev, state);
295 struct device *dev = to_device(entry);
296
297 error = suspend_device_late(dev, state);
298 if (error) { 582 if (error) {
299 printk(KERN_ERR "Could not power down device %s: " 583 pm_dev_err(dev, state, " late", error);
300 "error %d\n",
301 kobject_name(&dev->kobj), error);
302 break; 584 break;
303 } 585 }
304 if (!list_empty(&dev->power.entry)) 586 dev->power.status = DPM_OFF_IRQ;
305 list_move(&dev->power.entry, &dpm_off_irq);
306 } 587 }
307
308 if (!error) 588 if (!error)
309 error = sysdev_suspend(state); 589 error = sysdev_suspend(state);
310 if (error) 590 if (error)
311 dpm_power_up(); 591 dpm_power_up(resume_event(state));
312 return error; 592 return error;
313} 593}
314EXPORT_SYMBOL_GPL(device_power_down); 594EXPORT_SYMBOL_GPL(device_power_down);
@@ -316,7 +596,7 @@ EXPORT_SYMBOL_GPL(device_power_down);
316/** 596/**
317 * suspend_device - Save state of one device. 597 * suspend_device - Save state of one device.
318 * @dev: Device. 598 * @dev: Device.
319 * @state: Power state device is entering. 599 * @state: PM transition of the system being carried out.
320 */ 600 */
321static int suspend_device(struct device *dev, pm_message_t state) 601static int suspend_device(struct device *dev, pm_message_t state)
322{ 602{
@@ -324,24 +604,43 @@ static int suspend_device(struct device *dev, pm_message_t state)
324 604
325 down(&dev->sem); 605 down(&dev->sem);
326 606
327 if (dev->class && dev->class->suspend) { 607 if (dev->class) {
328 suspend_device_dbg(dev, state, "class "); 608 if (dev->class->pm) {
329 error = dev->class->suspend(dev, state); 609 pm_dev_dbg(dev, state, "class ");
330 suspend_report_result(dev->class->suspend, error); 610 error = pm_op(dev, dev->class->pm, state);
611 } else if (dev->class->suspend) {
612 pm_dev_dbg(dev, state, "legacy class ");
613 error = dev->class->suspend(dev, state);
614 suspend_report_result(dev->class->suspend, error);
615 }
616 if (error)
617 goto End;
331 } 618 }
332 619
333 if (!error && dev->type && dev->type->suspend) { 620 if (dev->type) {
334 suspend_device_dbg(dev, state, "type "); 621 if (dev->type->pm) {
335 error = dev->type->suspend(dev, state); 622 pm_dev_dbg(dev, state, "type ");
336 suspend_report_result(dev->type->suspend, error); 623 error = pm_op(dev, dev->type->pm, state);
624 } else if (dev->type->suspend) {
625 pm_dev_dbg(dev, state, "legacy type ");
626 error = dev->type->suspend(dev, state);
627 suspend_report_result(dev->type->suspend, error);
628 }
629 if (error)
630 goto End;
337 } 631 }
338 632
339 if (!error && dev->bus && dev->bus->suspend) { 633 if (dev->bus) {
340 suspend_device_dbg(dev, state, ""); 634 if (dev->bus->pm) {
341 error = dev->bus->suspend(dev, state); 635 pm_dev_dbg(dev, state, "");
342 suspend_report_result(dev->bus->suspend, error); 636 error = pm_op(dev, &dev->bus->pm->base, state);
637 } else if (dev->bus->suspend) {
638 pm_dev_dbg(dev, state, "legacy ");
639 error = dev->bus->suspend(dev, state);
640 suspend_report_result(dev->bus->suspend, error);
641 }
343 } 642 }
344 643 End:
345 up(&dev->sem); 644 up(&dev->sem);
346 645
347 return error; 646 return error;
@@ -349,67 +648,139 @@ static int suspend_device(struct device *dev, pm_message_t state)
349 648
350/** 649/**
351 * dpm_suspend - Suspend every device. 650 * dpm_suspend - Suspend every device.
352 * @state: Power state to put each device in. 651 * @state: PM transition of the system being carried out.
353 *
354 * Walk the dpm_locked list. Suspend each device and move it
355 * to the dpm_off list.
356 * 652 *
357 * (For historical reasons, if it returns -EAGAIN, that used to mean 653 * Execute the appropriate "suspend" callbacks for all devices.
358 * that the device would be called again with interrupts disabled.
359 * These days, we use the "suspend_late()" callback for that, so we
360 * print a warning and consider it an error).
361 */ 654 */
362static int dpm_suspend(pm_message_t state) 655static int dpm_suspend(pm_message_t state)
363{ 656{
657 struct list_head list;
364 int error = 0; 658 int error = 0;
365 659
660 INIT_LIST_HEAD(&list);
366 mutex_lock(&dpm_list_mtx); 661 mutex_lock(&dpm_list_mtx);
367 while (!list_empty(&dpm_active)) { 662 while (!list_empty(&dpm_list)) {
368 struct list_head *entry = dpm_active.prev; 663 struct device *dev = to_device(dpm_list.prev);
369 struct device *dev = to_device(entry);
370 664
371 WARN_ON(dev->parent && dev->parent->power.sleeping); 665 get_device(dev);
372
373 dev->power.sleeping = true;
374 mutex_unlock(&dpm_list_mtx); 666 mutex_unlock(&dpm_list_mtx);
667
375 error = suspend_device(dev, state); 668 error = suspend_device(dev, state);
669
376 mutex_lock(&dpm_list_mtx); 670 mutex_lock(&dpm_list_mtx);
377 if (error) { 671 if (error) {
378 printk(KERN_ERR "Could not suspend device %s: " 672 pm_dev_err(dev, state, "", error);
379 "error %d%s\n", 673 put_device(dev);
380 kobject_name(&dev->kobj),
381 error,
382 (error == -EAGAIN ?
383 " (please convert to suspend_late)" :
384 ""));
385 dev->power.sleeping = false;
386 break; 674 break;
387 } 675 }
676 dev->power.status = DPM_OFF;
388 if (!list_empty(&dev->power.entry)) 677 if (!list_empty(&dev->power.entry))
389 list_move(&dev->power.entry, &dpm_off); 678 list_move(&dev->power.entry, &list);
679 put_device(dev);
390 } 680 }
391 if (!error) 681 list_splice(&list, dpm_list.prev);
392 all_sleeping = true;
393 mutex_unlock(&dpm_list_mtx); 682 mutex_unlock(&dpm_list_mtx);
683 return error;
684}
685
686/**
687 * prepare_device - Execute the ->prepare() callback(s) for given device.
688 * @dev: Device.
689 * @state: PM transition of the system being carried out.
690 */
691static int prepare_device(struct device *dev, pm_message_t state)
692{
693 int error = 0;
694
695 down(&dev->sem);
696
697 if (dev->bus && dev->bus->pm && dev->bus->pm->base.prepare) {
698 pm_dev_dbg(dev, state, "preparing ");
699 error = dev->bus->pm->base.prepare(dev);
700 suspend_report_result(dev->bus->pm->base.prepare, error);
701 if (error)
702 goto End;
703 }
704
705 if (dev->type && dev->type->pm && dev->type->pm->prepare) {
706 pm_dev_dbg(dev, state, "preparing type ");
707 error = dev->type->pm->prepare(dev);
708 suspend_report_result(dev->type->pm->prepare, error);
709 if (error)
710 goto End;
711 }
712
713 if (dev->class && dev->class->pm && dev->class->pm->prepare) {
714 pm_dev_dbg(dev, state, "preparing class ");
715 error = dev->class->pm->prepare(dev);
716 suspend_report_result(dev->class->pm->prepare, error);
717 }
718 End:
719 up(&dev->sem);
720
721 return error;
722}
723
724/**
725 * dpm_prepare - Prepare all devices for a PM transition.
726 * @state: PM transition of the system being carried out.
727 *
728 * Execute the ->prepare() callback for all devices.
729 */
730static int dpm_prepare(pm_message_t state)
731{
732 struct list_head list;
733 int error = 0;
734
735 INIT_LIST_HEAD(&list);
736 mutex_lock(&dpm_list_mtx);
737 transition_started = true;
738 while (!list_empty(&dpm_list)) {
739 struct device *dev = to_device(dpm_list.next);
740
741 get_device(dev);
742 dev->power.status = DPM_PREPARING;
743 mutex_unlock(&dpm_list_mtx);
394 744
745 error = prepare_device(dev, state);
746
747 mutex_lock(&dpm_list_mtx);
748 if (error) {
749 dev->power.status = DPM_ON;
750 if (error == -EAGAIN) {
751 put_device(dev);
752 continue;
753 }
754 printk(KERN_ERR "PM: Failed to prepare device %s "
755 "for power transition: error %d\n",
756 kobject_name(&dev->kobj), error);
757 put_device(dev);
758 break;
759 }
760 dev->power.status = DPM_SUSPENDING;
761 if (!list_empty(&dev->power.entry))
762 list_move_tail(&dev->power.entry, &list);
763 put_device(dev);
764 }
765 list_splice(&list, &dpm_list);
766 mutex_unlock(&dpm_list_mtx);
395 return error; 767 return error;
396} 768}
397 769
398/** 770/**
399 * device_suspend - Save state and stop all devices in system. 771 * device_suspend - Save state and stop all devices in system.
400 * @state: new power management state 772 * @state: PM transition of the system being carried out.
401 * 773 *
402 * Prevent new devices from being registered, then lock all devices 774 * Prepare and suspend all devices.
403 * and suspend them.
404 */ 775 */
405int device_suspend(pm_message_t state) 776int device_suspend(pm_message_t state)
406{ 777{
407 int error; 778 int error;
408 779
409 might_sleep(); 780 might_sleep();
410 error = dpm_suspend(state); 781 error = dpm_prepare(state);
411 if (error) 782 if (!error)
412 device_resume(); 783 error = dpm_suspend(state);
413 return error; 784 return error;
414} 785}
415EXPORT_SYMBOL_GPL(device_suspend); 786EXPORT_SYMBOL_GPL(device_suspend);
diff --git a/drivers/base/power/power.h b/drivers/base/power/power.h
index a6894f2a4b99..a3252c0e2887 100644
--- a/drivers/base/power/power.h
+++ b/drivers/base/power/power.h
@@ -4,7 +4,7 @@
4 * main.c 4 * main.c
5 */ 5 */
6 6
7extern struct list_head dpm_active; /* The active device list */ 7extern struct list_head dpm_list; /* The active device list */
8 8
9static inline struct device *to_device(struct list_head *entry) 9static inline struct device *to_device(struct list_head *entry)
10{ 10{
diff --git a/drivers/base/power/sysfs.c b/drivers/base/power/sysfs.c
index d11f74b038db..596aeecfdffe 100644
--- a/drivers/base/power/sysfs.c
+++ b/drivers/base/power/sysfs.c
@@ -6,9 +6,6 @@
6#include <linux/string.h> 6#include <linux/string.h>
7#include "power.h" 7#include "power.h"
8 8
9int (*platform_enable_wakeup)(struct device *dev, int is_on);
10
11
12/* 9/*
13 * wakeup - Report/change current wakeup option for device 10 * wakeup - Report/change current wakeup option for device
14 * 11 *
diff --git a/drivers/base/power/trace.c b/drivers/base/power/trace.c
index 87a7f1d02578..9b1b20b59e0a 100644
--- a/drivers/base/power/trace.c
+++ b/drivers/base/power/trace.c
@@ -188,9 +188,9 @@ static int show_file_hash(unsigned int value)
188static int show_dev_hash(unsigned int value) 188static int show_dev_hash(unsigned int value)
189{ 189{
190 int match = 0; 190 int match = 0;
191 struct list_head * entry = dpm_active.prev; 191 struct list_head *entry = dpm_list.prev;
192 192
193 while (entry != &dpm_active) { 193 while (entry != &dpm_list) {
194 struct device * dev = to_device(entry); 194 struct device * dev = to_device(entry);
195 unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH); 195 unsigned int hash = hash_string(DEVSEED, dev->bus_id, DEVHASH);
196 if (hash == value) { 196 if (hash == value) {