diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 23:03:54 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-09-14 23:03:54 -0400 |
| commit | f86054c24565d09d1997f03192761dabf6b8a9c9 (patch) | |
| tree | 64a48fd9d03b39932c768ea28eb8edf6cecbeaf1 /include | |
| parent | c91d7d54ea9e75ec18c733969ba16dd7ab94fc99 (diff) | |
| parent | 33f82d141c897f39cd8bce592d88cb3c5af58342 (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: (23 commits)
at_hdmac: Rework suspend_late()/resume_early()
PM: Reset transition_started at dpm_resume_noirq
PM: Update kerneldoc comments in drivers/base/power/main.c
PM: Add convenience macro to make switching to dev_pm_ops less error-prone
hp-wmi: Switch driver to dev_pm_ops
floppy: Switch driver to dev_pm_ops
PM: Trivial fixes
PM / Hibernate / Memory hotplug: Always use for_each_populated_zone()
PM/Hibernate: Do not try to allocate too much memory too hard (rev. 2)
PM/Hibernate: Do not release preallocated memory unnecessarily (rev. 2)
PM/Hibernate: Rework shrinking of memory
PM: Fix typo in label name s/Platofrm_finish/Platform_finish/
PM: Run-time PM platform device bus support
PM: Introduce core framework for run-time PM of I/O devices (rev. 17)
Driver Core: Make PM operations a const pointer
PM: Remove platform device suspend_late()/resume_early() V2
USB: Rework musb suspend()/resume_early()
I2C: Rework i2c-s3c2410 suspend_late()/resume() V2
I2C: Rework i2c-pxa suspend_late()/resume_early()
DMA: Rework txx9dmac suspend_late()/resume_early()
...
Fix trivial conflict in drivers/base/platform.c (due to same
constification patch being merged in both sides, along with some other
PM work in the PM branch)
Diffstat (limited to 'include')
| -rw-r--r-- | include/asm-generic/device.h | 3 | ||||
| -rw-r--r-- | include/linux/platform_device.h | 5 | ||||
| -rw-r--r-- | include/linux/pm.h | 115 | ||||
| -rw-r--r-- | include/linux/pm_runtime.h | 114 |
4 files changed, 232 insertions, 5 deletions
diff --git a/include/asm-generic/device.h b/include/asm-generic/device.h index c17c9600f220..d7c76bba640d 100644 --- a/include/asm-generic/device.h +++ b/include/asm-generic/device.h | |||
| @@ -9,4 +9,7 @@ | |||
| 9 | struct dev_archdata { | 9 | struct dev_archdata { |
| 10 | }; | 10 | }; |
| 11 | 11 | ||
| 12 | struct pdev_archdata { | ||
| 13 | }; | ||
| 14 | |||
| 12 | #endif /* _ASM_GENERIC_DEVICE_H */ | 15 | #endif /* _ASM_GENERIC_DEVICE_H */ |
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 8dc5123b6305..3c6675c2444b 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h | |||
| @@ -22,6 +22,9 @@ struct platform_device { | |||
| 22 | struct resource * resource; | 22 | struct resource * resource; |
| 23 | 23 | ||
| 24 | struct platform_device_id *id_entry; | 24 | struct platform_device_id *id_entry; |
| 25 | |||
| 26 | /* arch specific additions */ | ||
| 27 | struct pdev_archdata archdata; | ||
| 25 | }; | 28 | }; |
| 26 | 29 | ||
| 27 | #define platform_get_device_id(pdev) ((pdev)->id_entry) | 30 | #define platform_get_device_id(pdev) ((pdev)->id_entry) |
| @@ -57,8 +60,6 @@ struct platform_driver { | |||
| 57 | int (*remove)(struct platform_device *); | 60 | int (*remove)(struct platform_device *); |
| 58 | void (*shutdown)(struct platform_device *); | 61 | void (*shutdown)(struct platform_device *); |
| 59 | int (*suspend)(struct platform_device *, pm_message_t state); | 62 | int (*suspend)(struct platform_device *, pm_message_t state); |
| 60 | int (*suspend_late)(struct platform_device *, pm_message_t state); | ||
| 61 | int (*resume_early)(struct platform_device *); | ||
| 62 | int (*resume)(struct platform_device *); | 63 | int (*resume)(struct platform_device *); |
| 63 | struct device_driver driver; | 64 | struct device_driver driver; |
| 64 | struct platform_device_id *id_table; | 65 | struct platform_device_id *id_table; |
diff --git a/include/linux/pm.h b/include/linux/pm.h index b3f74764a586..3b7e04b95bd2 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h | |||
| @@ -22,6 +22,10 @@ | |||
| 22 | #define _LINUX_PM_H | 22 | #define _LINUX_PM_H |
| 23 | 23 | ||
| 24 | #include <linux/list.h> | 24 | #include <linux/list.h> |
| 25 | #include <linux/workqueue.h> | ||
| 26 | #include <linux/spinlock.h> | ||
| 27 | #include <linux/wait.h> | ||
| 28 | #include <linux/timer.h> | ||
| 25 | 29 | ||
| 26 | /* | 30 | /* |
| 27 | * Callbacks for platform drivers to implement. | 31 | * Callbacks for platform drivers to implement. |
| @@ -165,6 +169,28 @@ typedef struct pm_message { | |||
| 165 | * It is allowed to unregister devices while the above callbacks are being | 169 | * It is allowed to unregister devices while the above callbacks are being |
| 166 | * executed. However, it is not allowed to unregister a device from within any | 170 | * executed. However, it is not allowed to unregister a device from within any |
| 167 | * of its own callbacks. | 171 | * of its own callbacks. |
| 172 | * | ||
| 173 | * There also are the following callbacks related to run-time power management | ||
| 174 | * of devices: | ||
| 175 | * | ||
| 176 | * @runtime_suspend: Prepare the device for a condition in which it won't be | ||
| 177 | * able to communicate with the CPU(s) and RAM due to power management. | ||
| 178 | * This need not mean that the device should be put into a low power state. | ||
| 179 | * For example, if the device is behind a link which is about to be turned | ||
| 180 | * off, the device may remain at full power. If the device does go to low | ||
| 181 | * power and if device_may_wakeup(dev) is true, remote wake-up (i.e., a | ||
| 182 | * hardware mechanism allowing the device to request a change of its power | ||
| 183 | * state, such as PCI PME) should be enabled for it. | ||
| 184 | * | ||
| 185 | * @runtime_resume: Put the device into the fully active state in response to a | ||
| 186 | * wake-up event generated by hardware or at the request of software. If | ||
| 187 | * necessary, put the device into the full power state and restore its | ||
| 188 | * registers, so that it is fully operational. | ||
| 189 | * | ||
| 190 | * @runtime_idle: Device appears to be inactive and it might be put into a low | ||
| 191 | * power state if all of the necessary conditions are satisfied. Check | ||
| 192 | * these conditions and handle the device as appropriate, possibly queueing | ||
| 193 | * a suspend request for it. The return value is ignored by the PM core. | ||
| 168 | */ | 194 | */ |
| 169 | 195 | ||
| 170 | struct dev_pm_ops { | 196 | struct dev_pm_ops { |
| @@ -182,8 +208,25 @@ struct dev_pm_ops { | |||
| 182 | int (*thaw_noirq)(struct device *dev); | 208 | int (*thaw_noirq)(struct device *dev); |
| 183 | int (*poweroff_noirq)(struct device *dev); | 209 | int (*poweroff_noirq)(struct device *dev); |
| 184 | int (*restore_noirq)(struct device *dev); | 210 | int (*restore_noirq)(struct device *dev); |
| 211 | int (*runtime_suspend)(struct device *dev); | ||
| 212 | int (*runtime_resume)(struct device *dev); | ||
| 213 | int (*runtime_idle)(struct device *dev); | ||
| 185 | }; | 214 | }; |
| 186 | 215 | ||
| 216 | /* | ||
| 217 | * Use this if you want to use the same suspend and resume callbacks for suspend | ||
| 218 | * to RAM and hibernation. | ||
| 219 | */ | ||
| 220 | #define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \ | ||
| 221 | struct dev_pm_ops name = { \ | ||
| 222 | .suspend = suspend_fn, \ | ||
| 223 | .resume = resume_fn, \ | ||
| 224 | .freeze = suspend_fn, \ | ||
| 225 | .thaw = resume_fn, \ | ||
| 226 | .poweroff = suspend_fn, \ | ||
| 227 | .restore = resume_fn, \ | ||
| 228 | } | ||
| 229 | |||
| 187 | /** | 230 | /** |
| 188 | * PM_EVENT_ messages | 231 | * PM_EVENT_ messages |
| 189 | * | 232 | * |
| @@ -315,14 +358,80 @@ enum dpm_state { | |||
| 315 | DPM_OFF_IRQ, | 358 | DPM_OFF_IRQ, |
| 316 | }; | 359 | }; |
| 317 | 360 | ||
| 361 | /** | ||
| 362 | * Device run-time power management status. | ||
| 363 | * | ||
| 364 | * These status labels are used internally by the PM core to indicate the | ||
| 365 | * current status of a device with respect to the PM core operations. They do | ||
| 366 | * not reflect the actual power state of the device or its status as seen by the | ||
| 367 | * driver. | ||
| 368 | * | ||
| 369 | * RPM_ACTIVE Device is fully operational. Indicates that the device | ||
| 370 | * bus type's ->runtime_resume() callback has completed | ||
| 371 | * successfully. | ||
| 372 | * | ||
| 373 | * RPM_SUSPENDED Device bus type's ->runtime_suspend() callback has | ||
| 374 | * completed successfully. The device is regarded as | ||
| 375 | * suspended. | ||
| 376 | * | ||
| 377 | * RPM_RESUMING Device bus type's ->runtime_resume() callback is being | ||
| 378 | * executed. | ||
| 379 | * | ||
| 380 | * RPM_SUSPENDING Device bus type's ->runtime_suspend() callback is being | ||
| 381 | * executed. | ||
| 382 | */ | ||
| 383 | |||
| 384 | enum rpm_status { | ||
| 385 | RPM_ACTIVE = 0, | ||
| 386 | RPM_RESUMING, | ||
| 387 | RPM_SUSPENDED, | ||
| 388 | RPM_SUSPENDING, | ||
| 389 | }; | ||
| 390 | |||
| 391 | /** | ||
| 392 | * Device run-time power management request types. | ||
| 393 | * | ||
| 394 | * RPM_REQ_NONE Do nothing. | ||
| 395 | * | ||
| 396 | * RPM_REQ_IDLE Run the device bus type's ->runtime_idle() callback | ||
| 397 | * | ||
| 398 | * RPM_REQ_SUSPEND Run the device bus type's ->runtime_suspend() callback | ||
| 399 | * | ||
| 400 | * RPM_REQ_RESUME Run the device bus type's ->runtime_resume() callback | ||
| 401 | */ | ||
| 402 | |||
| 403 | enum rpm_request { | ||
| 404 | RPM_REQ_NONE = 0, | ||
| 405 | RPM_REQ_IDLE, | ||
| 406 | RPM_REQ_SUSPEND, | ||
| 407 | RPM_REQ_RESUME, | ||
| 408 | }; | ||
| 409 | |||
| 318 | struct dev_pm_info { | 410 | struct dev_pm_info { |
| 319 | pm_message_t power_state; | 411 | pm_message_t power_state; |
| 320 | unsigned can_wakeup:1; | 412 | unsigned int can_wakeup:1; |
| 321 | unsigned should_wakeup:1; | 413 | unsigned int should_wakeup:1; |
| 322 | enum dpm_state status; /* Owned by the PM core */ | 414 | enum dpm_state status; /* Owned by the PM core */ |
| 323 | #ifdef CONFIG_PM_SLEEP | 415 | #ifdef CONFIG_PM_SLEEP |
| 324 | struct list_head entry; | 416 | struct list_head entry; |
| 325 | #endif | 417 | #endif |
| 418 | #ifdef CONFIG_PM_RUNTIME | ||
| 419 | struct timer_list suspend_timer; | ||
| 420 | unsigned long timer_expires; | ||
| 421 | struct work_struct work; | ||
| 422 | wait_queue_head_t wait_queue; | ||
| 423 | spinlock_t lock; | ||
| 424 | atomic_t usage_count; | ||
| 425 | atomic_t child_count; | ||
| 426 | unsigned int disable_depth:3; | ||
| 427 | unsigned int ignore_children:1; | ||
| 428 | unsigned int idle_notification:1; | ||
| 429 | unsigned int request_pending:1; | ||
| 430 | unsigned int deferred_resume:1; | ||
| 431 | enum rpm_request request; | ||
| 432 | enum rpm_status runtime_status; | ||
| 433 | int runtime_error; | ||
| 434 | #endif | ||
| 326 | }; | 435 | }; |
| 327 | 436 | ||
| 328 | /* | 437 | /* |
diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h new file mode 100644 index 000000000000..44087044910f --- /dev/null +++ b/include/linux/pm_runtime.h | |||
| @@ -0,0 +1,114 @@ | |||
| 1 | /* | ||
| 2 | * pm_runtime.h - Device run-time power management helper functions. | ||
| 3 | * | ||
| 4 | * Copyright (C) 2009 Rafael J. Wysocki <rjw@sisk.pl> | ||
| 5 | * | ||
| 6 | * This file is released under the GPLv2. | ||
| 7 | */ | ||
| 8 | |||
| 9 | #ifndef _LINUX_PM_RUNTIME_H | ||
| 10 | #define _LINUX_PM_RUNTIME_H | ||
| 11 | |||
| 12 | #include <linux/device.h> | ||
| 13 | #include <linux/pm.h> | ||
| 14 | |||
| 15 | #ifdef CONFIG_PM_RUNTIME | ||
| 16 | |||
| 17 | extern struct workqueue_struct *pm_wq; | ||
| 18 | |||
| 19 | extern int pm_runtime_idle(struct device *dev); | ||
| 20 | extern int pm_runtime_suspend(struct device *dev); | ||
| 21 | extern int pm_runtime_resume(struct device *dev); | ||
| 22 | extern int pm_request_idle(struct device *dev); | ||
| 23 | extern int pm_schedule_suspend(struct device *dev, unsigned int delay); | ||
| 24 | extern int pm_request_resume(struct device *dev); | ||
| 25 | extern int __pm_runtime_get(struct device *dev, bool sync); | ||
| 26 | extern int __pm_runtime_put(struct device *dev, bool sync); | ||
| 27 | extern int __pm_runtime_set_status(struct device *dev, unsigned int status); | ||
| 28 | extern int pm_runtime_barrier(struct device *dev); | ||
| 29 | extern void pm_runtime_enable(struct device *dev); | ||
| 30 | extern void __pm_runtime_disable(struct device *dev, bool check_resume); | ||
| 31 | |||
| 32 | static inline bool pm_children_suspended(struct device *dev) | ||
| 33 | { | ||
| 34 | return dev->power.ignore_children | ||
| 35 | || !atomic_read(&dev->power.child_count); | ||
| 36 | } | ||
| 37 | |||
| 38 | static inline void pm_suspend_ignore_children(struct device *dev, bool enable) | ||
| 39 | { | ||
| 40 | dev->power.ignore_children = enable; | ||
| 41 | } | ||
| 42 | |||
| 43 | static inline void pm_runtime_get_noresume(struct device *dev) | ||
| 44 | { | ||
| 45 | atomic_inc(&dev->power.usage_count); | ||
| 46 | } | ||
| 47 | |||
| 48 | static inline void pm_runtime_put_noidle(struct device *dev) | ||
| 49 | { | ||
| 50 | atomic_add_unless(&dev->power.usage_count, -1, 0); | ||
| 51 | } | ||
| 52 | |||
| 53 | #else /* !CONFIG_PM_RUNTIME */ | ||
| 54 | |||
| 55 | static inline int pm_runtime_idle(struct device *dev) { return -ENOSYS; } | ||
| 56 | static inline int pm_runtime_suspend(struct device *dev) { return -ENOSYS; } | ||
| 57 | static inline int pm_runtime_resume(struct device *dev) { return 0; } | ||
| 58 | static inline int pm_request_idle(struct device *dev) { return -ENOSYS; } | ||
| 59 | static inline int pm_schedule_suspend(struct device *dev, unsigned int delay) | ||
| 60 | { | ||
| 61 | return -ENOSYS; | ||
| 62 | } | ||
| 63 | static inline int pm_request_resume(struct device *dev) { return 0; } | ||
| 64 | static inline int __pm_runtime_get(struct device *dev, bool sync) { return 1; } | ||
| 65 | static inline int __pm_runtime_put(struct device *dev, bool sync) { return 0; } | ||
| 66 | static inline int __pm_runtime_set_status(struct device *dev, | ||
| 67 | unsigned int status) { return 0; } | ||
| 68 | static inline int pm_runtime_barrier(struct device *dev) { return 0; } | ||
| 69 | static inline void pm_runtime_enable(struct device *dev) {} | ||
| 70 | static inline void __pm_runtime_disable(struct device *dev, bool c) {} | ||
| 71 | |||
| 72 | static inline bool pm_children_suspended(struct device *dev) { return false; } | ||
| 73 | static inline void pm_suspend_ignore_children(struct device *dev, bool en) {} | ||
| 74 | static inline void pm_runtime_get_noresume(struct device *dev) {} | ||
| 75 | static inline void pm_runtime_put_noidle(struct device *dev) {} | ||
| 76 | |||
| 77 | #endif /* !CONFIG_PM_RUNTIME */ | ||
| 78 | |||
| 79 | static inline int pm_runtime_get(struct device *dev) | ||
| 80 | { | ||
| 81 | return __pm_runtime_get(dev, false); | ||
| 82 | } | ||
| 83 | |||
| 84 | static inline int pm_runtime_get_sync(struct device *dev) | ||
| 85 | { | ||
| 86 | return __pm_runtime_get(dev, true); | ||
| 87 | } | ||
| 88 | |||
| 89 | static inline int pm_runtime_put(struct device *dev) | ||
| 90 | { | ||
| 91 | return __pm_runtime_put(dev, false); | ||
| 92 | } | ||
| 93 | |||
| 94 | static inline int pm_runtime_put_sync(struct device *dev) | ||
| 95 | { | ||
| 96 | return __pm_runtime_put(dev, true); | ||
| 97 | } | ||
| 98 | |||
| 99 | static inline int pm_runtime_set_active(struct device *dev) | ||
| 100 | { | ||
| 101 | return __pm_runtime_set_status(dev, RPM_ACTIVE); | ||
| 102 | } | ||
| 103 | |||
| 104 | static inline void pm_runtime_set_suspended(struct device *dev) | ||
| 105 | { | ||
| 106 | __pm_runtime_set_status(dev, RPM_SUSPENDED); | ||
| 107 | } | ||
| 108 | |||
| 109 | static inline void pm_runtime_disable(struct device *dev) | ||
| 110 | { | ||
| 111 | __pm_runtime_disable(dev, true); | ||
| 112 | } | ||
| 113 | |||
| 114 | #endif | ||
