diff options
Diffstat (limited to 'drivers/base/power/suspend.c')
-rw-r--r-- | drivers/base/power/suspend.c | 210 |
1 files changed, 0 insertions, 210 deletions
diff --git a/drivers/base/power/suspend.c b/drivers/base/power/suspend.c deleted file mode 100644 index 26df9b231737..000000000000 --- a/drivers/base/power/suspend.c +++ /dev/null | |||
@@ -1,210 +0,0 @@ | |||
1 | /* | ||
2 | * suspend.c - Functions for putting devices to sleep. | ||
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/kallsyms.h> | ||
13 | #include <linux/pm.h> | ||
14 | #include "../base.h" | ||
15 | #include "power.h" | ||
16 | |||
17 | /* | ||
18 | * The entries in the dpm_active list are in a depth first order, simply | ||
19 | * because children are guaranteed to be discovered after parents, and | ||
20 | * are inserted at the back of the list on discovery. | ||
21 | * | ||
22 | * All list on the suspend path are done in reverse order, so we operate | ||
23 | * on the leaves of the device tree (or forests, depending on how you want | ||
24 | * to look at it ;) first. As nodes are removed from the back of the list, | ||
25 | * they are inserted into the front of their destintation lists. | ||
26 | * | ||
27 | * Things are the reverse on the resume path - iterations are done in | ||
28 | * forward order, and nodes are inserted at the back of their destination | ||
29 | * lists. This way, the ancestors will be accessed before their descendents. | ||
30 | */ | ||
31 | |||
32 | static inline char *suspend_verb(u32 event) | ||
33 | { | ||
34 | switch (event) { | ||
35 | case PM_EVENT_SUSPEND: return "suspend"; | ||
36 | case PM_EVENT_FREEZE: return "freeze"; | ||
37 | case PM_EVENT_PRETHAW: return "prethaw"; | ||
38 | default: return "(unknown suspend event)"; | ||
39 | } | ||
40 | } | ||
41 | |||
42 | |||
43 | static void | ||
44 | suspend_device_dbg(struct device *dev, pm_message_t state, char *info) | ||
45 | { | ||
46 | dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event), | ||
47 | ((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ? | ||
48 | ", may wakeup" : ""); | ||
49 | } | ||
50 | |||
51 | /** | ||
52 | * suspend_device - Save state of one device. | ||
53 | * @dev: Device. | ||
54 | * @state: Power state device is entering. | ||
55 | */ | ||
56 | |||
57 | int suspend_device(struct device * dev, pm_message_t state) | ||
58 | { | ||
59 | int error = 0; | ||
60 | |||
61 | down(&dev->sem); | ||
62 | if (dev->power.power_state.event) { | ||
63 | dev_dbg(dev, "PM: suspend %d-->%d\n", | ||
64 | dev->power.power_state.event, state.event); | ||
65 | } | ||
66 | |||
67 | if (dev->class && dev->class->suspend) { | ||
68 | suspend_device_dbg(dev, state, "class "); | ||
69 | error = dev->class->suspend(dev, state); | ||
70 | suspend_report_result(dev->class->suspend, error); | ||
71 | } | ||
72 | |||
73 | if (!error && dev->type && dev->type->suspend) { | ||
74 | suspend_device_dbg(dev, state, "type "); | ||
75 | error = dev->type->suspend(dev, state); | ||
76 | suspend_report_result(dev->type->suspend, error); | ||
77 | } | ||
78 | |||
79 | if (!error && dev->bus && dev->bus->suspend) { | ||
80 | suspend_device_dbg(dev, state, ""); | ||
81 | error = dev->bus->suspend(dev, state); | ||
82 | suspend_report_result(dev->bus->suspend, error); | ||
83 | } | ||
84 | up(&dev->sem); | ||
85 | return error; | ||
86 | } | ||
87 | |||
88 | |||
89 | /* | ||
90 | * This is called with interrupts off, only a single CPU | ||
91 | * running. We can't acquire a mutex or semaphore (and we don't | ||
92 | * need the protection) | ||
93 | */ | ||
94 | static int suspend_device_late(struct device *dev, pm_message_t state) | ||
95 | { | ||
96 | int error = 0; | ||
97 | |||
98 | if (dev->bus && dev->bus->suspend_late) { | ||
99 | suspend_device_dbg(dev, state, "LATE "); | ||
100 | error = dev->bus->suspend_late(dev, state); | ||
101 | suspend_report_result(dev->bus->suspend_late, error); | ||
102 | } | ||
103 | return error; | ||
104 | } | ||
105 | |||
106 | /** | ||
107 | * device_suspend - Save state and stop all devices in system. | ||
108 | * @state: Power state to put each device in. | ||
109 | * | ||
110 | * Walk the dpm_active list, call ->suspend() for each device, and move | ||
111 | * it to the dpm_off list. | ||
112 | * | ||
113 | * (For historical reasons, if it returns -EAGAIN, that used to mean | ||
114 | * that the device would be called again with interrupts disabled. | ||
115 | * These days, we use the "suspend_late()" callback for that, so we | ||
116 | * print a warning and consider it an error). | ||
117 | * | ||
118 | * If we get a different error, try and back out. | ||
119 | * | ||
120 | * If we hit a failure with any of the devices, call device_resume() | ||
121 | * above to bring the suspended devices back to life. | ||
122 | * | ||
123 | */ | ||
124 | |||
125 | int device_suspend(pm_message_t state) | ||
126 | { | ||
127 | int error = 0; | ||
128 | |||
129 | might_sleep(); | ||
130 | mutex_lock(&dpm_mtx); | ||
131 | mutex_lock(&dpm_list_mtx); | ||
132 | while (!list_empty(&dpm_active) && error == 0) { | ||
133 | struct list_head * entry = dpm_active.prev; | ||
134 | struct device * dev = to_device(entry); | ||
135 | |||
136 | get_device(dev); | ||
137 | mutex_unlock(&dpm_list_mtx); | ||
138 | |||
139 | error = suspend_device(dev, state); | ||
140 | |||
141 | mutex_lock(&dpm_list_mtx); | ||
142 | |||
143 | /* Check if the device got removed */ | ||
144 | if (!list_empty(&dev->power.entry)) { | ||
145 | /* Move it to the dpm_off list */ | ||
146 | if (!error) | ||
147 | list_move(&dev->power.entry, &dpm_off); | ||
148 | } | ||
149 | if (error) | ||
150 | printk(KERN_ERR "Could not suspend device %s: " | ||
151 | "error %d%s\n", | ||
152 | kobject_name(&dev->kobj), error, | ||
153 | error == -EAGAIN ? " (please convert to suspend_late)" : ""); | ||
154 | put_device(dev); | ||
155 | } | ||
156 | mutex_unlock(&dpm_list_mtx); | ||
157 | if (error) | ||
158 | dpm_resume(); | ||
159 | |||
160 | mutex_unlock(&dpm_mtx); | ||
161 | return error; | ||
162 | } | ||
163 | |||
164 | EXPORT_SYMBOL_GPL(device_suspend); | ||
165 | |||
166 | /** | ||
167 | * device_power_down - Shut down special devices. | ||
168 | * @state: Power state to enter. | ||
169 | * | ||
170 | * Walk the dpm_off_irq list, calling ->power_down() for each device that | ||
171 | * couldn't power down the device with interrupts enabled. When we're | ||
172 | * done, power down system devices. | ||
173 | */ | ||
174 | |||
175 | int device_power_down(pm_message_t state) | ||
176 | { | ||
177 | int error = 0; | ||
178 | struct device * dev; | ||
179 | |||
180 | while (!list_empty(&dpm_off)) { | ||
181 | struct list_head * entry = dpm_off.prev; | ||
182 | |||
183 | dev = to_device(entry); | ||
184 | error = suspend_device_late(dev, state); | ||
185 | if (error) | ||
186 | goto Error; | ||
187 | list_move(&dev->power.entry, &dpm_off_irq); | ||
188 | } | ||
189 | |||
190 | error = sysdev_suspend(state); | ||
191 | Done: | ||
192 | return error; | ||
193 | Error: | ||
194 | printk(KERN_ERR "Could not power down device %s: " | ||
195 | "error %d\n", kobject_name(&dev->kobj), error); | ||
196 | dpm_power_up(); | ||
197 | goto Done; | ||
198 | } | ||
199 | |||
200 | EXPORT_SYMBOL_GPL(device_power_down); | ||
201 | |||
202 | void __suspend_report_result(const char *function, void *fn, int ret) | ||
203 | { | ||
204 | if (ret) { | ||
205 | printk(KERN_ERR "%s(): ", function); | ||
206 | print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn); | ||
207 | printk("%d\n", ret); | ||
208 | } | ||
209 | } | ||
210 | EXPORT_SYMBOL_GPL(__suspend_report_result); | ||