From 30e3ce6dcbe3fc29c343b17e768b07d4a795de21 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 29 Apr 2012 22:52:52 +0200 Subject: PM / Sleep: Change wakeup source statistics to follow Android Wakeup statistics used by Android are slightly different from what we have in wakeup sources at the moment and there aren't any known users of those statistics other than Android, so modify them to make it easier for Android to switch to wakeup sources. This removes the struct wakeup_source's hit_cout field, which is very rough and therefore not very useful, and adds two new fields, wakeup_count and expire_count. The first one tracks how many times the wakeup source is activated with events_check_enabled set (which roughly corresponds to the situations when a system power transition to a sleep state is in progress and would be aborted by this wakeup source if it were the only active one at that time) and the second one is the number of times the wakeup source has been activated with a timeout that expired. Additionally, the last_time field is now updated when the wakeup source is deactivated too (previously it was only updated during the wakeup source's activation), which seems to be what Android does with the analogous counter for wakelocks. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman --- include/linux/pm_wakeup.h | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h index d9f05113e5fb..5285317a612a 100644 --- a/include/linux/pm_wakeup.h +++ b/include/linux/pm_wakeup.h @@ -33,12 +33,14 @@ * * @total_time: Total time this wakeup source has been active. * @max_time: Maximum time this wakeup source has been continuously active. - * @last_time: Monotonic clock when the wakeup source's was activated last time. + * @last_time: Monotonic clock when the wakeup source's was touched last time. * @event_count: Number of signaled wakeup events. * @active_count: Number of times the wakeup sorce was activated. * @relax_count: Number of times the wakeup sorce was deactivated. - * @hit_count: Number of times the wakeup sorce might abort system suspend. + * @expire_count: Number of times the wakeup source's timeout has expired. + * @wakeup_count: Number of times the wakeup source might abort suspend. * @active: Status of the wakeup source. + * @has_timeout: The wakeup source has been activated with a timeout. */ struct wakeup_source { const char *name; @@ -52,8 +54,9 @@ struct wakeup_source { unsigned long event_count; unsigned long active_count; unsigned long relax_count; - unsigned long hit_count; - unsigned int active:1; + unsigned long expire_count; + unsigned long wakeup_count; + bool active:1; }; #ifdef CONFIG_PM_SLEEP -- cgit v1.2.3 From 6791e36c4a40e8930e08669e60077eea6770c429 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Sun, 29 Apr 2012 22:53:02 +0200 Subject: PM / Sleep: Add wakeup_source_activate and wakeup_source_deactivate tracepoints MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add tracepoints to wakeup_source_activate and wakeup_source_deactivate. Useful for checking that specific wakeup sources overlap as expected. Signed-off-by: Arve Hjønnevåg Acked-by: Greg Kroah-Hartman Signed-off-by: Rafael J. Wysocki --- include/trace/events/power.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'include') diff --git a/include/trace/events/power.h b/include/trace/events/power.h index cae9a94f025d..0c9783841a30 100644 --- a/include/trace/events/power.h +++ b/include/trace/events/power.h @@ -65,6 +65,40 @@ TRACE_EVENT(machine_suspend, TP_printk("state=%lu", (unsigned long)__entry->state) ); +DECLARE_EVENT_CLASS(wakeup_source, + + TP_PROTO(const char *name, unsigned int state), + + TP_ARGS(name, state), + + TP_STRUCT__entry( + __string( name, name ) + __field( u64, state ) + ), + + TP_fast_assign( + __assign_str(name, name); + __entry->state = state; + ), + + TP_printk("%s state=0x%lx", __get_str(name), + (unsigned long)__entry->state) +); + +DEFINE_EVENT(wakeup_source, wakeup_source_activate, + + TP_PROTO(const char *name, unsigned int state), + + TP_ARGS(name, state) +); + +DEFINE_EVENT(wakeup_source, wakeup_source_deactivate, + + TP_PROTO(const char *name, unsigned int state), + + TP_ARGS(name, state) +); + #ifdef CONFIG_EVENT_POWER_TRACING_DEPRECATED /* -- cgit v1.2.3 From 7483b4a4d9abf9dcf1ffe6e805ead2847ec3264e Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 29 Apr 2012 22:53:22 +0200 Subject: PM / Sleep: Implement opportunistic sleep, v2 Introduce a mechanism by which the kernel can trigger global transitions to a sleep state chosen by user space if there are no active wakeup sources. It consists of a new sysfs attribute, /sys/power/autosleep, that can be written one of the strings returned by reads from /sys/power/state, an ordered workqueue and a work item carrying out the "suspend" operations. If a string representing the system's sleep state is written to /sys/power/autosleep, the work item triggering transitions to that state is queued up and it requeues itself after every execution until user space writes "off" to /sys/power/autosleep. That work item enables the detection of wakeup events using the functions already defined in drivers/base/power/wakeup.c (with one small modification) and calls either pm_suspend(), or hibernate() to put the system into a sleep state. If a wakeup event is reported while the transition is in progress, it will abort the transition and the "system suspend" work item will be queued up again. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman Reviewed-by: NeilBrown --- include/linux/suspend.h | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/suspend.h b/include/linux/suspend.h index ac1c114c499d..76b7ec7d3a81 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -356,7 +356,7 @@ extern int unregister_pm_notifier(struct notifier_block *nb); extern bool events_check_enabled; extern bool pm_wakeup_pending(void); -extern bool pm_get_wakeup_count(unsigned int *count); +extern bool pm_get_wakeup_count(unsigned int *count, bool block); extern bool pm_save_wakeup_count(unsigned int count); static inline void lock_system_sleep(void) @@ -407,6 +407,17 @@ static inline void unlock_system_sleep(void) {} #endif /* !CONFIG_PM_SLEEP */ +#ifdef CONFIG_PM_AUTOSLEEP + +/* kernel/power/autosleep.c */ +void queue_up_suspend_work(void); + +#else /* !CONFIG_PM_AUTOSLEEP */ + +static inline void queue_up_suspend_work(void) {} + +#endif /* !CONFIG_PM_AUTOSLEEP */ + #ifdef CONFIG_ARCH_SAVE_PAGE_KEYS /* * The ARCH_SAVE_PAGE_KEYS functions can be used by an architecture -- cgit v1.2.3 From 55850945e872531644f31fefd217d61dd15dcab8 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 29 Apr 2012 22:53:32 +0200 Subject: PM / Sleep: Add "prevent autosleep time" statistics to wakeup sources Android uses one wakelock statistics that is only necessary for opportunistic sleep. Namely, the prevent_suspend_time field accumulates the total time the given wakelock has been locked while "automatic suspend" was enabled. Add an analogous field, prevent_sleep_time, to wakeup sources and make it behave in a similar way. Signed-off-by: Rafael J. Wysocki Acked-by: Greg Kroah-Hartman --- include/linux/pm_wakeup.h | 4 ++++ include/linux/suspend.h | 1 + 2 files changed, 5 insertions(+) (limited to 'include') diff --git a/include/linux/pm_wakeup.h b/include/linux/pm_wakeup.h index 5285317a612a..569781faa504 100644 --- a/include/linux/pm_wakeup.h +++ b/include/linux/pm_wakeup.h @@ -34,6 +34,7 @@ * @total_time: Total time this wakeup source has been active. * @max_time: Maximum time this wakeup source has been continuously active. * @last_time: Monotonic clock when the wakeup source's was touched last time. + * @prevent_sleep_time: Total time this source has been preventing autosleep. * @event_count: Number of signaled wakeup events. * @active_count: Number of times the wakeup sorce was activated. * @relax_count: Number of times the wakeup sorce was deactivated. @@ -51,12 +52,15 @@ struct wakeup_source { ktime_t total_time; ktime_t max_time; ktime_t last_time; + ktime_t start_prevent_time; + ktime_t prevent_sleep_time; unsigned long event_count; unsigned long active_count; unsigned long relax_count; unsigned long expire_count; unsigned long wakeup_count; bool active:1; + bool autosleep_enabled:1; }; #ifdef CONFIG_PM_SLEEP diff --git a/include/linux/suspend.h b/include/linux/suspend.h index 76b7ec7d3a81..cd83059fb592 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -358,6 +358,7 @@ extern bool events_check_enabled; extern bool pm_wakeup_pending(void); extern bool pm_get_wakeup_count(unsigned int *count, bool block); extern bool pm_save_wakeup_count(unsigned int count); +extern void pm_wakep_autosleep_enabled(bool set); static inline void lock_system_sleep(void) { -- cgit v1.2.3 From a5bef810ad9816a3a8e500d8832be77d52903a12 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 29 Apr 2012 22:54:17 +0200 Subject: PM / Domains: Rework default device stop governor function, v2 The existing default device stop governor function for PM domains, default_stop_ok(), is supposed to check whether or not the device's PM QoS latency constraint will be violated if the device is stopped by pm_genpd_runtime_suspend(). However, the computations carried out by it don't reflect the definition of the PM QoS latency constrait in Documentation/ABI/testing/sysfs-devices-power. Make default_stop_ok() follow the definition of the PM QoS latency constrait. In particular, make it take the device's start and stop latencies correctly. Add a new field, effective_constraint_ns, to struct gpd_timing_data and use it to store the difference between the device's PM QoS constraint and its resume latency for use by the device's parent (the effective_constraint_ns values for the children are used for computing the parent's one along with its PM QoS constraint). Remove the break_even_ns field from struct gpd_timing_data, because it's not used any more. Signed-off-by: Rafael J. Wysocki --- include/linux/pm_domain.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 91f8286106ea..9c25219458c2 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -93,7 +93,7 @@ struct gpd_timing_data { s64 start_latency_ns; s64 save_state_latency_ns; s64 restore_state_latency_ns; - s64 break_even_ns; + s64 effective_constraint_ns; }; struct generic_pm_domain_data { -- cgit v1.2.3 From dd8683e97f12609fb3f8c4318628f0d246542f89 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 29 Apr 2012 22:54:30 +0200 Subject: PM / Domains: Rework default domain power off governor function, v2 The existing default domain power down governor function for PM domains, default_power_down_ok(), is supposed to check whether or not the PM QoS latency constraints of the devices in the domain will be violated if the domain is turned off by pm_genpd_poweroff(). However, the computations carried out by it don't reflect the definition of the PM QoS latency constrait in Documentation/ABI/testing/sysfs-devices-power. Make default_power_down_ok() follow the definition of the PM QoS latency constrait. In particular, make it only take latencies into account, because it doesn't matter how much time has elapsed since the domain's devices were suspended for the computation. Remove the break_even_ns and power_off_time fields from struct generic_pm_domain, because they are not necessary any more. Signed-off-by: Rafael J. Wysocki --- include/linux/pm_domain.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 9c25219458c2..e7ada5ccdfc2 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -70,9 +70,7 @@ struct generic_pm_domain { int (*power_on)(struct generic_pm_domain *domain); s64 power_on_latency_ns; struct gpd_dev_ops dev_ops; - s64 break_even_ns; /* Power break even for the entire domain. */ s64 max_off_time_ns; /* Maximum allowed "suspended" time. */ - ktime_t power_off_time; struct device_node *of_node; /* Node in device tree */ }; -- cgit v1.2.3 From 76e267d822f2913893ad210ba431607aa8e2af94 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 29 Apr 2012 22:54:36 +0200 Subject: PM / Runtime: Remove device fields related to suspend time, v2 After the previous changes in default_stop_ok() and default_power_down_ok() for PM domains, there are two fields in struct dev_pm_info that aren't necessary any more, suspend_time and max_time_suspended_ns. Remove those fields along with all of the code that accesses them, which simplifies the runtime PM framework quite a bit. Signed-off-by: Rafael J. Wysocki --- include/linux/pm.h | 2 -- include/linux/pm_runtime.h | 3 --- 2 files changed, 5 deletions(-) (limited to 'include') diff --git a/include/linux/pm.h b/include/linux/pm.h index 715305e05123..f067e60a3832 100644 --- a/include/linux/pm.h +++ b/include/linux/pm.h @@ -544,8 +544,6 @@ struct dev_pm_info { unsigned long active_jiffies; unsigned long suspended_jiffies; unsigned long accounting_timestamp; - ktime_t suspend_time; - s64 max_time_suspended_ns; struct dev_pm_qos_request *pq_req; #endif struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */ diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 609daae7a014..f271860c78d5 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -150,9 +150,6 @@ static inline void pm_runtime_set_autosuspend_delay(struct device *dev, static inline unsigned long pm_runtime_autosuspend_expiration( struct device *dev) { return 0; } -static inline void pm_runtime_update_max_time_suspended(struct device *dev, - s64 delta_ns) {} - #endif /* !CONFIG_PM_RUNTIME */ static inline int pm_runtime_idle(struct device *dev) -- cgit v1.2.3 From 4d7e30d98939a0340022ccd49325a3d70f7e0238 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arve=20Hj=C3=B8nnev=C3=A5g?= Date: Tue, 1 May 2012 21:33:34 +0200 Subject: epoll: Add a flag, EPOLLWAKEUP, to prevent suspend while epoll events are ready MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When an epoll_event, that has the EPOLLWAKEUP flag set, is ready, a wakeup_source will be active to prevent suspend. This can be used to handle wakeup events from a driver that support poll, e.g. input, if that driver wakes up the waitqueue passed to epoll before allowing suspend. Signed-off-by: Arve Hjønnevåg Reviewed-by: NeilBrown Signed-off-by: Rafael J. Wysocki --- include/linux/capability.h | 5 ++++- include/linux/eventpoll.h | 12 ++++++++++++ 2 files changed, 16 insertions(+), 1 deletion(-) (limited to 'include') diff --git a/include/linux/capability.h b/include/linux/capability.h index 12d52dedb229..c398cff3dab7 100644 --- a/include/linux/capability.h +++ b/include/linux/capability.h @@ -360,8 +360,11 @@ struct cpu_vfs_cap_data { #define CAP_WAKE_ALARM 35 +/* Allow preventing system suspends while epoll events are pending */ -#define CAP_LAST_CAP CAP_WAKE_ALARM +#define CAP_EPOLLWAKEUP 36 + +#define CAP_LAST_CAP CAP_EPOLLWAKEUP #define cap_valid(x) ((x) >= 0 && (x) <= CAP_LAST_CAP) diff --git a/include/linux/eventpoll.h b/include/linux/eventpoll.h index 657ab55beda0..6f8be328770a 100644 --- a/include/linux/eventpoll.h +++ b/include/linux/eventpoll.h @@ -26,6 +26,18 @@ #define EPOLL_CTL_DEL 2 #define EPOLL_CTL_MOD 3 +/* + * Request the handling of system wakeup events so as to prevent system suspends + * from happening while those events are being processed. + * + * Assuming neither EPOLLET nor EPOLLONESHOT is set, system suspends will not be + * re-allowed until epoll_wait is called again after consuming the wakeup + * event(s). + * + * Requires CAP_EPOLLWAKEUP + */ +#define EPOLLWAKEUP (1 << 29) + /* Set the One Shot behaviour for the target file descriptor */ #define EPOLLONESHOT (1 << 30) -- cgit v1.2.3 From 6ff7bb0d02f82968be13937c03e93b6c090229df Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 1 May 2012 21:34:07 +0200 Subject: PM / Domains: Cache device stop and domain power off governor results, v3 The results of the default device stop and domain power off governor functions for generic PM domains, default_stop_ok() and default_power_down_ok(), depend only on the timing data of devices, which are static, and on their PM QoS constraints. Thus, in theory, these functions only need to carry out their computations, which may be time consuming in general, when it is known that the PM QoS constraint of at least one of the devices in question has changed. Use the PM QoS notifiers of devices to implement that. First, introduce new fields, constraint_changed and max_off_time_changed, into struct gpd_timing_data and struct generic_pm_domain, respectively, and register a PM QoS notifier function when adding a device into a domain that will set those fields to 'true' whenever the device's PM QoS constraint is modified. Second, make default_stop_ok() and default_power_down_ok() use those fields to decide whether or not to carry out their computations from scratch. The device and PM domain hierarchies are taken into account in that and the expense is that the changes of PM QoS constraints of suspended devices will not be taken into account immediately, which isn't guaranteed anyway in general. Signed-off-by: Rafael J. Wysocki --- include/linux/pm_domain.h | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'include') diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index e7ada5ccdfc2..1e994eeacdf3 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -14,6 +14,7 @@ #include #include #include +#include enum gpd_status { GPD_STATE_ACTIVE = 0, /* PM domain is active */ @@ -71,6 +72,8 @@ struct generic_pm_domain { s64 power_on_latency_ns; struct gpd_dev_ops dev_ops; s64 max_off_time_ns; /* Maximum allowed "suspended" time. */ + bool max_off_time_changed; + bool cached_power_down_ok; struct device_node *of_node; /* Node in device tree */ }; @@ -92,12 +95,16 @@ struct gpd_timing_data { s64 save_state_latency_ns; s64 restore_state_latency_ns; s64 effective_constraint_ns; + bool constraint_changed; + bool cached_stop_ok; }; struct generic_pm_domain_data { struct pm_domain_data base; struct gpd_dev_ops ops; struct gpd_timing_data td; + struct notifier_block nb; + struct mutex lock; bool need_restore; bool always_on; }; -- cgit v1.2.3 From ca1d72f033d4a89e60db25f680896c76c721062b Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 14 May 2012 21:45:52 +0200 Subject: PM / Domains: Make it possible to add devices to inactive domains The generic PM domains core code currently requires domains to be in the "power on" state for adding devices to them, but this limitation turns out to be inconvenient in some situations, so remove it. For this purpose, make __pm_genpd_add_device() set the device's need_restore flag if the domain is in the "power off" state, so that the device's "restore state" (usually .runtime_resume()) callback is executed when it is resumed after the domain has been turned on. If the domain is in the "power on" state, the device's need_restore flag will be cleared by __pm_genpd_add_device(), so that its "save state" (usually .runtime_suspend()) callback is executed when the domain is about to be turned off. However, since that default behavior need not be always desirable, add a helper function pm_genpd_dev_need_restore() allowing a device's need_restore flag to be set/unset at any time. Signed-off-by: Rafael J. Wysocki --- include/linux/pm_domain.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/pm_domain.h b/include/linux/pm_domain.h index 1e994eeacdf3..30f794eb3826 100644 --- a/include/linux/pm_domain.h +++ b/include/linux/pm_domain.h @@ -146,6 +146,7 @@ static inline int pm_genpd_of_add_device(struct device_node *genpd_node, extern int pm_genpd_remove_device(struct generic_pm_domain *genpd, struct device *dev); extern void pm_genpd_dev_always_on(struct device *dev, bool val); +extern void pm_genpd_dev_need_restore(struct device *dev, bool val); extern int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, struct generic_pm_domain *new_subdomain); extern int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, @@ -189,6 +190,7 @@ static inline int pm_genpd_remove_device(struct generic_pm_domain *genpd, return -ENOSYS; } static inline void pm_genpd_dev_always_on(struct device *dev, bool val) {} +static inline void pm_genpd_dev_need_restore(struct device *dev, bool val) {} static inline int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, struct generic_pm_domain *new_sd) { -- cgit v1.2.3