PM / Runtime: Add sysfs switch for disabling device run-time PM
[safe/jmp/linux-2.6] / include / linux / pm.h
index de2e0a8..25b1eca 100644 (file)
 #define _LINUX_PM_H
 
 #include <linux/list.h>
+#include <linux/workqueue.h>
+#include <linux/spinlock.h>
+#include <linux/wait.h>
+#include <linux/timer.h>
 
 /*
  * Callbacks for platform drivers to implement.
@@ -165,6 +169,29 @@ typedef struct pm_message {
  * It is allowed to unregister devices while the above callbacks are being
  * executed.  However, it is not allowed to unregister a device from within any
  * of its own callbacks.
+ *
+ * There also are the following callbacks related to run-time power management
+ * of devices:
+ *
+ * @runtime_suspend: Prepare the device for a condition in which it won't be
+ *     able to communicate with the CPU(s) and RAM due to power management.
+ *     This need not mean that the device should be put into a low power state.
+ *     For example, if the device is behind a link which is about to be turned
+ *     off, the device may remain at full power.  If the device does go to low
+ *     power and is capable of generating run-time wake-up events, remote
+ *     wake-up (i.e., a hardware mechanism allowing the device to request a
+ *     change of its power state via a wake-up event, such as PCI PME) should
+ *     be enabled for it.
+ *
+ * @runtime_resume: Put the device into the fully active state in response to a
+ *     wake-up event generated by hardware or at the request of software.  If
+ *     necessary, put the device into the full power state and restore its
+ *     registers, so that it is fully operational.
+ *
+ * @runtime_idle: Device appears to be inactive and it might be put into a low
+ *     power state if all of the necessary conditions are satisfied.  Check
+ *     these conditions and handle the device as appropriate, possibly queueing
+ *     a suspend request for it.  The return value is ignored by the PM core.
  */
 
 struct dev_pm_ops {
@@ -182,8 +209,25 @@ struct dev_pm_ops {
        int (*thaw_noirq)(struct device *dev);
        int (*poweroff_noirq)(struct device *dev);
        int (*restore_noirq)(struct device *dev);
+       int (*runtime_suspend)(struct device *dev);
+       int (*runtime_resume)(struct device *dev);
+       int (*runtime_idle)(struct device *dev);
 };
 
+/*
+ * Use this if you want to use the same suspend and resume callbacks for suspend
+ * to RAM and hibernation.
+ */
+#define SIMPLE_DEV_PM_OPS(name, suspend_fn, resume_fn) \
+const struct dev_pm_ops name = { \
+       .suspend = suspend_fn, \
+       .resume = resume_fn, \
+       .freeze = suspend_fn, \
+       .thaw = resume_fn, \
+       .poweroff = suspend_fn, \
+       .restore = resume_fn, \
+}
+
 /**
  * PM_EVENT_ messages
  *
@@ -315,14 +359,82 @@ enum dpm_state {
        DPM_OFF_IRQ,
 };
 
+/**
+ * Device run-time power management status.
+ *
+ * These status labels are used internally by the PM core to indicate the
+ * current status of a device with respect to the PM core operations.  They do
+ * not reflect the actual power state of the device or its status as seen by the
+ * driver.
+ *
+ * RPM_ACTIVE          Device is fully operational.  Indicates that the device
+ *                     bus type's ->runtime_resume() callback has completed
+ *                     successfully.
+ *
+ * RPM_SUSPENDED       Device bus type's ->runtime_suspend() callback has
+ *                     completed successfully.  The device is regarded as
+ *                     suspended.
+ *
+ * RPM_RESUMING                Device bus type's ->runtime_resume() callback is being
+ *                     executed.
+ *
+ * RPM_SUSPENDING      Device bus type's ->runtime_suspend() callback is being
+ *                     executed.
+ */
+
+enum rpm_status {
+       RPM_ACTIVE = 0,
+       RPM_RESUMING,
+       RPM_SUSPENDED,
+       RPM_SUSPENDING,
+};
+
+/**
+ * Device run-time power management request types.
+ *
+ * RPM_REQ_NONE                Do nothing.
+ *
+ * RPM_REQ_IDLE                Run the device bus type's ->runtime_idle() callback
+ *
+ * RPM_REQ_SUSPEND     Run the device bus type's ->runtime_suspend() callback
+ *
+ * RPM_REQ_RESUME      Run the device bus type's ->runtime_resume() callback
+ */
+
+enum rpm_request {
+       RPM_REQ_NONE = 0,
+       RPM_REQ_IDLE,
+       RPM_REQ_SUSPEND,
+       RPM_REQ_RESUME,
+};
+
 struct dev_pm_info {
        pm_message_t            power_state;
-       unsigned                can_wakeup:1;
-       unsigned                should_wakeup:1;
+       unsigned int            can_wakeup:1;
+       unsigned int            should_wakeup:1;
        enum dpm_state          status;         /* Owned by the PM core */
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM_SLEEP
        struct list_head        entry;
 #endif
+#ifdef CONFIG_PM_RUNTIME
+       struct timer_list       suspend_timer;
+       unsigned long           timer_expires;
+       struct work_struct      work;
+       wait_queue_head_t       wait_queue;
+       spinlock_t              lock;
+       atomic_t                usage_count;
+       atomic_t                child_count;
+       unsigned int            disable_depth:3;
+       unsigned int            ignore_children:1;
+       unsigned int            idle_notification:1;
+       unsigned int            request_pending:1;
+       unsigned int            deferred_resume:1;
+       unsigned int            run_wake:1;
+       unsigned int            runtime_auto:1;
+       enum rpm_request        request;
+       enum rpm_status         runtime_status;
+       int                     runtime_error;
+#endif
 };
 
 /*
@@ -381,13 +493,14 @@ struct dev_pm_info {
 
 #ifdef CONFIG_PM_SLEEP
 extern void device_pm_lock(void);
-extern void device_power_up(pm_message_t state);
-extern void device_resume(pm_message_t state);
+extern int sysdev_resume(void);
+extern void dpm_resume_noirq(pm_message_t state);
+extern void dpm_resume_end(pm_message_t state);
 
 extern void device_pm_unlock(void);
-extern int device_power_down(pm_message_t state);
-extern int device_suspend(pm_message_t state);
-extern int device_prepare_suspend(pm_message_t state);
+extern int sysdev_suspend(pm_message_t state);
+extern int dpm_suspend_noirq(pm_message_t state);
+extern int dpm_suspend_start(pm_message_t state);
 
 extern void __suspend_report_result(const char *function, void *fn, int ret);
 
@@ -398,7 +511,10 @@ extern void __suspend_report_result(const char *function, void *fn, int ret);
 
 #else /* !CONFIG_PM_SLEEP */
 
-static inline int device_suspend(pm_message_t state)
+#define device_pm_lock() do {} while (0)
+#define device_pm_unlock() do {} while (0)
+
+static inline int dpm_suspend_start(pm_message_t state)
 {
        return 0;
 }
@@ -407,6 +523,14 @@ static inline int device_suspend(pm_message_t state)
 
 #endif /* !CONFIG_PM_SLEEP */
 
+/* How to reorder dpm_list after device_move() */
+enum dpm_order {
+       DPM_ORDER_NONE,
+       DPM_ORDER_DEV_AFTER_PARENT,
+       DPM_ORDER_PARENT_BEFORE_DEV,
+       DPM_ORDER_DEV_LAST,
+};
+
 /*
  * Global Power Management flags
  * Used to keep APM and ACPI from both being active