Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /* |
2 | * drivers/base/power/main.c - Where the driver meets power management. | |
3 | * | |
4 | * Copyright (c) 2003 Patrick Mochel | |
5 | * Copyright (c) 2003 Open Source Development Lab | |
6 | * | |
7 | * This file is released under the GPLv2 | |
8 | * | |
9 | * | |
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 | |
12 | * and add it to the list of power-controlled devices. sysfs entries for | |
13 | * controlling device power management will also be added. | |
14 | * | |
15 | * A different set of lists than the global subsystem list are used to | |
16 | * keep track of power info because we use different lists to hold | |
17 | * devices based on what stage of the power management process they | |
18 | * are in. The power domain dependencies may also differ from the | |
19 | * ancestral dependencies that the subsystem list maintains. | |
20 | */ | |
21 | ||
1da177e4 | 22 | #include <linux/device.h> |
cd59abfc | 23 | #include <linux/kallsyms.h> |
11048dcf | 24 | #include <linux/mutex.h> |
cd59abfc AS |
25 | #include <linux/pm.h> |
26 | #include <linux/resume-trace.h> | |
11048dcf | 27 | |
cd59abfc | 28 | #include "../base.h" |
1da177e4 LT |
29 | #include "power.h" |
30 | ||
31 | LIST_HEAD(dpm_active); | |
cd59abfc AS |
32 | static LIST_HEAD(dpm_off); |
33 | static LIST_HEAD(dpm_off_irq); | |
1da177e4 | 34 | |
cd59abfc AS |
35 | static DEFINE_MUTEX(dpm_mtx); |
36 | static DEFINE_MUTEX(dpm_list_mtx); | |
1da177e4 | 37 | |
075c1771 DB |
38 | int (*platform_enable_wakeup)(struct device *dev, int is_on); |
39 | ||
cd59abfc | 40 | |
dec13c15 | 41 | void device_pm_add(struct device *dev) |
1da177e4 | 42 | { |
1da177e4 | 43 | pr_debug("PM: Adding info for %s:%s\n", |
c48ea603 DT |
44 | dev->bus ? dev->bus->name : "No Bus", |
45 | kobject_name(&dev->kobj)); | |
11048dcf | 46 | mutex_lock(&dpm_list_mtx); |
1da177e4 | 47 | list_add_tail(&dev->power.entry, &dpm_active); |
11048dcf | 48 | mutex_unlock(&dpm_list_mtx); |
1da177e4 LT |
49 | } |
50 | ||
9cddad77 | 51 | void device_pm_remove(struct device *dev) |
1da177e4 LT |
52 | { |
53 | pr_debug("PM: Removing info for %s:%s\n", | |
c48ea603 DT |
54 | dev->bus ? dev->bus->name : "No Bus", |
55 | kobject_name(&dev->kobj)); | |
11048dcf | 56 | mutex_lock(&dpm_list_mtx); |
1da177e4 | 57 | dpm_sysfs_remove(dev); |
1da177e4 | 58 | list_del_init(&dev->power.entry); |
11048dcf | 59 | mutex_unlock(&dpm_list_mtx); |
1da177e4 LT |
60 | } |
61 | ||
62 | ||
cd59abfc AS |
63 | /*------------------------- Resume routines -------------------------*/ |
64 | ||
65 | /** | |
66 | * resume_device - Restore state for one device. | |
67 | * @dev: Device. | |
68 | * | |
69 | */ | |
70 | ||
71 | static int resume_device(struct device * dev) | |
72 | { | |
73 | int error = 0; | |
74 | ||
75 | TRACE_DEVICE(dev); | |
76 | TRACE_RESUME(0); | |
77 | ||
78 | down(&dev->sem); | |
79 | ||
80 | if (dev->bus && dev->bus->resume) { | |
81 | dev_dbg(dev,"resuming\n"); | |
82 | error = dev->bus->resume(dev); | |
83 | } | |
84 | ||
85 | if (!error && dev->type && dev->type->resume) { | |
86 | dev_dbg(dev,"resuming\n"); | |
87 | error = dev->type->resume(dev); | |
88 | } | |
89 | ||
90 | if (!error && dev->class && dev->class->resume) { | |
91 | dev_dbg(dev,"class resume\n"); | |
92 | error = dev->class->resume(dev); | |
93 | } | |
94 | ||
95 | up(&dev->sem); | |
96 | ||
97 | TRACE_RESUME(error); | |
98 | return error; | |
99 | } | |
100 | ||
101 | ||
102 | static int resume_device_early(struct device * dev) | |
103 | { | |
104 | int error = 0; | |
105 | ||
106 | TRACE_DEVICE(dev); | |
107 | TRACE_RESUME(0); | |
108 | if (dev->bus && dev->bus->resume_early) { | |
109 | dev_dbg(dev,"EARLY resume\n"); | |
110 | error = dev->bus->resume_early(dev); | |
111 | } | |
112 | TRACE_RESUME(error); | |
113 | return error; | |
114 | } | |
115 | ||
116 | /* | |
117 | * Resume the devices that have either not gone through | |
118 | * the late suspend, or that did go through it but also | |
119 | * went through the early resume | |
120 | */ | |
121 | static void dpm_resume(void) | |
122 | { | |
123 | mutex_lock(&dpm_list_mtx); | |
124 | while(!list_empty(&dpm_off)) { | |
125 | struct list_head * entry = dpm_off.next; | |
126 | struct device * dev = to_device(entry); | |
127 | ||
128 | get_device(dev); | |
129 | list_move_tail(entry, &dpm_active); | |
130 | ||
131 | mutex_unlock(&dpm_list_mtx); | |
132 | resume_device(dev); | |
133 | mutex_lock(&dpm_list_mtx); | |
134 | put_device(dev); | |
135 | } | |
136 | mutex_unlock(&dpm_list_mtx); | |
137 | } | |
138 | ||
139 | ||
140 | /** | |
141 | * device_resume - Restore state of each device in system. | |
142 | * | |
143 | * Walk the dpm_off list, remove each entry, resume the device, | |
144 | * then add it to the dpm_active list. | |
145 | */ | |
146 | ||
147 | void device_resume(void) | |
148 | { | |
149 | might_sleep(); | |
150 | mutex_lock(&dpm_mtx); | |
151 | dpm_resume(); | |
152 | mutex_unlock(&dpm_mtx); | |
153 | } | |
154 | ||
155 | EXPORT_SYMBOL_GPL(device_resume); | |
156 | ||
157 | ||
158 | /** | |
159 | * dpm_power_up - Power on some devices. | |
160 | * | |
161 | * Walk the dpm_off_irq list and power each device up. This | |
162 | * is used for devices that required they be powered down with | |
163 | * interrupts disabled. As devices are powered on, they are moved | |
164 | * to the dpm_active list. | |
165 | * | |
166 | * Interrupts must be disabled when calling this. | |
167 | */ | |
168 | ||
169 | static void dpm_power_up(void) | |
170 | { | |
171 | while(!list_empty(&dpm_off_irq)) { | |
172 | struct list_head * entry = dpm_off_irq.next; | |
173 | struct device * dev = to_device(entry); | |
174 | ||
175 | list_move_tail(entry, &dpm_off); | |
176 | resume_device_early(dev); | |
177 | } | |
178 | } | |
179 | ||
180 | ||
181 | /** | |
182 | * device_power_up - Turn on all devices that need special attention. | |
183 | * | |
184 | * Power on system devices then devices that required we shut them down | |
185 | * with interrupts disabled. | |
186 | * Called with interrupts disabled. | |
187 | */ | |
188 | ||
189 | void device_power_up(void) | |
190 | { | |
191 | sysdev_resume(); | |
192 | dpm_power_up(); | |
193 | } | |
194 | ||
195 | EXPORT_SYMBOL_GPL(device_power_up); | |
196 | ||
197 | ||
198 | /*------------------------- Suspend routines -------------------------*/ | |
199 | ||
200 | /* | |
201 | * The entries in the dpm_active list are in a depth first order, simply | |
202 | * because children are guaranteed to be discovered after parents, and | |
203 | * are inserted at the back of the list on discovery. | |
204 | * | |
205 | * All list on the suspend path are done in reverse order, so we operate | |
206 | * on the leaves of the device tree (or forests, depending on how you want | |
207 | * to look at it ;) first. As nodes are removed from the back of the list, | |
208 | * they are inserted into the front of their destintation lists. | |
209 | * | |
210 | * Things are the reverse on the resume path - iterations are done in | |
211 | * forward order, and nodes are inserted at the back of their destination | |
212 | * lists. This way, the ancestors will be accessed before their descendents. | |
213 | */ | |
214 | ||
215 | static inline char *suspend_verb(u32 event) | |
216 | { | |
217 | switch (event) { | |
218 | case PM_EVENT_SUSPEND: return "suspend"; | |
219 | case PM_EVENT_FREEZE: return "freeze"; | |
220 | case PM_EVENT_PRETHAW: return "prethaw"; | |
221 | default: return "(unknown suspend event)"; | |
222 | } | |
223 | } | |
224 | ||
225 | ||
226 | static void | |
227 | suspend_device_dbg(struct device *dev, pm_message_t state, char *info) | |
228 | { | |
229 | dev_dbg(dev, "%s%s%s\n", info, suspend_verb(state.event), | |
230 | ((state.event == PM_EVENT_SUSPEND) && device_may_wakeup(dev)) ? | |
231 | ", may wakeup" : ""); | |
232 | } | |
233 | ||
234 | /** | |
235 | * suspend_device - Save state of one device. | |
236 | * @dev: Device. | |
237 | * @state: Power state device is entering. | |
238 | */ | |
239 | ||
240 | static int suspend_device(struct device * dev, pm_message_t state) | |
241 | { | |
242 | int error = 0; | |
243 | ||
244 | down(&dev->sem); | |
245 | if (dev->power.power_state.event) { | |
246 | dev_dbg(dev, "PM: suspend %d-->%d\n", | |
247 | dev->power.power_state.event, state.event); | |
248 | } | |
249 | ||
250 | if (dev->class && dev->class->suspend) { | |
251 | suspend_device_dbg(dev, state, "class "); | |
252 | error = dev->class->suspend(dev, state); | |
253 | suspend_report_result(dev->class->suspend, error); | |
254 | } | |
255 | ||
256 | if (!error && dev->type && dev->type->suspend) { | |
257 | suspend_device_dbg(dev, state, "type "); | |
258 | error = dev->type->suspend(dev, state); | |
259 | suspend_report_result(dev->type->suspend, error); | |
260 | } | |
261 | ||
262 | if (!error && dev->bus && dev->bus->suspend) { | |
263 | suspend_device_dbg(dev, state, ""); | |
264 | error = dev->bus->suspend(dev, state); | |
265 | suspend_report_result(dev->bus->suspend, error); | |
266 | } | |
267 | up(&dev->sem); | |
268 | return error; | |
269 | } | |
270 | ||
271 | ||
272 | /* | |
273 | * This is called with interrupts off, only a single CPU | |
274 | * running. We can't acquire a mutex or semaphore (and we don't | |
275 | * need the protection) | |
276 | */ | |
277 | static int suspend_device_late(struct device *dev, pm_message_t state) | |
278 | { | |
279 | int error = 0; | |
280 | ||
281 | if (dev->bus && dev->bus->suspend_late) { | |
282 | suspend_device_dbg(dev, state, "LATE "); | |
283 | error = dev->bus->suspend_late(dev, state); | |
284 | suspend_report_result(dev->bus->suspend_late, error); | |
285 | } | |
286 | return error; | |
287 | } | |
288 | ||
289 | /** | |
290 | * device_suspend - Save state and stop all devices in system. | |
291 | * @state: Power state to put each device in. | |
292 | * | |
293 | * Walk the dpm_active list, call ->suspend() for each device, and move | |
294 | * it to the dpm_off list. | |
295 | * | |
296 | * (For historical reasons, if it returns -EAGAIN, that used to mean | |
297 | * that the device would be called again with interrupts disabled. | |
298 | * These days, we use the "suspend_late()" callback for that, so we | |
299 | * print a warning and consider it an error). | |
300 | * | |
301 | * If we get a different error, try and back out. | |
302 | * | |
303 | * If we hit a failure with any of the devices, call device_resume() | |
304 | * above to bring the suspended devices back to life. | |
305 | * | |
306 | */ | |
307 | ||
308 | int device_suspend(pm_message_t state) | |
309 | { | |
310 | int error = 0; | |
311 | ||
312 | might_sleep(); | |
313 | mutex_lock(&dpm_mtx); | |
314 | mutex_lock(&dpm_list_mtx); | |
315 | while (!list_empty(&dpm_active) && error == 0) { | |
316 | struct list_head * entry = dpm_active.prev; | |
317 | struct device * dev = to_device(entry); | |
318 | ||
319 | get_device(dev); | |
320 | mutex_unlock(&dpm_list_mtx); | |
321 | ||
322 | error = suspend_device(dev, state); | |
323 | ||
324 | mutex_lock(&dpm_list_mtx); | |
325 | ||
326 | /* Check if the device got removed */ | |
327 | if (!list_empty(&dev->power.entry)) { | |
328 | /* Move it to the dpm_off list */ | |
329 | if (!error) | |
330 | list_move(&dev->power.entry, &dpm_off); | |
331 | } | |
332 | if (error) | |
333 | printk(KERN_ERR "Could not suspend device %s: " | |
334 | "error %d%s\n", | |
335 | kobject_name(&dev->kobj), error, | |
336 | error == -EAGAIN ? " (please convert to suspend_late)" : ""); | |
337 | put_device(dev); | |
338 | } | |
339 | mutex_unlock(&dpm_list_mtx); | |
340 | if (error) | |
341 | dpm_resume(); | |
342 | ||
343 | mutex_unlock(&dpm_mtx); | |
344 | return error; | |
345 | } | |
346 | ||
347 | EXPORT_SYMBOL_GPL(device_suspend); | |
348 | ||
349 | /** | |
350 | * device_power_down - Shut down special devices. | |
351 | * @state: Power state to enter. | |
352 | * | |
353 | * Walk the dpm_off_irq list, calling ->power_down() for each device that | |
354 | * couldn't power down the device with interrupts enabled. When we're | |
355 | * done, power down system devices. | |
356 | */ | |
357 | ||
358 | int device_power_down(pm_message_t state) | |
359 | { | |
360 | int error = 0; | |
361 | struct device * dev; | |
362 | ||
363 | while (!list_empty(&dpm_off)) { | |
364 | struct list_head * entry = dpm_off.prev; | |
365 | ||
366 | dev = to_device(entry); | |
367 | error = suspend_device_late(dev, state); | |
368 | if (error) | |
369 | goto Error; | |
370 | list_move(&dev->power.entry, &dpm_off_irq); | |
371 | } | |
372 | ||
373 | error = sysdev_suspend(state); | |
374 | Done: | |
375 | return error; | |
376 | Error: | |
377 | printk(KERN_ERR "Could not power down device %s: " | |
378 | "error %d\n", kobject_name(&dev->kobj), error); | |
379 | dpm_power_up(); | |
380 | goto Done; | |
381 | } | |
382 | ||
383 | EXPORT_SYMBOL_GPL(device_power_down); | |
384 | ||
385 | void __suspend_report_result(const char *function, void *fn, int ret) | |
386 | { | |
387 | if (ret) { | |
388 | printk(KERN_ERR "%s(): ", function); | |
389 | print_fn_descriptor_symbol("%s() returns ", (unsigned long)fn); | |
390 | printk("%d\n", ret); | |
391 | } | |
392 | } | |
393 | EXPORT_SYMBOL_GPL(__suspend_report_result); |