From 45f0a85c8258741d11bda25c0a5669c06267204a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Mon, 3 Jun 2013 21:49:52 +0200 Subject: PM / Runtime: Rework the "runtime idle" helper routine The "runtime idle" helper routine, rpm_idle(), currently ignores return values from .runtime_idle() callbacks executed by it. However, it turns out that many subsystems use pm_generic_runtime_idle() which checks the return value of the driver's callback and executes pm_runtime_suspend() for the device unless that value is not 0. If that logic is moved to rpm_idle() instead, pm_generic_runtime_idle() can be dropped and its users will not need any .runtime_idle() callbacks any more. Moreover, the PCI, SCSI, and SATA subsystems' .runtime_idle() routines, pci_pm_runtime_idle(), scsi_runtime_idle(), and ata_port_runtime_idle(), respectively, as well as a few drivers' ones may be simplified if rpm_idle() calls rpm_suspend() after 0 has been returned by the .runtime_idle() callback executed by it. To reduce overall code bloat, make the changes described above. Tested-by: Mika Westerberg Tested-by: Kevin Hilman Signed-off-by: Rafael J. Wysocki Acked-by: Kevin Hilman Reviewed-by: Ulf Hansson Acked-by: Alan Stern --- include/linux/pm_runtime.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include') diff --git a/include/linux/pm_runtime.h b/include/linux/pm_runtime.h index 7d7e09efff9b..6fa7cea25da9 100644 --- a/include/linux/pm_runtime.h +++ b/include/linux/pm_runtime.h @@ -37,7 +37,6 @@ extern void pm_runtime_enable(struct device *dev); extern void __pm_runtime_disable(struct device *dev, bool check_resume); extern void pm_runtime_allow(struct device *dev); extern void pm_runtime_forbid(struct device *dev); -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); @@ -143,7 +142,6 @@ static inline bool pm_runtime_active(struct device *dev) { return true; } static inline bool pm_runtime_status_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; } static inline int pm_generic_runtime_resume(struct device *dev) { return 0; } static inline void pm_runtime_no_callbacks(struct device *dev) {} -- cgit v1.2.3 From bb177fedd348c92c2bea6adc9a2163ebff15272e Mon Sep 17 00:00:00 2001 From: Julius Werner Date: Wed, 12 Jun 2013 12:55:22 -0700 Subject: PM / Sleep: Print last wakeup source on failed wakeup_count write Commit a938da06 introduced a useful little log message to tell users/debuggers which wakeup source aborted a suspend. However, this message is only printed if the abort happens during the in-kernel suspend path (after writing /sys/power/state). The full specification of the /sys/power/wakeup_count facility allows user-space power managers to double-check if wakeups have already happened before it actually tries to suspend (e.g. while it was running user-space pre-suspend hooks), by writing the last known wakeup_count value to /sys/power/wakeup_count. This patch changes the sysfs handler for that node to also print said log message if that write fails, so that we can figure out the offending wakeup source for both kinds of suspend aborts. Signed-off-by: Julius Werner Signed-off-by: Rafael J. Wysocki --- include/linux/suspend.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include') diff --git a/include/linux/suspend.h b/include/linux/suspend.h index d4e3f16d5e89..f73cabf59012 100644 --- a/include/linux/suspend.h +++ b/include/linux/suspend.h @@ -363,6 +363,7 @@ 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); +extern void pm_print_active_wakeup_sources(void); static inline void lock_system_sleep(void) { -- cgit v1.2.3 From 247e9ee034b0448a585afa16e292cbb9dc0aef68 Mon Sep 17 00:00:00 2001 From: Sahara Date: Fri, 21 Jun 2013 11:12:28 +0900 Subject: PM / QoS: Add pm_qos_update_target/flags tracepoints This patch adds tracepoints to pm_qos_update_target and pm_qos_update_flags. It's useful for checking pm qos action, previous value and current value. Signed-off-by: Sahara Signed-off-by: Rafael J. Wysocki --- include/trace/events/power.h | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'include') diff --git a/include/trace/events/power.h b/include/trace/events/power.h index 427acab5d69a..f1e73bd04beb 100644 --- a/include/trace/events/power.h +++ b/include/trace/events/power.h @@ -5,6 +5,7 @@ #define _TRACE_POWER_H #include +#include #include DECLARE_EVENT_CLASS(cpu, @@ -177,6 +178,56 @@ DEFINE_EVENT(power_domain, power_domain_target, TP_ARGS(name, state, cpu_id) ); + +/* + * The pm qos events are used for pm qos update + */ +DECLARE_EVENT_CLASS(pm_qos_update, + + TP_PROTO(enum pm_qos_req_action action, int prev_value, int curr_value), + + TP_ARGS(action, prev_value, curr_value), + + TP_STRUCT__entry( + __field( enum pm_qos_req_action, action ) + __field( int, prev_value ) + __field( int, curr_value ) + ), + + TP_fast_assign( + __entry->action = action; + __entry->prev_value = prev_value; + __entry->curr_value = curr_value; + ), + + TP_printk("action=%s prev_value=%d curr_value=%d", + __print_symbolic(__entry->action, + { PM_QOS_ADD_REQ, "ADD_REQ" }, + { PM_QOS_UPDATE_REQ, "UPDATE_REQ" }, + { PM_QOS_REMOVE_REQ, "REMOVE_REQ" }), + __entry->prev_value, __entry->curr_value) +); + +DEFINE_EVENT(pm_qos_update, pm_qos_update_target, + + TP_PROTO(enum pm_qos_req_action action, int prev_value, int curr_value), + + TP_ARGS(action, prev_value, curr_value) +); + +DEFINE_EVENT_PRINT(pm_qos_update, pm_qos_update_flags, + + TP_PROTO(enum pm_qos_req_action action, int prev_value, int curr_value), + + TP_ARGS(action, prev_value, curr_value), + + TP_printk("action=%s prev_value=0x%x curr_value=0x%x", + __print_symbolic(__entry->action, + { PM_QOS_ADD_REQ, "ADD_REQ" }, + { PM_QOS_UPDATE_REQ, "UPDATE_REQ" }, + { PM_QOS_REMOVE_REQ, "REMOVE_REQ" }), + __entry->prev_value, __entry->curr_value) +); #endif /* _TRACE_POWER_H */ /* This part must be outside protection */ -- cgit v1.2.3 From ae8822b842e229fa4459fca2d979b630d812311d Mon Sep 17 00:00:00 2001 From: Sahara Date: Fri, 21 Jun 2013 11:12:29 +0900 Subject: PM / QoS: Add pm_qos_request tracepoints Adds tracepoints to pm_qos_add_request, pm_qos_update_request, pm_qos_remove_request, and pm_qos_update_request_timeout. It's useful for checking pm_qos_class, value, and timeout_us. Signed-off-by: Sahara Signed-off-by: Rafael J. Wysocki --- include/trace/events/power.h | 71 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 71 insertions(+) (limited to 'include') diff --git a/include/trace/events/power.h b/include/trace/events/power.h index f1e73bd04beb..6411f924afb1 100644 --- a/include/trace/events/power.h +++ b/include/trace/events/power.h @@ -182,6 +182,77 @@ DEFINE_EVENT(power_domain, power_domain_target, /* * The pm qos events are used for pm qos update */ +DECLARE_EVENT_CLASS(pm_qos_request, + + TP_PROTO(int pm_qos_class, s32 value), + + TP_ARGS(pm_qos_class, value), + + TP_STRUCT__entry( + __field( int, pm_qos_class ) + __field( s32, value ) + ), + + TP_fast_assign( + __entry->pm_qos_class = pm_qos_class; + __entry->value = value; + ), + + TP_printk("pm_qos_class=%s value=%d", + __print_symbolic(__entry->pm_qos_class, + { PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }, + { PM_QOS_NETWORK_LATENCY, "NETWORK_LATENCY" }, + { PM_QOS_NETWORK_THROUGHPUT, "NETWORK_THROUGHPUT" }), + __entry->value) +); + +DEFINE_EVENT(pm_qos_request, pm_qos_add_request, + + TP_PROTO(int pm_qos_class, s32 value), + + TP_ARGS(pm_qos_class, value) +); + +DEFINE_EVENT(pm_qos_request, pm_qos_update_request, + + TP_PROTO(int pm_qos_class, s32 value), + + TP_ARGS(pm_qos_class, value) +); + +DEFINE_EVENT(pm_qos_request, pm_qos_remove_request, + + TP_PROTO(int pm_qos_class, s32 value), + + TP_ARGS(pm_qos_class, value) +); + +TRACE_EVENT(pm_qos_update_request_timeout, + + TP_PROTO(int pm_qos_class, s32 value, unsigned long timeout_us), + + TP_ARGS(pm_qos_class, value, timeout_us), + + TP_STRUCT__entry( + __field( int, pm_qos_class ) + __field( s32, value ) + __field( unsigned long, timeout_us ) + ), + + TP_fast_assign( + __entry->pm_qos_class = pm_qos_class; + __entry->value = value; + __entry->timeout_us = timeout_us; + ), + + TP_printk("pm_qos_class=%s value=%d, timeout_us=%ld", + __print_symbolic(__entry->pm_qos_class, + { PM_QOS_CPU_DMA_LATENCY, "CPU_DMA_LATENCY" }, + { PM_QOS_NETWORK_LATENCY, "NETWORK_LATENCY" }, + { PM_QOS_NETWORK_THROUGHPUT, "NETWORK_THROUGHPUT" }), + __entry->value, __entry->timeout_us) +); + DECLARE_EVENT_CLASS(pm_qos_update, TP_PROTO(enum pm_qos_req_action action, int prev_value, int curr_value), -- cgit v1.2.3 From 96d9d0b5dc17e80cefbd7c5be15a5072d33513f8 Mon Sep 17 00:00:00 2001 From: Sahara Date: Fri, 21 Jun 2013 11:12:30 +0900 Subject: PM / QoS: Add dev_pm_qos_request tracepoints Adds tracepoints to dev_pm_qos_add_request, dev_pm_qos_update_request, and dev_pm_qos_remove_request. It's useful for checking device name, dev_pm_qos_request_type, and value. Signed-off-by: Sahara Signed-off-by: Rafael J. Wysocki --- include/trace/events/power.h | 51 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) (limited to 'include') diff --git a/include/trace/events/power.h b/include/trace/events/power.h index 6411f924afb1..8e42410bd159 100644 --- a/include/trace/events/power.h +++ b/include/trace/events/power.h @@ -299,6 +299,57 @@ DEFINE_EVENT_PRINT(pm_qos_update, pm_qos_update_flags, { PM_QOS_REMOVE_REQ, "REMOVE_REQ" }), __entry->prev_value, __entry->curr_value) ); + +DECLARE_EVENT_CLASS(dev_pm_qos_request, + + TP_PROTO(const char *name, enum dev_pm_qos_req_type type, + s32 new_value), + + TP_ARGS(name, type, new_value), + + TP_STRUCT__entry( + __string( name, name ) + __field( enum dev_pm_qos_req_type, type ) + __field( s32, new_value ) + ), + + TP_fast_assign( + __assign_str(name, name); + __entry->type = type; + __entry->new_value = new_value; + ), + + TP_printk("device=%s type=%s new_value=%d", + __get_str(name), + __print_symbolic(__entry->type, + { DEV_PM_QOS_LATENCY, "DEV_PM_QOS_LATENCY" }, + { DEV_PM_QOS_FLAGS, "DEV_PM_QOS_FLAGS" }), + __entry->new_value) +); + +DEFINE_EVENT(dev_pm_qos_request, dev_pm_qos_add_request, + + TP_PROTO(const char *name, enum dev_pm_qos_req_type type, + s32 new_value), + + TP_ARGS(name, type, new_value) +); + +DEFINE_EVENT(dev_pm_qos_request, dev_pm_qos_update_request, + + TP_PROTO(const char *name, enum dev_pm_qos_req_type type, + s32 new_value), + + TP_ARGS(name, type, new_value) +); + +DEFINE_EVENT(dev_pm_qos_request, dev_pm_qos_remove_request, + + TP_PROTO(const char *name, enum dev_pm_qos_req_type type, + s32 new_value), + + TP_ARGS(name, type, new_value) +); #endif /* _TRACE_POWER_H */ /* This part must be outside protection */ -- cgit v1.2.3