From c7b61de5b7b17f0df34dc7d2f8b9576f8bd36fce Mon Sep 17 00:00:00 2001 From: Alan Stern Date: Wed, 1 Dec 2010 00:14:42 +0100 Subject: PM / Runtime: Add synchronous runtime interface for interrupt handlers (v3) This patch (as1431c) makes the synchronous runtime-PM interface suitable for use in interrupt handlers. Subsystems can call the new pm_runtime_irq_safe() function to tell the PM core that a device's runtime_suspend and runtime_resume callbacks should be invoked with interrupts disabled and the spinlock held. This permits the pm_runtime_get_sync() and the new pm_runtime_put_sync_suspend() routines to be called from within interrupt handlers. When a device is declared irq-safe in this way, the PM core increments the parent's usage count, so the parent will never be runtime suspended. This prevents difficult situations in which an irq-safe device can't resume because it is forced to wait for its non-irq-safe parent. Signed-off-by: Alan Stern Signed-off-by: Rafael J. Wysocki --- include/linux/pm.h | 1 + include/linux/pm_runtime.h | 7 +++++++ 2 files changed, 8 insertions(+) (limited to 'include/linux') diff --git a/include/linux/pm.h b/include/linux/pm.h index 40f3f45702ba..61f2066e6852 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -486,6 +486,7 @@ struct dev_pm_info { unsigned int run_wake:1; unsigned int runtime_auto:1; unsigned int no_callbacks:1; + unsigned int irq_safe:1; unsigned int use_autosuspend:1; unsigned int timer_autosuspends:1; enum rpm_request request; diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index d19f1cca7f74..e9cc049ccb62 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -40,6 +40,7 @@ extern int pm_generic_runtime_idle(struct device *dev); extern int pm_generic_runtime_suspend(struct device *dev); extern int pm_generic_runtime_resume(struct device *dev); extern void pm_runtime_no_callbacks(struct device *dev); +extern void pm_runtime_irq_safe(struct device *dev); extern void __pm_runtime_use_autosuspend(struct device *dev, bool use); extern void pm_runtime_set_autosuspend_delay(struct device *dev, int delay); extern unsigned long pm_runtime_autosuspend_expiration(struct device *dev); @@ -124,6 +125,7 @@ static inline int pm_generic_runtime_idle(struct device *dev) { return 0; } static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; } static inline int pm_generic_runtime_resume(struct device *dev) { return 0; } static inline void pm_runtime_no_callbacks(struct device *dev) {} +static inline void pm_runtime_irq_safe(struct device *dev) {} static inline void pm_runtime_mark_last_busy(struct device *dev) {} static inline void __pm_runtime_use_autosuspend(struct device *dev, @@ -196,6 +198,11 @@ static inline int pm_runtime_put_sync(struct device *dev) return __pm_runtime_idle(dev, RPM_GET_PUT); } +static inline int pm_runtime_put_sync_suspend(struct device *dev) +{ + return __pm_runtime_suspend(dev, RPM_GET_PUT); +} + static inline int pm_runtime_put_sync_autosuspend(struct device *dev) { return __pm_runtime_suspend(dev, RPM_GET_PUT | RPM_AUTO); -- cgit From a2867e08c8e3bdbc00caf56bc3bdde19ccc058e3 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 3 Dec 2010 22:58:31 +0100 Subject: PM / Wakeup: Replace pm_check_wakeup_events() with pm_wakeup_pending() To avoid confusion with the meaning and return value of pm_check_wakeup_events() replace it with pm_wakeup_pending() that will work the other way around (ie. return true when system-wide power transition should be aborted). Signed-off-by: Rafael J. Wysocki --- include/linux/suspend.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 26697514c5ec..144b34be5c32 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -292,7 +292,7 @@ extern int unregister_pm_notifier(struct notifier_block *nb); /* drivers/base/power/wakeup.c */ extern bool events_check_enabled; -extern bool pm_check_wakeup_events(void); +extern bool pm_wakeup_pending(void); extern bool pm_get_wakeup_count(unsigned int *count); extern bool pm_save_wakeup_count(unsigned int count); #else /* !CONFIG_PM_SLEEP */ @@ -309,7 +309,7 @@ static inline int unregister_pm_notifier(struct notifier_block *nb) #define pm_notifier(fn, pri) do { (void)(fn); } while (0) -static inline bool pm_check_wakeup_events(void) { return true; } +static inline bool pm_wakeup_pending(void) { return false; } #endif /* !CONFIG_PM_SLEEP */ extern struct mutex pm_mutex; -- cgit From b8c76f6aed0ab7df73a6410f3f82de2c831bb144 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Thu, 16 Dec 2010 00:51:21 +0100 Subject: PM: Replace the device power.status field with a bit field The device power.status field is too complicated for its purpose (storing the information about whether or not the device is in the "active" state from the PM core's point of view), so replace it with a bit field and modify all of its users accordingly. Signed-off-by: Rafael J. Wysocki --- include/linux/device.h | 4 ++-- include/linux/pm.h | 43 ++----------------------------------------- 2 files changed, 4 insertions(+), 43 deletions(-) (limited to 'include/linux') diff --git a/include/linux/device.h b/include/linux/device.h index dd4895313468..45bc8c1669d2 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -508,13 +508,13 @@ static inline int device_is_registered(struct device *dev) static inline void device_enable_async_suspend(struct device *dev) { - if (dev->power.status == DPM_ON) + if (!dev->power.in_suspend) dev->power.async_suspend = true; } static inline void device_disable_async_suspend(struct device *dev) { - if (dev->power.status == DPM_ON) + if (!dev->power.in_suspend) dev->power.async_suspend = false; } diff --git a/include/linux/pm.h b/include/linux/pm.h index 61f2066e6852..c1756dfeb8c5 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -366,45 +366,6 @@ extern struct dev_pm_ops generic_subsys_pm_ops; #define PMSG_AUTO_RESUME ((struct pm_message) \ { .event = PM_EVENT_AUTO_RESUME, }) -/** - * Device power management states - * - * These state labels are used internally by the PM core to indicate the current - * status of a device with respect to the PM core operations. - * - * DPM_ON Device is regarded as operational. Set this way - * initially and when ->complete() is about to be called. - * Also set when ->prepare() fails. - * - * DPM_PREPARING Device is going to be prepared for a PM transition. Set - * when ->prepare() is about to be called. - * - * DPM_RESUMING Device is going to be resumed. Set when ->resume(), - * ->thaw(), or ->restore() is about to be called. - * - * DPM_SUSPENDING Device has been prepared for a power transition. Set - * when ->prepare() has just succeeded. - * - * DPM_OFF Device is regarded as inactive. Set immediately after - * ->suspend(), ->freeze(), or ->poweroff() has succeeded. - * Also set when ->resume()_noirq, ->thaw_noirq(), or - * ->restore_noirq() is about to be called. - * - * DPM_OFF_IRQ Device is in a "deep sleep". Set immediately after - * ->suspend_noirq(), ->freeze_noirq(), or - * ->poweroff_noirq() has just succeeded. - */ - -enum dpm_state { - DPM_INVALID, - DPM_ON, - DPM_PREPARING, - DPM_RESUMING, - DPM_SUSPENDING, - DPM_OFF, - DPM_OFF_IRQ, -}; - /** * Device run-time power management status. * @@ -463,8 +424,8 @@ struct wakeup_source; struct dev_pm_info { pm_message_t power_state; unsigned int can_wakeup:1; - unsigned async_suspend:1; - enum dpm_state status; /* Owned by the PM core */ + unsigned int async_suspend:1; + unsigned int in_suspend:1; /* Owned by the PM core */ spinlock_t lock; #ifdef CONFIG_PM_SLEEP struct list_head entry; -- cgit From 4b31db8a16fa0d4d6a0fa42d044e7a4f4dad3641 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Fri, 24 Dec 2010 15:04:06 +0100 Subject: PM / Runtime: Generic resume shouldn't set RPM_ACTIVE unconditionally The __pm_generic_resume() function changes the given device's runtime PM status to RPM_ACTIVE if its driver's callback returns 0, but it only should do that if the rumtime PM is enabled for the device. Signed-off-by: Rafael J. Wysocki --- include/linux/pm_runtime.h | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'include/linux') diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index e9cc049ccb62..d34f067e2a7f 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -82,6 +82,11 @@ static inline bool pm_runtime_suspended(struct device *dev) && !dev->power.disable_depth; } +static inline bool pm_runtime_enabled(struct device *dev) +{ + return !dev->power.disable_depth; +} + static inline void pm_runtime_mark_last_busy(struct device *dev) { ACCESS_ONCE(dev->power.last_busy) = jiffies; @@ -120,6 +125,7 @@ static inline void pm_runtime_put_noidle(struct device *dev) {} static inline bool device_run_wake(struct device *dev) { return false; } static inline void device_set_run_wake(struct device *dev, bool enable) {} static inline bool pm_runtime_suspended(struct device *dev) { return false; } +static inline bool pm_runtime_enabled(struct device *dev) { return false; } static inline int pm_generic_runtime_idle(struct device *dev) { return 0; } static inline int pm_generic_runtime_suspend(struct device *dev) { return 0; } -- cgit From 62bcb91573425975d6ad2389d7ab1d8feca88ab4 Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 24 Dec 2010 15:04:41 +0100 Subject: PM: Prototype the pm_generic_ operations The pm_generic_ operations are all exported but are not prototyped in any header file for direct use. Do so. [rjw: Added extern.] Signed-off-by: Mark Brown Signed-off-by: Rafael J. Wysocki --- include/linux/pm.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include/linux') diff --git a/include/linux/pm.h b/include/linux/pm.h index c1756dfeb8c5..dd9c7ab38270 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -572,4 +572,11 @@ extern unsigned int pm_flags; #define PM_APM 1 #define PM_ACPI 2 +extern int pm_generic_suspend(struct device *dev); +extern int pm_generic_resume(struct device *dev); +extern int pm_generic_freeze(struct device *dev); +extern int pm_generic_thaw(struct device *dev); +extern int pm_generic_restore(struct device *dev); +extern int pm_generic_poweroff(struct device *dev); + #endif /* _LINUX_PM_H */ -- cgit