]> err.no Git - linux-2.6/blob - drivers/base/power/resume.c
Merge branch 'master' of ssh://master.kernel.org/pub/scm/linux/kernel/git/mchehab...
[linux-2.6] / drivers / base / power / resume.c
1 /*
2  * resume.c - Functions for waking devices up.
3  *
4  * Copyright (c) 2003 Patrick Mochel
5  * Copyright (c) 2003 Open Source Development Labs
6  *
7  * This file is released under the GPLv2
8  *
9  */
10
11 #include <linux/device.h>
12 #include <linux/resume-trace.h>
13 #include "../base.h"
14 #include "power.h"
15
16
17 /**
18  *      resume_device - Restore state for one device.
19  *      @dev:   Device.
20  *
21  */
22
23 int resume_device(struct device * dev)
24 {
25         int error = 0;
26
27         TRACE_DEVICE(dev);
28         TRACE_RESUME(0);
29
30         down(&dev->sem);
31
32         if (dev->power.pm_parent
33                         && dev->power.pm_parent->power.power_state.event) {
34                 dev_err(dev, "PM: resume from %d, parent %s still %d\n",
35                         dev->power.power_state.event,
36                         dev->power.pm_parent->bus_id,
37                         dev->power.pm_parent->power.power_state.event);
38         }
39
40         if (dev->bus && dev->bus->resume) {
41                 dev_dbg(dev,"resuming\n");
42                 error = dev->bus->resume(dev);
43         }
44
45         if (!error && dev->type && dev->type->resume) {
46                 dev_dbg(dev,"resuming\n");
47                 error = dev->type->resume(dev);
48         }
49
50         if (!error && dev->class && dev->class->resume) {
51                 dev_dbg(dev,"class resume\n");
52                 error = dev->class->resume(dev);
53         }
54
55         up(&dev->sem);
56
57         TRACE_RESUME(error);
58         return error;
59 }
60
61
62 static int resume_device_early(struct device * dev)
63 {
64         int error = 0;
65
66         TRACE_DEVICE(dev);
67         TRACE_RESUME(0);
68         if (dev->bus && dev->bus->resume_early) {
69                 dev_dbg(dev,"EARLY resume\n");
70                 error = dev->bus->resume_early(dev);
71         }
72         TRACE_RESUME(error);
73         return error;
74 }
75
76 /*
77  * Resume the devices that have either not gone through
78  * the late suspend, or that did go through it but also
79  * went through the early resume
80  */
81 void dpm_resume(void)
82 {
83         down(&dpm_list_sem);
84         while(!list_empty(&dpm_off)) {
85                 struct list_head * entry = dpm_off.next;
86                 struct device * dev = to_device(entry);
87
88                 get_device(dev);
89                 list_move_tail(entry, &dpm_active);
90
91                 up(&dpm_list_sem);
92                 if (!dev->power.prev_state.event)
93                         resume_device(dev);
94                 down(&dpm_list_sem);
95                 put_device(dev);
96         }
97         up(&dpm_list_sem);
98 }
99
100
101 /**
102  *      device_resume - Restore state of each device in system.
103  *
104  *      Walk the dpm_off list, remove each entry, resume the device,
105  *      then add it to the dpm_active list.
106  */
107
108 void device_resume(void)
109 {
110         might_sleep();
111         down(&dpm_sem);
112         dpm_resume();
113         up(&dpm_sem);
114 }
115
116 EXPORT_SYMBOL_GPL(device_resume);
117
118
119 /**
120  *      dpm_power_up - Power on some devices.
121  *
122  *      Walk the dpm_off_irq list and power each device up. This
123  *      is used for devices that required they be powered down with
124  *      interrupts disabled. As devices are powered on, they are moved
125  *      to the dpm_active list.
126  *
127  *      Interrupts must be disabled when calling this.
128  */
129
130 void dpm_power_up(void)
131 {
132         while(!list_empty(&dpm_off_irq)) {
133                 struct list_head * entry = dpm_off_irq.next;
134                 struct device * dev = to_device(entry);
135
136                 list_move_tail(entry, &dpm_off);
137                 resume_device_early(dev);
138         }
139 }
140
141
142 /**
143  *      device_power_up - Turn on all devices that need special attention.
144  *
145  *      Power on system devices then devices that required we shut them down
146  *      with interrupts disabled.
147  *      Called with interrupts disabled.
148  */
149
150 void device_power_up(void)
151 {
152         sysdev_resume();
153         dpm_power_up();
154 }
155
156 EXPORT_SYMBOL_GPL(device_power_up);
157
158