From 2f0aea9363609433b38ab13f0f86f38372668c68 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 4 Mar 2014 11:00:26 +0800 Subject: cpufreq: suspend governors on system suspend/hibernate This patch adds cpufreq suspend/resume calls to dpm_{suspend|resume}() for handling suspend/resume of cpufreq governors. Lan Tianyu (Intel) & Jinhyuk Choi (Broadcom) found an issue where the tunables configuration for clusters/sockets with non-boot CPUs was lost after system suspend/resume, as we were notifying governors with CPUFREQ_GOV_POLICY_EXIT on removal of the last CPU for that policy which caused the tunables memory to be freed. This is fixed by preventing any governor operations from being carried out between the device suspend and device resume stages of system suspend and resume, respectively. We could have added these callbacks at dpm_{suspend|resume}_noirq() level, but there is an additional problem that the majority of I/O devices is already suspended at that point and if cpufreq drivers want to change the frequency before suspending, then that not be possible on some platforms (which depend on peripherals like i2c, regulators, etc). Reported-and-tested-by: Lan Tianyu Reported-by: Jinhyuk Choi Signed-off-by: Viresh Kumar [rjw: Changelog] Signed-off-by: Rafael J. Wysocki --- include/linux/cpufreq.h | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'include/linux') diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 4d89e0e6f9cc..94ed907c6999 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -296,6 +296,14 @@ cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy) policy->cpuinfo.max_freq); } +#ifdef CONFIG_CPU_FREQ +void cpufreq_suspend(void); +void cpufreq_resume(void); +#else +static inline void cpufreq_suspend(void) {} +static inline void cpufreq_resume(void) {} +#endif + /********************************************************************* * CPUFREQ NOTIFIER INTERFACE * *********************************************************************/ -- cgit v1.2.3 From e28867eab7c0a60cddf0cb59f9f6cbbd9561425d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 4 Mar 2014 11:00:27 +0800 Subject: cpufreq: Implement cpufreq_generic_suspend() Multiple platforms need to set CPUs to a particular frequency before suspending the system, so provide a common infrastructure for them. Those platforms only need to point their ->suspend callback pointers to the generic routine. Tested-by: Stephen Warren Signed-off-by: Viresh Kumar [rjw: Changelog] Signed-off-by: Rafael J. Wysocki --- include/linux/cpufreq.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'include/linux') diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 94ed907c6999..325bab04271b 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -74,6 +74,8 @@ struct cpufreq_policy { unsigned int max; /* in kHz */ unsigned int cur; /* in kHz, only needed if cpufreq * governors are used */ + unsigned int suspend_freq; /* freq to set during suspend */ + unsigned int policy; /* see above */ struct cpufreq_governor *governor; /* see below */ void *governor_data; @@ -299,6 +301,7 @@ cpufreq_verify_within_cpu_limits(struct cpufreq_policy *policy) #ifdef CONFIG_CPU_FREQ void cpufreq_suspend(void); void cpufreq_resume(void); +int cpufreq_generic_suspend(struct cpufreq_policy *policy); #else static inline void cpufreq_suspend(void) {} static inline void cpufreq_resume(void) {} -- cgit v1.2.3 From e0b3165ba521c6824b3e9f563f38a701dfa2d8e6 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 10 Mar 2014 14:53:33 +0530 Subject: cpufreq: add 'freq_table' in struct cpufreq_policy freq table is not per CPU but per policy, so it makes more sense to keep it within struct cpufreq_policy instead of a per-cpu variable. This patch does it. Over that, there is no need to set policy->freq_table to NULL in ->exit(), as policy structure is going to be freed soon. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- include/linux/cpufreq.h | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 325bab04271b..79341350f498 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -85,6 +85,7 @@ struct cpufreq_policy { * called, but you're in IRQ context */ struct cpufreq_real_policy user_policy; + struct cpufreq_frequency_table *freq_table; struct list_head policy_list; struct kobject kobj; @@ -474,7 +475,6 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, int cpufreq_frequency_table_get_index(struct cpufreq_policy *policy, unsigned int freq); -void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy); ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf); #ifdef CONFIG_CPU_FREQ @@ -501,9 +501,6 @@ struct cpufreq_frequency_table *cpufreq_frequency_get_table(unsigned int cpu); /* the following are really really optional */ extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs; extern struct freq_attr *cpufreq_generic_attr[]; -void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, - unsigned int cpu); -void cpufreq_frequency_table_put_attr(unsigned int cpu); int cpufreq_table_validate_and_show(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table); @@ -513,7 +510,6 @@ int cpufreq_generic_init(struct cpufreq_policy *policy, unsigned int transition_latency); static inline int cpufreq_generic_exit(struct cpufreq_policy *policy) { - cpufreq_frequency_table_put_attr(policy->cpu); return 0; } -- cgit v1.2.3 From 979d86fac5e6dbf5c939e9a2a9fe294c9e05e42f Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Mon, 10 Mar 2014 14:53:34 +0530 Subject: cpufreq: Remove cpufreq_generic_exit() cpufreq_generic_exit() is empty now and can be deleted. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- include/linux/cpufreq.h | 5 ----- 1 file changed, 5 deletions(-) (limited to 'include/linux') diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 79341350f498..31c431e150a7 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -508,9 +508,4 @@ unsigned int cpufreq_generic_get(unsigned int cpu); int cpufreq_generic_init(struct cpufreq_policy *policy, struct cpufreq_frequency_table *table, unsigned int transition_latency); -static inline int cpufreq_generic_exit(struct cpufreq_policy *policy) -{ - return 0; -} - #endif /* _LINUX_CPUFREQ_H */ -- cgit v1.2.3 From 0b443ead714f0cba797a7f2476dd756f22b5421e Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 19 Mar 2014 11:24:58 +0530 Subject: cpufreq: remove unused notifier: CPUFREQ_{SUSPENDCHANGE|RESUMECHANGE} Two cpufreq notifiers CPUFREQ_RESUMECHANGE and CPUFREQ_SUSPENDCHANGE have not been used for some time, so remove them to clean up code a bit. Signed-off-by: Viresh Kumar Reviewed-by: Srivatsa S. Bhat [rjw: Changelog] Signed-off-by: Rafael J. Wysocki --- include/linux/cpufreq.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'include/linux') diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 31c431e150a7..70929bcf1a9d 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -318,8 +318,6 @@ static inline void cpufreq_resume(void) {} /* Transition notifiers */ #define CPUFREQ_PRECHANGE (0) #define CPUFREQ_POSTCHANGE (1) -#define CPUFREQ_RESUMECHANGE (8) -#define CPUFREQ_SUSPENDCHANGE (9) /* Policy Notifiers */ #define CPUFREQ_ADJUST (0) -- cgit v1.2.3 From 367dc4aa932bfb33a3189064d33f7890a8ec1ca8 Mon Sep 17 00:00:00 2001 From: Dirk Brandewie Date: Wed, 19 Mar 2014 08:45:53 -0700 Subject: cpufreq: Add stop CPU callback to cpufreq_driver interface This callback allows the driver to do clean up before the CPU is completely down and its state cannot be modified. This is used by the intel_pstate driver to reduce the requested P state prior to the core going away. This is required because the requested P state of the offline core is used to select the package P state. This effectively sets the floor package P state to the requested P state on the offline core. Signed-off-by: Dirk Brandewie [rjw: Minor modifications] Signed-off-by: Rafael J. Wysocki --- include/linux/cpufreq.h | 1 + 1 file changed, 1 insertion(+) (limited to 'include/linux') diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 70929bcf1a9d..2d2e62c8666a 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -227,6 +227,7 @@ struct cpufreq_driver { int (*bios_limit) (int cpu, unsigned int *limit); int (*exit) (struct cpufreq_policy *policy); + void (*stop_cpu) (struct cpufreq_policy *policy); int (*suspend) (struct cpufreq_policy *policy); int (*resume) (struct cpufreq_policy *policy); struct freq_attr **attr; -- cgit v1.2.3