From dfa5bb622555d9da0df21b50f46ebdeef390041b Mon Sep 17 00:00:00 2001 From: Stratos Karafotis Date: Wed, 5 Jun 2013 19:01:25 +0300 Subject: [PATCH 01/25] cpufreq: ondemand: Change the calculation of target frequency The ondemand governor calculates load in terms of frequency and increases it only if load_freq is greater than up_threshold multiplied by the current or average frequency. This appears to produce oscillations of frequency between min and max because, for example, a relatively small load can easily saturate minimum frequency and lead the CPU to the max. Then, it will decrease back to the min due to small load_freq. Change the calculation method of load and target frequency on the basis of the following two observations: - Load computation should not depend on the current or average measured frequency. For example, absolute load of 80% at 100MHz is not necessarily equivalent to 8% at 1000MHz in the next sampling interval. - It should be possible to increase the target frequency to any value present in the frequency table proportional to the absolute load, rather than to the max only, so that: Target frequency = C * load where we take C = policy->cpuinfo.max_freq / 100. Tested on Intel i7-3770 CPU @ 3.40GHz and on Quad core 1500MHz Krait. Phoronix benchmark of Linux Kernel Compilation 3.1 test shows an increase ~1.5% in performance. cpufreq_stats (time_in_state) shows that middle frequencies are used more, with this patch. Highest and lowest frequencies were used less by ~9%. [rjw: We have run multiple other tests on kernels with this change applied and in the vast majority of cases it turns out that the resulting performance improvement also leads to reduced consumption of energy. The change is additionally justified by the overall simplification of the code in question.] Signed-off-by: Stratos Karafotis Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq_governor.c | 10 +------- drivers/cpufreq/cpufreq_governor.h | 1 - drivers/cpufreq/cpufreq_ondemand.c | 39 ++++++------------------------ 3 files changed, 8 insertions(+), 42 deletions(-) diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 7b839a8db2a7..7409dbd1d897 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -53,7 +53,7 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu) policy = cdbs->cur_policy; - /* Get Absolute Load (in terms of freq for ondemand gov) */ + /* Get Absolute Load */ for_each_cpu(j, policy->cpus) { struct cpu_dbs_common_info *j_cdbs; u64 cur_wall_time, cur_idle_time; @@ -104,14 +104,6 @@ void dbs_check_cpu(struct dbs_data *dbs_data, int cpu) load = 100 * (wall_time - idle_time) / wall_time; - if (dbs_data->cdata->governor == GOV_ONDEMAND) { - int freq_avg = __cpufreq_driver_getavg(policy, j); - if (freq_avg <= 0) - freq_avg = policy->cur; - - load *= freq_avg; - } - if (load > max_load) max_load = load; } diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index 6663ec3b3056..0e0dd4c82020 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h @@ -169,7 +169,6 @@ struct od_dbs_tuners { unsigned int sampling_rate; unsigned int sampling_down_factor; unsigned int up_threshold; - unsigned int adj_up_threshold; unsigned int powersave_bias; unsigned int io_is_busy; }; diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 93eb5cbcc1f6..a3c5574f9b3a 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -29,11 +29,9 @@ #include "cpufreq_governor.h" /* On-demand governor macros */ -#define DEF_FREQUENCY_DOWN_DIFFERENTIAL (10) #define DEF_FREQUENCY_UP_THRESHOLD (80) #define DEF_SAMPLING_DOWN_FACTOR (1) #define MAX_SAMPLING_DOWN_FACTOR (100000) -#define MICRO_FREQUENCY_DOWN_DIFFERENTIAL (3) #define MICRO_FREQUENCY_UP_THRESHOLD (95) #define MICRO_FREQUENCY_MIN_SAMPLE_RATE (10000) #define MIN_FREQUENCY_UP_THRESHOLD (11) @@ -161,14 +159,10 @@ static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq) /* * Every sampling_rate, we check, if current idle time is less than 20% - * (default), then we try to increase frequency. Every sampling_rate, we look - * for the lowest frequency which can sustain the load while keeping idle time - * over 30%. If such a frequency exist, we try to decrease to this frequency. - * - * Any frequency increase takes it to the maximum frequency. Frequency reduction - * happens at minimum steps of 5% (default) of current frequency + * (default), then we try to increase frequency. Else, we adjust the frequency + * proportional to load. */ -static void od_check_cpu(int cpu, unsigned int load_freq) +static void od_check_cpu(int cpu, unsigned int load) { struct od_cpu_dbs_info_s *dbs_info = &per_cpu(od_cpu_dbs_info, cpu); struct cpufreq_policy *policy = dbs_info->cdbs.cur_policy; @@ -178,29 +172,17 @@ static void od_check_cpu(int cpu, unsigned int load_freq) dbs_info->freq_lo = 0; /* Check for frequency increase */ - if (load_freq > od_tuners->up_threshold * policy->cur) { + if (load > od_tuners->up_threshold) { /* If switching to max speed, apply sampling_down_factor */ if (policy->cur < policy->max) dbs_info->rate_mult = od_tuners->sampling_down_factor; dbs_freq_increase(policy, policy->max); return; - } - - /* Check for frequency decrease */ - /* if we cannot reduce the frequency anymore, break out early */ - if (policy->cur == policy->min) - return; - - /* - * The optimal frequency is the frequency that is the lowest that can - * support the current CPU usage without triggering the up policy. To be - * safe, we focus 10 points under the threshold. - */ - if (load_freq < od_tuners->adj_up_threshold - * policy->cur) { + } else { + /* Calculate the next frequency proportional to load */ unsigned int freq_next; - freq_next = load_freq / od_tuners->adj_up_threshold; + freq_next = load * policy->cpuinfo.max_freq / 100; /* No longer fully busy, reset rate_mult */ dbs_info->rate_mult = 1; @@ -374,9 +356,6 @@ static ssize_t store_up_threshold(struct dbs_data *dbs_data, const char *buf, input < MIN_FREQUENCY_UP_THRESHOLD) { return -EINVAL; } - /* Calculate the new adj_up_threshold */ - od_tuners->adj_up_threshold += input; - od_tuners->adj_up_threshold -= od_tuners->up_threshold; od_tuners->up_threshold = input; return count; @@ -525,8 +504,6 @@ static int od_init(struct dbs_data *dbs_data) if (idle_time != -1ULL) { /* Idle micro accounting is supported. Use finer thresholds */ tuners->up_threshold = MICRO_FREQUENCY_UP_THRESHOLD; - tuners->adj_up_threshold = MICRO_FREQUENCY_UP_THRESHOLD - - MICRO_FREQUENCY_DOWN_DIFFERENTIAL; /* * In nohz/micro accounting case we set the minimum frequency * not depending on HZ, but fixed (very low). The deferred @@ -535,8 +512,6 @@ static int od_init(struct dbs_data *dbs_data) dbs_data->min_sampling_rate = MICRO_FREQUENCY_MIN_SAMPLE_RATE; } else { tuners->up_threshold = DEF_FREQUENCY_UP_THRESHOLD; - tuners->adj_up_threshold = DEF_FREQUENCY_UP_THRESHOLD - - DEF_FREQUENCY_DOWN_DIFFERENTIAL; /* For correct statistics, we need 10 ticks for each measure */ dbs_data->min_sampling_rate = MIN_SAMPLING_RATE_RATIO * From 61c63e5ed3b9c472899d7152e961f2ffaafcf5a0 Mon Sep 17 00:00:00 2001 From: Stratos Karafotis Date: Wed, 5 Jun 2013 19:01:42 +0300 Subject: [PATCH 02/25] cpufreq: Remove unused APERF/MPERF support The target frequency calculation method in the ondemand governor has changed and it is now independent of the measured average frequency. Consequently, the APERF/MPERF support in cpufreq is not used any more, so drop it. [rjw: Changelog] Signed-off-by: Stratos Karafotis Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- arch/x86/include/asm/processor.h | 29 ------------------ drivers/cpufreq/Makefile | 2 +- drivers/cpufreq/acpi-cpufreq.c | 5 ---- drivers/cpufreq/mperf.c | 51 -------------------------------- drivers/cpufreq/mperf.h | 9 ------ 5 files changed, 1 insertion(+), 95 deletions(-) delete mode 100644 drivers/cpufreq/mperf.c delete mode 100644 drivers/cpufreq/mperf.h diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 24cf5aefb704..4f4a3d98c170 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -942,35 +942,6 @@ extern int set_tsc_mode(unsigned int val); extern u16 amd_get_nb_id(int cpu); -struct aperfmperf { - u64 aperf, mperf; -}; - -static inline void get_aperfmperf(struct aperfmperf *am) -{ - WARN_ON_ONCE(!boot_cpu_has(X86_FEATURE_APERFMPERF)); - - rdmsrl(MSR_IA32_APERF, am->aperf); - rdmsrl(MSR_IA32_MPERF, am->mperf); -} - -#define APERFMPERF_SHIFT 10 - -static inline -unsigned long calc_aperfmperf_ratio(struct aperfmperf *old, - struct aperfmperf *new) -{ - u64 aperf = new->aperf - old->aperf; - u64 mperf = new->mperf - old->mperf; - unsigned long ratio = aperf; - - mperf >>= APERFMPERF_SHIFT; - if (mperf) - ratio = div64_u64(aperf, mperf); - - return ratio; -} - extern unsigned long arch_align_stack(unsigned long sp); extern void free_init_pages(char *what, unsigned long begin, unsigned long end); diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile index d345b5a7aa71..ad5866c2ada0 100644 --- a/drivers/cpufreq/Makefile +++ b/drivers/cpufreq/Makefile @@ -23,7 +23,7 @@ obj-$(CONFIG_GENERIC_CPUFREQ_CPU0) += cpufreq-cpu0.o # powernow-k8 can load then. ACPI is preferred to all other hardware-specific drivers. # speedstep-* is preferred over p4-clockmod. -obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o mperf.o +obj-$(CONFIG_X86_ACPI_CPUFREQ) += acpi-cpufreq.o obj-$(CONFIG_X86_POWERNOW_K8) += powernow-k8.o obj-$(CONFIG_X86_PCC_CPUFREQ) += pcc-cpufreq.o obj-$(CONFIG_X86_POWERNOW_K6) += powernow-k6.o diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 39264020b88a..e673670d2321 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -45,7 +45,6 @@ #include #include #include -#include "mperf.h" MODULE_AUTHOR("Paul Diefenbaugh, Dominik Brodowski"); MODULE_DESCRIPTION("ACPI Processor P-States Driver"); @@ -861,10 +860,6 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) /* notify BIOS that we exist */ acpi_processor_notify_smm(THIS_MODULE); - /* Check for APERF/MPERF support in hardware */ - if (boot_cpu_has(X86_FEATURE_APERFMPERF)) - acpi_cpufreq_driver.getavg = cpufreq_get_measured_perf; - pr_debug("CPU%u - ACPI performance management activated.\n", cpu); for (i = 0; i < perf->state_count; i++) pr_debug(" %cP%d: %d MHz, %d mW, %d uS\n", diff --git a/drivers/cpufreq/mperf.c b/drivers/cpufreq/mperf.c deleted file mode 100644 index 911e193018ae..000000000000 --- a/drivers/cpufreq/mperf.c +++ /dev/null @@ -1,51 +0,0 @@ -#include -#include -#include -#include -#include -#include - -#include "mperf.h" - -static DEFINE_PER_CPU(struct aperfmperf, acfreq_old_perf); - -/* Called via smp_call_function_single(), on the target CPU */ -static void read_measured_perf_ctrs(void *_cur) -{ - struct aperfmperf *am = _cur; - - get_aperfmperf(am); -} - -/* - * Return the measured active (C0) frequency on this CPU since last call - * to this function. - * Input: cpu number - * Return: Average CPU frequency in terms of max frequency (zero on error) - * - * We use IA32_MPERF and IA32_APERF MSRs to get the measured performance - * over a period of time, while CPU is in C0 state. - * IA32_MPERF counts at the rate of max advertised frequency - * IA32_APERF counts at the rate of actual CPU frequency - * Only IA32_APERF/IA32_MPERF ratio is architecturally defined and - * no meaning should be associated with absolute values of these MSRs. - */ -unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy, - unsigned int cpu) -{ - struct aperfmperf perf; - unsigned long ratio; - unsigned int retval; - - if (smp_call_function_single(cpu, read_measured_perf_ctrs, &perf, 1)) - return 0; - - ratio = calc_aperfmperf_ratio(&per_cpu(acfreq_old_perf, cpu), &perf); - per_cpu(acfreq_old_perf, cpu) = perf; - - retval = (policy->cpuinfo.max_freq * ratio) >> APERFMPERF_SHIFT; - - return retval; -} -EXPORT_SYMBOL_GPL(cpufreq_get_measured_perf); -MODULE_LICENSE("GPL"); diff --git a/drivers/cpufreq/mperf.h b/drivers/cpufreq/mperf.h deleted file mode 100644 index 5dbf2950dc22..000000000000 --- a/drivers/cpufreq/mperf.h +++ /dev/null @@ -1,9 +0,0 @@ -/* - * (c) 2010 Advanced Micro Devices, Inc. - * Your use of this code is subject to the terms and conditions of the - * GNU general public license version 2. See "COPYING" or - * http://www.gnu.org/licenses/gpl.html - */ - -unsigned int cpufreq_get_measured_perf(struct cpufreq_policy *policy, - unsigned int cpu); From cffe4e0e7413eb29fb8bd035c8b12b33a4b8522a Mon Sep 17 00:00:00 2001 From: Stratos Karafotis Date: Wed, 5 Jun 2013 19:01:50 +0300 Subject: [PATCH 03/25] cpufreq: Remove unused function __cpufreq_driver_getavg() The target frequency calculation method in the ondemand governor has changed and it is now independent of the measured average frequency. Consequently, the __cpufreq_driver_getavg() function and getavg member of struct cpufreq_driver are not used any more, so drop them. [rjw: Changelog] Signed-off-by: Stratos Karafotis Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 12 ------------ include/linux/cpufreq.h | 6 ------ 2 files changed, 18 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index a4ad7339588d..9a9d8ee9faec 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1593,18 +1593,6 @@ fail: } EXPORT_SYMBOL_GPL(cpufreq_driver_target); -int __cpufreq_driver_getavg(struct cpufreq_policy *policy, unsigned int cpu) -{ - if (cpufreq_disabled()) - return 0; - - if (!cpufreq_driver->getavg) - return 0; - - return cpufreq_driver->getavg(policy, cpu); -} -EXPORT_SYMBOL_GPL(__cpufreq_driver_getavg); - /* * when "event" is CPUFREQ_GOV_LIMITS */ diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 90d5a15120d5..e1fd215e16c9 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -216,10 +216,6 @@ extern int cpufreq_driver_target(struct cpufreq_policy *policy, extern int __cpufreq_driver_target(struct cpufreq_policy *policy, unsigned int target_freq, unsigned int relation); - -extern int __cpufreq_driver_getavg(struct cpufreq_policy *policy, - unsigned int cpu); - int cpufreq_register_governor(struct cpufreq_governor *governor); void cpufreq_unregister_governor(struct cpufreq_governor *governor); @@ -258,8 +254,6 @@ struct cpufreq_driver { unsigned int (*get) (unsigned int cpu); /* optional */ - unsigned int (*getavg) (struct cpufreq_policy *policy, - unsigned int cpu); int (*bios_limit) (int cpu, unsigned int *limit); int (*exit) (struct cpufreq_policy *policy); From 23d328994b548d6822b88fe7e1903652afc354e0 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 30 Jul 2013 04:23:56 +0530 Subject: [PATCH 04/25] cpufreq: Fix misplaced call to cpufreq_update_policy() The call to cpufreq_update_policy() is placed in the CPU hotplug callback of cpufreq_stats, which has a higher priority than the CPU hotplug callback of cpufreq-core. As a result, during CPU_ONLINE/CPU_ONLINE_FROZEN, we end up calling cpufreq_update_policy() *before* calling cpufreq_add_dev() ! And for uninitialized CPUs, it just returns silently, not doing anything. To add to that, cpufreq_stats is not even the right place to call cpufreq_update_policy() to begin with. The cpufreq core ought to handle this in its own callback, from an elegance/relevance perspective. So move the invocation of cpufreq_update_policy() to cpufreq_cpu_callback, and place it *after* cpufreq_add_dev(). Signed-off-by: Srivatsa S. Bhat Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 1 + drivers/cpufreq/cpufreq_stats.c | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index f0a5e2b0eb8a..5b317b0db902 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1945,6 +1945,7 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, case CPU_ONLINE: case CPU_ONLINE_FROZEN: cpufreq_add_dev(dev, NULL); + cpufreq_update_policy(cpu); break; case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE_FROZEN: diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index d37568c5ca9c..bc73be225be5 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -348,10 +348,6 @@ static int cpufreq_stat_cpu_callback(struct notifier_block *nfb, unsigned int cpu = (unsigned long)hcpu; switch (action) { - case CPU_ONLINE: - case CPU_ONLINE_FROZEN: - cpufreq_update_policy(cpu); - break; case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE_FROZEN: cpufreq_stats_free_sysfs(cpu); @@ -390,8 +386,6 @@ static int __init cpufreq_stats_init(void) return ret; register_hotcpu_notifier(&cpufreq_stat_cpu_notifier); - for_each_online_cpu(cpu) - cpufreq_update_policy(cpu); ret = cpufreq_register_notifier(¬ifier_trans_block, CPUFREQ_TRANSITION_NOTIFIER); From e9698cc5d2749c5b74e137f94a95d7e505b097e8 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 30 Jul 2013 04:24:11 +0530 Subject: [PATCH 05/25] cpufreq: Add helper to perform alloc/free of policy structure Separate out the allocation of the cpufreq policy structure (along with its error handling) to a helper function. This makes the code easier to read and also helps with some upcoming code reorganization. Signed-off-by: Srivatsa S. Bhat Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 49 +++++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 5b317b0db902..18e58c1bfd66 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -944,6 +944,37 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, } #endif +static struct cpufreq_policy *cpufreq_policy_alloc(void) +{ + struct cpufreq_policy *policy; + + policy = kzalloc(sizeof(*policy), GFP_KERNEL); + if (!policy) + return NULL; + + if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL)) + goto err_free_policy; + + if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) + goto err_free_cpumask; + + return policy; + +err_free_cpumask: + free_cpumask_var(policy->cpus); +err_free_policy: + kfree(policy); + + return NULL; +} + +static void cpufreq_policy_free(struct cpufreq_policy *policy) +{ + free_cpumask_var(policy->related_cpus); + free_cpumask_var(policy->cpus); + kfree(policy); +} + /** * cpufreq_add_dev - add a CPU device * @@ -997,16 +1028,10 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) goto module_out; } - policy = kzalloc(sizeof(struct cpufreq_policy), GFP_KERNEL); + policy = cpufreq_policy_alloc(); if (!policy) goto nomem_out; - if (!alloc_cpumask_var(&policy->cpus, GFP_KERNEL)) - goto err_free_policy; - - if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) - goto err_free_cpumask; - policy->cpu = cpu; policy->governor = CPUFREQ_DEFAULT_GOVERNOR; cpumask_copy(policy->cpus, cpumask_of(cpu)); @@ -1071,11 +1096,7 @@ err_out_unregister: err_set_policy_cpu: per_cpu(cpufreq_policy_cpu, cpu) = -1; - free_cpumask_var(policy->related_cpus); -err_free_cpumask: - free_cpumask_var(policy->cpus); -err_free_policy: - kfree(policy); + cpufreq_policy_free(policy); nomem_out: module_put(cpufreq_driver->owner); module_out: @@ -1199,9 +1220,7 @@ static int __cpufreq_remove_dev(struct device *dev, if (cpufreq_driver->exit) cpufreq_driver->exit(data); - free_cpumask_var(data->related_cpus); - free_cpumask_var(data->cpus); - kfree(data); + cpufreq_policy_free(data); } else { pr_debug("%s: removing link, cpu: %d\n", __func__, cpu); cpufreq_cpu_put(data); From e18f1682bce701ddcf88ba3651e07c7ee9b3ed60 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 30 Jul 2013 04:24:23 +0530 Subject: [PATCH 06/25] cpufreq: Extract non-interface related stuff from cpufreq_add_dev_interface cpufreq_add_dev_interface() includes the work of exposing the interface to the device, as well as a lot of unrelated stuff. Move the latter to cpufreq_add_dev(), where it is more appropriate. Signed-off-by: Srivatsa S. Bhat Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 43 +++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 17 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 18e58c1bfd66..f7c58c79217d 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -835,11 +835,8 @@ static int cpufreq_add_dev_interface(unsigned int cpu, struct cpufreq_policy *policy, struct device *dev) { - struct cpufreq_policy new_policy; struct freq_attr **drv_attr; - unsigned long flags; int ret = 0; - unsigned int j; /* prepare interface data */ ret = kobject_init_and_add(&policy->kobj, &ktype_cpufreq, @@ -871,17 +868,23 @@ static int cpufreq_add_dev_interface(unsigned int cpu, goto err_out_kobj_put; } - write_lock_irqsave(&cpufreq_driver_lock, flags); - for_each_cpu(j, policy->cpus) { - per_cpu(cpufreq_cpu_data, j) = policy; - per_cpu(cpufreq_policy_cpu, j) = policy->cpu; - } - write_unlock_irqrestore(&cpufreq_driver_lock, flags); - ret = cpufreq_add_dev_symlink(cpu, policy); if (ret) goto err_out_kobj_put; + return ret; + +err_out_kobj_put: + kobject_put(&policy->kobj); + wait_for_completion(&policy->kobj_unregister); + return ret; +} + +static void cpufreq_init_policy(struct cpufreq_policy *policy) +{ + struct cpufreq_policy new_policy; + int ret = 0; + memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); /* assure that the starting sequence is run in __cpufreq_set_policy */ policy->governor = NULL; @@ -896,12 +899,6 @@ static int cpufreq_add_dev_interface(unsigned int cpu, if (cpufreq_driver->exit) cpufreq_driver->exit(policy); } - return ret; - -err_out_kobj_put: - kobject_put(&policy->kobj); - wait_for_completion(&policy->kobj_unregister); - return ret; } #ifdef CONFIG_HOTPLUG_CPU @@ -1075,10 +1072,19 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) } #endif + write_lock_irqsave(&cpufreq_driver_lock, flags); + for_each_cpu(j, policy->cpus) { + per_cpu(cpufreq_cpu_data, j) = policy; + per_cpu(cpufreq_policy_cpu, j) = policy->cpu; + } + write_unlock_irqrestore(&cpufreq_driver_lock, flags); + ret = cpufreq_add_dev_interface(cpu, policy, dev); if (ret) goto err_out_unregister; + cpufreq_init_policy(policy); + kobject_uevent(&policy->kobj, KOBJ_ADD); module_put(cpufreq_driver->owner); pr_debug("initialization complete\n"); @@ -1087,8 +1093,11 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) err_out_unregister: write_lock_irqsave(&cpufreq_driver_lock, flags); - for_each_cpu(j, policy->cpus) + for_each_cpu(j, policy->cpus) { per_cpu(cpufreq_cpu_data, j) = NULL; + if (j != cpu) + per_cpu(cpufreq_policy_cpu, j) = -1; + } write_unlock_irqrestore(&cpufreq_driver_lock, flags); kobject_put(&policy->kobj); From f9ba680d23ea7e2fc31b4b7106a482d90ec62a24 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 30 Jul 2013 04:24:36 +0530 Subject: [PATCH 07/25] cpufreq: Extract the handover of policy cpu to a helper function During cpu offline, when the policy->cpu is going down, some other CPU present in the policy->cpus mask is nominated as the new policy->cpu. Extract this functionality from __cpufreq_remove_dev() and implement it in a helper function. This helps in upcoming code reorganization. Signed-off-by: Srivatsa S. Bhat Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 63 ++++++++++++++++++++++++--------------- 1 file changed, 39 insertions(+), 24 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index f7c58c79217d..0611ae48e767 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1129,6 +1129,38 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) CPUFREQ_UPDATE_POLICY_CPU, policy); } +static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *data, + unsigned int old_cpu) +{ + struct device *cpu_dev; + unsigned long flags; + int ret; + + /* first sibling now owns the new sysfs dir */ + cpu_dev = get_cpu_device(cpumask_first(data->cpus)); + sysfs_remove_link(&cpu_dev->kobj, "cpufreq"); + ret = kobject_move(&data->kobj, &cpu_dev->kobj); + if (ret) { + pr_err("%s: Failed to move kobj: %d", __func__, ret); + + WARN_ON(lock_policy_rwsem_write(old_cpu)); + cpumask_set_cpu(old_cpu, data->cpus); + + write_lock_irqsave(&cpufreq_driver_lock, flags); + per_cpu(cpufreq_cpu_data, old_cpu) = data; + write_unlock_irqrestore(&cpufreq_driver_lock, flags); + + unlock_policy_rwsem_write(old_cpu); + + ret = sysfs_create_link(&cpu_dev->kobj, &data->kobj, + "cpufreq"); + + return -EINVAL; + } + + return cpu_dev->id; +} + /** * __cpufreq_remove_dev - remove a CPU device * @@ -1139,12 +1171,12 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) { - unsigned int cpu = dev->id, ret, cpus; + unsigned int cpu = dev->id, cpus; + int new_cpu; unsigned long flags; struct cpufreq_policy *data; struct kobject *kobj; struct completion *cmp; - struct device *cpu_dev; pr_debug("%s: unregistering CPU %u\n", __func__, cpu); @@ -1179,32 +1211,15 @@ static int __cpufreq_remove_dev(struct device *dev, if (cpu != data->cpu) { sysfs_remove_link(&dev->kobj, "cpufreq"); } else if (cpus > 1) { - /* first sibling now owns the new sysfs dir */ - cpu_dev = get_cpu_device(cpumask_first(data->cpus)); - sysfs_remove_link(&cpu_dev->kobj, "cpufreq"); - ret = kobject_move(&data->kobj, &cpu_dev->kobj); - if (ret) { - pr_err("%s: Failed to move kobj: %d", __func__, ret); + new_cpu = cpufreq_nominate_new_policy_cpu(data, cpu); + if (new_cpu >= 0) { WARN_ON(lock_policy_rwsem_write(cpu)); - cpumask_set_cpu(cpu, data->cpus); - - write_lock_irqsave(&cpufreq_driver_lock, flags); - per_cpu(cpufreq_cpu_data, cpu) = data; - write_unlock_irqrestore(&cpufreq_driver_lock, flags); - + update_policy_cpu(data, new_cpu); unlock_policy_rwsem_write(cpu); - - ret = sysfs_create_link(&cpu_dev->kobj, &data->kobj, - "cpufreq"); - return -EINVAL; + pr_debug("%s: policy Kobject moved to cpu: %d " + "from: %d\n",__func__, new_cpu, cpu); } - - WARN_ON(lock_policy_rwsem_write(cpu)); - update_policy_cpu(data, cpu_dev->id); - unlock_policy_rwsem_write(cpu); - pr_debug("%s: policy Kobject moved to cpu: %d from: %d\n", - __func__, cpu_dev->id, cpu); } /* If cpu is last user of policy, free policy */ From a82fab292898f88ea9ca99dd10c1773dcada08b6 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 30 Jul 2013 04:24:49 +0530 Subject: [PATCH 08/25] cpufreq: Introduce a flag ('frozen') to separate full vs temporary init/teardown During suspend/resume we would like to do a light-weight init/teardown of CPUs in the cpufreq subsystem and preserve certain things such as sysfs files etc across suspend/resume transitions. Add a flag called 'frozen' to help distinguish the full init/teardown sequence from the light-weight one. Signed-off-by: Srivatsa S. Bhat Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 76 +++++++++++++++++++++++++-------------- 1 file changed, 49 insertions(+), 27 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 0611ae48e767..1d041aff4d48 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -903,7 +903,7 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy) #ifdef CONFIG_HOTPLUG_CPU static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, - struct device *dev) + struct device *dev, bool frozen) { struct cpufreq_policy *policy; int ret = 0, has_target = !!cpufreq_driver->target; @@ -931,13 +931,18 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); } - ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq"); - if (ret) { + /* Don't touch sysfs links during light-weight init */ + if (frozen) { + /* Drop the extra refcount that we took above */ cpufreq_cpu_put(policy); - return ret; + return 0; } - return 0; + ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq"); + if (ret) + cpufreq_cpu_put(policy); + + return ret; } #endif @@ -972,16 +977,8 @@ static void cpufreq_policy_free(struct cpufreq_policy *policy) kfree(policy); } -/** - * cpufreq_add_dev - add a CPU device - * - * Adds the cpufreq interface for a CPU device. - * - * The Oracle says: try running cpufreq registration/unregistration concurrently - * with with cpu hotplugging and all hell will break loose. Tried to clean this - * mess up, but more thorough testing is needed. - Mathieu - */ -static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) +static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, + bool frozen) { unsigned int j, cpu = dev->id; int ret = -ENOMEM; @@ -1013,7 +1010,8 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling); if (cp && cpumask_test_cpu(cpu, cp->related_cpus)) { read_unlock_irqrestore(&cpufreq_driver_lock, flags); - return cpufreq_add_policy_cpu(cpu, sibling, dev); + return cpufreq_add_policy_cpu(cpu, sibling, dev, + frozen); } } read_unlock_irqrestore(&cpufreq_driver_lock, flags); @@ -1079,9 +1077,11 @@ static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) } write_unlock_irqrestore(&cpufreq_driver_lock, flags); - ret = cpufreq_add_dev_interface(cpu, policy, dev); - if (ret) - goto err_out_unregister; + if (!frozen) { + ret = cpufreq_add_dev_interface(cpu, policy, dev); + if (ret) + goto err_out_unregister; + } cpufreq_init_policy(policy); @@ -1112,6 +1112,20 @@ module_out: return ret; } +/** + * cpufreq_add_dev - add a CPU device + * + * Adds the cpufreq interface for a CPU device. + * + * The Oracle says: try running cpufreq registration/unregistration concurrently + * with with cpu hotplugging and all hell will break loose. Tried to clean this + * mess up, but more thorough testing is needed. - Mathieu + */ +static int cpufreq_add_dev(struct device *dev, struct subsys_interface *sif) +{ + return __cpufreq_add_dev(dev, sif, false); +} + static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) { int j; @@ -1130,7 +1144,7 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) } static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *data, - unsigned int old_cpu) + unsigned int old_cpu, bool frozen) { struct device *cpu_dev; unsigned long flags; @@ -1138,6 +1152,11 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *data, /* first sibling now owns the new sysfs dir */ cpu_dev = get_cpu_device(cpumask_first(data->cpus)); + + /* Don't touch sysfs files during light-weight tear-down */ + if (frozen) + return cpu_dev->id; + sysfs_remove_link(&cpu_dev->kobj, "cpufreq"); ret = kobject_move(&data->kobj, &cpu_dev->kobj); if (ret) { @@ -1169,7 +1188,7 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *data, * This routine frees the rwsem before returning. */ static int __cpufreq_remove_dev(struct device *dev, - struct subsys_interface *sif) + struct subsys_interface *sif, bool frozen) { unsigned int cpu = dev->id, cpus; int new_cpu; @@ -1208,17 +1227,20 @@ static int __cpufreq_remove_dev(struct device *dev, cpumask_clear_cpu(cpu, data->cpus); unlock_policy_rwsem_write(cpu); - if (cpu != data->cpu) { + if (cpu != data->cpu && !frozen) { sysfs_remove_link(&dev->kobj, "cpufreq"); } else if (cpus > 1) { - new_cpu = cpufreq_nominate_new_policy_cpu(data, cpu); + new_cpu = cpufreq_nominate_new_policy_cpu(data, cpu, frozen); if (new_cpu >= 0) { WARN_ON(lock_policy_rwsem_write(cpu)); update_policy_cpu(data, new_cpu); unlock_policy_rwsem_write(cpu); - pr_debug("%s: policy Kobject moved to cpu: %d " - "from: %d\n",__func__, new_cpu, cpu); + + if (!frozen) { + pr_debug("%s: policy Kobject moved to cpu: %d " + "from: %d\n",__func__, new_cpu, cpu); + } } } @@ -1266,7 +1288,7 @@ static int cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif) if (cpu_is_offline(cpu)) return 0; - retval = __cpufreq_remove_dev(dev, sif); + retval = __cpufreq_remove_dev(dev, sif, false); return retval; } @@ -1992,7 +2014,7 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, break; case CPU_DOWN_PREPARE: case CPU_DOWN_PREPARE_FROZEN: - __cpufreq_remove_dev(dev, NULL); + __cpufreq_remove_dev(dev, NULL, false); break; case CPU_DOWN_FAILED: case CPU_DOWN_FAILED_FROZEN: From 8414809c6a1e8479e331e09254adb58b33a36d25 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 30 Jul 2013 04:25:10 +0530 Subject: [PATCH 09/25] cpufreq: Preserve policy structure across suspend/resume To perform light-weight cpu-init and teardown in the cpufreq subsystem during suspend/resume, we need to separate out the 2 main functionalities of the cpufreq CPU hotplug callbacks, as outlined below: 1. Init/tear-down of core cpufreq and CPU-specific components, which are critical to the correct functioning of the cpufreq subsystem. 2. Init/tear-down of cpufreq sysfs files during suspend/resume. The first part requires accurate updates to the policy structure such as its ->cpus and ->related_cpus masks, whereas the second part requires that the policy->kobj structure is not released or re-initialized during suspend/resume. To handle both these requirements, we need to allow updates to the policy structure throughout suspend/resume, but prevent the structure from getting freed up. Also, we must have a mechanism by which the cpu-up callbacks can restore the policy structure, without allocating things afresh. (That also helps avoid memory leaks). To achieve this, we use 2 schemes: a. Use a fallback per-cpu storage area for preserving the policy structures during suspend, so that they can be restored during resume appropriately. b. Use the 'frozen' flag to determine when to free or allocate the policy structure vs when to restore the policy from the saved fallback storage. Thus we can successfully preserve the structure across suspend/resume. Effectively, this helps us complete the separation of the 'light-weight' and the 'full' init/tear-down sequences in the cpufreq subsystem, so that this can be made use of in the suspend/resume scenario. Signed-off-by: Srivatsa S. Bhat Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 69 ++++++++++++++++++++++++++++++--------- 1 file changed, 53 insertions(+), 16 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 1d041aff4d48..e0ace3d9382c 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -44,6 +44,7 @@ */ static struct cpufreq_driver *cpufreq_driver; static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data); +static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data_fallback); static DEFINE_RWLOCK(cpufreq_driver_lock); static DEFINE_MUTEX(cpufreq_governor_lock); @@ -946,6 +947,20 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, } #endif +static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu) +{ + struct cpufreq_policy *policy; + unsigned long flags; + + write_lock_irqsave(&cpufreq_driver_lock, flags); + + policy = per_cpu(cpufreq_cpu_data_fallback, cpu); + + write_unlock_irqrestore(&cpufreq_driver_lock, flags); + + return policy; +} + static struct cpufreq_policy *cpufreq_policy_alloc(void) { struct cpufreq_policy *policy; @@ -1023,7 +1038,12 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, goto module_out; } - policy = cpufreq_policy_alloc(); + if (frozen) + /* Restore the saved policy when doing light-weight init */ + policy = cpufreq_policy_restore(cpu); + else + policy = cpufreq_policy_alloc(); + if (!policy) goto nomem_out; @@ -1204,6 +1224,10 @@ static int __cpufreq_remove_dev(struct device *dev, data = per_cpu(cpufreq_cpu_data, cpu); per_cpu(cpufreq_cpu_data, cpu) = NULL; + /* Save the policy somewhere when doing a light-weight tear-down */ + if (frozen) + per_cpu(cpufreq_cpu_data_fallback, cpu) = data; + write_unlock_irqrestore(&cpufreq_driver_lock, flags); if (!data) { @@ -1249,27 +1273,40 @@ static int __cpufreq_remove_dev(struct device *dev, if (cpufreq_driver->target) __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT); - lock_policy_rwsem_read(cpu); - kobj = &data->kobj; - cmp = &data->kobj_unregister; - unlock_policy_rwsem_read(cpu); - kobject_put(kobj); + if (!frozen) { + lock_policy_rwsem_read(cpu); + kobj = &data->kobj; + cmp = &data->kobj_unregister; + unlock_policy_rwsem_read(cpu); + kobject_put(kobj); - /* we need to make sure that the underlying kobj is actually - * not referenced anymore by anybody before we proceed with - * unloading. + /* + * We need to make sure that the underlying kobj is + * actually not referenced anymore by anybody before we + * proceed with unloading. + */ + pr_debug("waiting for dropping of refcount\n"); + wait_for_completion(cmp); + pr_debug("wait complete\n"); + } + + /* + * Perform the ->exit() even during light-weight tear-down, + * since this is a core component, and is essential for the + * subsequent light-weight ->init() to succeed. */ - pr_debug("waiting for dropping of refcount\n"); - wait_for_completion(cmp); - pr_debug("wait complete\n"); - if (cpufreq_driver->exit) cpufreq_driver->exit(data); - cpufreq_policy_free(data); + if (!frozen) + cpufreq_policy_free(data); } else { - pr_debug("%s: removing link, cpu: %d\n", __func__, cpu); - cpufreq_cpu_put(data); + + if (!frozen) { + pr_debug("%s: removing link, cpu: %d\n", __func__, cpu); + cpufreq_cpu_put(data); + } + if (cpufreq_driver->target) { __cpufreq_governor(data, CPUFREQ_GOV_START); __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); From 5302c3fb2e62f4ca5e43e060491ba299f58c5231 Mon Sep 17 00:00:00 2001 From: "Srivatsa S. Bhat" Date: Tue, 30 Jul 2013 04:25:25 +0530 Subject: [PATCH 10/25] cpufreq: Perform light-weight init/teardown during suspend/resume Now that we have the infrastructure to perform a light-weight init/tear-down, use that in the cpufreq CPU hotplug notifier when invoked from the suspend/resume path. This also ensures that the file permissions of the cpufreq sysfs files are preserved across suspend/resume, something which commit a66b2e (cpufreq: Preserve sysfs files across suspend/resume) originally intended to do, but had to be reverted due to other problems. Signed-off-by: Srivatsa S. Bhat Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 18 +++++++++++------- drivers/cpufreq/cpufreq_stats.c | 2 -- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index e0ace3d9382c..370abb66babc 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -2040,22 +2040,26 @@ static int cpufreq_cpu_callback(struct notifier_block *nfb, { unsigned int cpu = (unsigned long)hcpu; struct device *dev; + bool frozen = false; dev = get_cpu_device(cpu); if (dev) { - switch (action) { + + if (action & CPU_TASKS_FROZEN) + frozen = true; + + switch (action & ~CPU_TASKS_FROZEN) { case CPU_ONLINE: - case CPU_ONLINE_FROZEN: - cpufreq_add_dev(dev, NULL); + __cpufreq_add_dev(dev, NULL, frozen); cpufreq_update_policy(cpu); break; + case CPU_DOWN_PREPARE: - case CPU_DOWN_PREPARE_FROZEN: - __cpufreq_remove_dev(dev, NULL, false); + __cpufreq_remove_dev(dev, NULL, frozen); break; + case CPU_DOWN_FAILED: - case CPU_DOWN_FAILED_FROZEN: - cpufreq_add_dev(dev, NULL); + __cpufreq_add_dev(dev, NULL, frozen); break; } } diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index bc73be225be5..cb3841355454 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -349,11 +349,9 @@ static int cpufreq_stat_cpu_callback(struct notifier_block *nfb, switch (action) { case CPU_DOWN_PREPARE: - case CPU_DOWN_PREPARE_FROZEN: cpufreq_stats_free_sysfs(cpu); break; case CPU_DEAD: - case CPU_DEAD_FROZEN: cpufreq_stats_free_table(cpu); break; } From e8fdde1011ea45792e60f14f620b01f78cb0d34d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 31 Jul 2013 14:31:33 +0200 Subject: [PATCH 11/25] cpufreq: Remove extra variables from cpufreq_add_dev_symlink() We call cpufreq_cpu_get() in cpufreq_add_dev_symlink() to increase usage refcount of policy, but not to get a policy for the given CPU. So, we don't really need to capture the return value of this routine. We can simply use policy passed as an argument to cpufreq_add_dev_symlink(). Moreover debug print is rewritten to make it more clear. [rjw: Changelog] Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 370abb66babc..b6154ca1f896 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -813,19 +813,18 @@ static int cpufreq_add_dev_symlink(unsigned int cpu, int ret = 0; for_each_cpu(j, policy->cpus) { - struct cpufreq_policy *managed_policy; struct device *cpu_dev; if (j == cpu) continue; - pr_debug("CPU %u already managed, adding link\n", j); - managed_policy = cpufreq_cpu_get(cpu); + pr_debug("Adding link for CPU: %u\n", j); + cpufreq_cpu_get(cpu); cpu_dev = get_cpu_device(j); ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj, "cpufreq"); if (ret) { - cpufreq_cpu_put(managed_policy); + cpufreq_cpu_put(policy); return ret; } } From 308b60e71541518f3fe97171b4daf71adc607f3d Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Wed, 31 Jul 2013 14:35:14 +0200 Subject: [PATCH 12/25] cpufreq: Don't pass CPU to cpufreq_add_dev_{symlink|interface}() Pointer to struct cpufreq_policy is already passed to these routines and we don't need to send policy->cpu to them as well. So, get rid of this extra argument and use policy->cpu everywhere. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index b6154ca1f896..576b312645a5 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -806,8 +806,7 @@ void cpufreq_sysfs_remove_file(const struct attribute *attr) EXPORT_SYMBOL(cpufreq_sysfs_remove_file); /* symlink affected CPUs */ -static int cpufreq_add_dev_symlink(unsigned int cpu, - struct cpufreq_policy *policy) +static int cpufreq_add_dev_symlink(struct cpufreq_policy *policy) { unsigned int j; int ret = 0; @@ -815,11 +814,11 @@ static int cpufreq_add_dev_symlink(unsigned int cpu, for_each_cpu(j, policy->cpus) { struct device *cpu_dev; - if (j == cpu) + if (j == policy->cpu) continue; pr_debug("Adding link for CPU: %u\n", j); - cpufreq_cpu_get(cpu); + cpufreq_cpu_get(policy->cpu); cpu_dev = get_cpu_device(j); ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj, "cpufreq"); @@ -831,8 +830,7 @@ static int cpufreq_add_dev_symlink(unsigned int cpu, return ret; } -static int cpufreq_add_dev_interface(unsigned int cpu, - struct cpufreq_policy *policy, +static int cpufreq_add_dev_interface(struct cpufreq_policy *policy, struct device *dev) { struct freq_attr **drv_attr; @@ -868,7 +866,7 @@ static int cpufreq_add_dev_interface(unsigned int cpu, goto err_out_kobj_put; } - ret = cpufreq_add_dev_symlink(cpu, policy); + ret = cpufreq_add_dev_symlink(policy); if (ret) goto err_out_kobj_put; @@ -1097,7 +1095,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, write_unlock_irqrestore(&cpufreq_driver_lock, flags); if (!frozen) { - ret = cpufreq_add_dev_interface(cpu, policy, dev); + ret = cpufreq_add_dev_interface(policy, dev); if (ret) goto err_out_unregister; } From 71c3461ef7c67024792d283b88630245a6c169ba Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 4 Aug 2013 01:19:34 +0200 Subject: [PATCH 13/25] cpufreq: Do not hold driver module references for additional policy CPUs The cpufreq core is a little inconsistent in the way it uses the driver module refcount. Namely, if __cpufreq_add_dev() is called for a CPU that doesn't share the policy object with any other CPUs, the driver module refcount it grabs to start with will be dropped by it before returning and will be equal to whatever it had been before that function was invoked. However, if the given CPU does share the policy object with other CPUs, either cpufreq_add_policy_cpu() is called to link the new CPU to the existing policy, or cpufreq_add_dev_symlink() is used to link the other CPUs sharing the policy with it to the just created policy object. In that case, because both cpufreq_add_policy_cpu() and cpufreq_add_dev_symlink() call cpufreq_cpu_get() for the given policy (the latter possibly many times) without the balancing cpufreq_cpu_put() (unless there is an error), the driver module refcount will be left by __cpufreq_add_dev() with a nonzero value (different from the initial one). To remove that inconsistency make cpufreq_add_policy_cpu() execute cpufreq_cpu_put() for the given policy before returning, which decrements the driver module refcount so that it will be equal to its initial value after __cpufreq_add_dev() returns. Also remove the cpufreq_cpu_get() call from cpufreq_add_dev_symlink(), since both the policy refcount and the driver module refcount are nonzero when it is called and they don't need to be bumped up by it. Accordingly, drop the cpufreq_cpu_put() from __cpufreq_remove_dev(), since it is only necessary to balance the cpufreq_cpu_get() called by cpufreq_add_policy_cpu() or cpufreq_add_dev_symlink(). Signed-off-by: Rafael J. Wysocki Reviewed-by: Srivatsa S. Bhat Acked-by: Viresh Kumar --- drivers/cpufreq/cpufreq.c | 28 +++++++--------------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 576b312645a5..c8b2ca0f44ae 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -818,14 +818,11 @@ static int cpufreq_add_dev_symlink(struct cpufreq_policy *policy) continue; pr_debug("Adding link for CPU: %u\n", j); - cpufreq_cpu_get(policy->cpu); cpu_dev = get_cpu_device(j); ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj, "cpufreq"); - if (ret) { - cpufreq_cpu_put(policy); - return ret; - } + if (ret) + break; } return ret; } @@ -908,7 +905,8 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, unsigned long flags; policy = cpufreq_cpu_get(sibling); - WARN_ON(!policy); + if (WARN_ON_ONCE(!policy)) + return -ENODATA; if (has_target) __cpufreq_governor(policy, CPUFREQ_GOV_STOP); @@ -930,16 +928,10 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, } /* Don't touch sysfs links during light-weight init */ - if (frozen) { - /* Drop the extra refcount that we took above */ - cpufreq_cpu_put(policy); - return 0; - } - - ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq"); - if (ret) - cpufreq_cpu_put(policy); + if (!frozen) + ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq"); + cpufreq_cpu_put(policy); return ret; } #endif @@ -1298,12 +1290,6 @@ static int __cpufreq_remove_dev(struct device *dev, if (!frozen) cpufreq_policy_free(data); } else { - - if (!frozen) { - pr_debug("%s: removing link, cpu: %d\n", __func__, cpu); - cpufreq_cpu_put(data); - } - if (cpufreq_driver->target) { __cpufreq_governor(data, CPUFREQ_GOV_START); __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); From 10659ab7b50e963429f1a681882404ca37aa584c Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Sun, 4 Aug 2013 01:19:41 +0200 Subject: [PATCH 14/25] cpufreq: Avoid double kobject_put() for the same kobject in error code path The only case triggering a jump to the err_out_unregister label in __cpufreq_add_dev() is when cpufreq_add_dev_interface() fails. However, if cpufreq_add_dev_interface() fails, it calls kobject_put() for the policy kobject in its error code path and since that causes the kobject's refcount to become 0, the additional kobject_put() for the same kobject under err_out_unregister and the wait_for_completion() following it are pointless, so drop them. Signed-off-by: Rafael J. Wysocki Reviewed-by: Srivatsa S. Bhat Acked-by: Viresh Kumar --- drivers/cpufreq/cpufreq.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index c8b2ca0f44ae..924d3f5df26d 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1109,9 +1109,6 @@ err_out_unregister: } write_unlock_irqrestore(&cpufreq_driver_lock, flags); - kobject_put(&policy->kobj); - wait_for_completion(&policy->kobj_unregister); - err_set_policy_cpu: per_cpu(cpufreq_policy_cpu, cpu) = -1; cpufreq_policy_free(policy); From d8d3b4711297e101bbad826474013edbe342c333 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Sun, 4 Aug 2013 01:20:07 +0200 Subject: [PATCH 15/25] cpufreq: Pass policy to cpufreq_add_policy_cpu() The caller of cpufreq_add_policy_cpu() already has a pointer to the policy structure and there is no need to look it up again in cpufreq_add_policy_cpu(). Let's pass it directly. Signed-off-by: Viresh Kumar Reviewed-by: Srivatsa S. Bhat Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 924d3f5df26d..1faf320a5038 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -897,21 +897,17 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy) } #ifdef CONFIG_HOTPLUG_CPU -static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, - struct device *dev, bool frozen) +static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, + unsigned int cpu, struct device *dev, + bool frozen) { - struct cpufreq_policy *policy; int ret = 0, has_target = !!cpufreq_driver->target; unsigned long flags; - policy = cpufreq_cpu_get(sibling); - if (WARN_ON_ONCE(!policy)) - return -ENODATA; - if (has_target) __cpufreq_governor(policy, CPUFREQ_GOV_STOP); - lock_policy_rwsem_write(sibling); + lock_policy_rwsem_write(policy->cpu); write_lock_irqsave(&cpufreq_driver_lock, flags); @@ -920,7 +916,7 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, per_cpu(cpufreq_cpu_data, cpu) = policy; write_unlock_irqrestore(&cpufreq_driver_lock, flags); - unlock_policy_rwsem_write(sibling); + unlock_policy_rwsem_write(policy->cpu); if (has_target) { __cpufreq_governor(policy, CPUFREQ_GOV_START); @@ -931,7 +927,6 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling, if (!frozen) ret = sysfs_create_link(&dev->kobj, &policy->kobj, "cpufreq"); - cpufreq_cpu_put(policy); return ret; } #endif @@ -1014,8 +1009,7 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling); if (cp && cpumask_test_cpu(cpu, cp->related_cpus)) { read_unlock_irqrestore(&cpufreq_driver_lock, flags); - return cpufreq_add_policy_cpu(cpu, sibling, dev, - frozen); + return cpufreq_add_policy_cpu(cp, cpu, dev, frozen); } } read_unlock_irqrestore(&cpufreq_driver_lock, flags); From 5ff0a268037d344f86df690ccb994d8bc015d2d9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 6 Aug 2013 22:53:03 +0530 Subject: [PATCH 16/25] cpufreq: Clean up header files included in the core This patch addresses the following issues in the header files in the cpufreq core: - Include headers in ascending order, so that we don't add same many times by mistake. - must be included after , so that they override whatever they need to. - Remove unnecessary includes. - Don't include files already included by cpufreq.h or cpufreq_governor.h. [rjw: Changelog] Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 19 ++++++------------- drivers/cpufreq/cpufreq_conservative.c | 12 ------------ drivers/cpufreq/cpufreq_governor.c | 6 ------ drivers/cpufreq/cpufreq_governor.h | 5 ++--- drivers/cpufreq/cpufreq_ondemand.c | 12 +----------- drivers/cpufreq/cpufreq_performance.c | 3 +-- drivers/cpufreq/cpufreq_powersave.c | 3 +-- drivers/cpufreq/cpufreq_stats.c | 9 +-------- drivers/cpufreq/freq_table.c | 4 +--- include/linux/cpufreq.h | 13 ++++--------- 10 files changed, 17 insertions(+), 69 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index e34bd94e12b4..845837174878 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -17,24 +17,17 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include -#include -#include -#include -#include -#include +#include #include #include -#include -#include -#include #include -#include -#include -#include +#include +#include +#include #include +#include #include - +#include #include /** diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 0ceb2eff5a7e..841e25699656 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -11,19 +11,7 @@ * published by the Free Software Foundation. */ -#include -#include -#include -#include -#include -#include -#include -#include -#include #include -#include -#include - #include "cpufreq_governor.h" /* Conservative governor macros */ diff --git a/drivers/cpufreq/cpufreq_governor.c b/drivers/cpufreq/cpufreq_governor.c index 7409dbd1d897..556064e9cc01 100644 --- a/drivers/cpufreq/cpufreq_governor.c +++ b/drivers/cpufreq/cpufreq_governor.c @@ -16,15 +16,9 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include -#include -#include #include #include -#include #include -#include -#include #include "cpufreq_governor.h" diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index 0e0dd4c82020..cf0b7a4425b0 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h @@ -18,10 +18,9 @@ #define _CPUFREQ_GOVERNOR_H #include -#include +#include +#include #include -#include -#include /* * The polling frequency depends on the capability of the processor. Default diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index a3c5574f9b3a..27c732eee431 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -12,20 +12,10 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include -#include -#include -#include -#include -#include -#include +#include #include #include -#include #include -#include -#include - #include "cpufreq_governor.h" /* On-demand governor macros */ diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c index 9fef7d6e4e6a..cf117deb39b1 100644 --- a/drivers/cpufreq/cpufreq_performance.c +++ b/drivers/cpufreq/cpufreq_performance.c @@ -12,10 +12,9 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include -#include #include #include +#include static int cpufreq_governor_performance(struct cpufreq_policy *policy, unsigned int event) diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c index 32109a14f5dc..e3b874c235ea 100644 --- a/drivers/cpufreq/cpufreq_powersave.c +++ b/drivers/cpufreq/cpufreq_powersave.c @@ -12,10 +12,9 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include -#include #include #include +#include static int cpufreq_governor_powersave(struct cpufreq_policy *policy, unsigned int event) diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index cb3841355454..a7143b0597af 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -9,17 +9,10 @@ * published by the Free Software Foundation. */ -#include -#include #include -#include #include #include -#include -#include -#include -#include -#include +#include #include static spinlock_t cpufreq_stats_lock; diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index f0d87412cc91..f111454a7aea 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -11,10 +11,8 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt -#include -#include -#include #include +#include /********************************************************************* * FREQUENCY TABLE HELPERS * diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index e1fd215e16c9..97627bbbca82 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -11,16 +11,11 @@ #ifndef _LINUX_CPUFREQ_H #define _LINUX_CPUFREQ_H -#include -#include -#include -#include -#include -#include -#include -#include #include -#include +#include +#include +#include +#include #define CPUFREQ_NAME_LEN 16 /* Print length for names. Extra 1 space for accomodating '\n' in prints */ From 74aca95da74836a6807118f6590d8df8232c74a9 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 6 Aug 2013 22:53:04 +0530 Subject: [PATCH 17/25] cpufreq: Re-arrange declarations in cpufreq.h They are pretty much mixed up. Although generic headers are present, definitions/declarations are present outside of them too ... This patch just moves stuff up and down to make it look better and consistent. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- include/linux/cpufreq.h | 407 +++++++++++++++++++--------------------- 1 file changed, 194 insertions(+), 213 deletions(-) diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 97627bbbca82..0d3b0266bc98 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -17,60 +17,30 @@ #include #include -#define CPUFREQ_NAME_LEN 16 -/* Print length for names. Extra 1 space for accomodating '\n' in prints */ -#define CPUFREQ_NAME_PLEN (CPUFREQ_NAME_LEN + 1) - /********************************************************************* - * CPUFREQ NOTIFIER INTERFACE * + * CPUFREQ INTERFACE * *********************************************************************/ - -#define CPUFREQ_TRANSITION_NOTIFIER (0) -#define CPUFREQ_POLICY_NOTIFIER (1) - -#ifdef CONFIG_CPU_FREQ -int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list); -int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list); -extern void disable_cpufreq(void); -#else /* CONFIG_CPU_FREQ */ -static inline int cpufreq_register_notifier(struct notifier_block *nb, - unsigned int list) -{ - return 0; -} -static inline int cpufreq_unregister_notifier(struct notifier_block *nb, - unsigned int list) -{ - return 0; -} -static inline void disable_cpufreq(void) { } -#endif /* CONFIG_CPU_FREQ */ - -/* if (cpufreq_driver->target) exists, the ->governor decides what frequency - * within the limits is used. If (cpufreq_driver->setpolicy> exists, these - * two generic policies are available: - */ - -#define CPUFREQ_POLICY_POWERSAVE (1) -#define CPUFREQ_POLICY_PERFORMANCE (2) - -/* Frequency values here are CPU kHz so that hardware which doesn't run - * with some frequencies can complain without having to guess what per - * cent / per mille means. +/* + * Frequency values here are CPU kHz + * * Maximum transition latency is in nanoseconds - if it's unknown, * CPUFREQ_ETERNAL shall be used. */ +#define CPUFREQ_ETERNAL (-1) +#define CPUFREQ_NAME_LEN 16 +/* Print length for names. Extra 1 space for accomodating '\n' in prints */ +#define CPUFREQ_NAME_PLEN (CPUFREQ_NAME_LEN + 1) + struct cpufreq_governor; -/* /sys/devices/system/cpu/cpufreq: entry point for global variables */ -extern struct kobject *cpufreq_global_kobject; -int cpufreq_get_global_kobject(void); -void cpufreq_put_global_kobject(void); -int cpufreq_sysfs_create_file(const struct attribute *attr); -void cpufreq_sysfs_remove_file(const struct attribute *attr); +struct cpufreq_freqs { + unsigned int cpu; /* cpu nr */ + unsigned int old; + unsigned int new; + u8 flags; /* flags of cpufreq_driver, see below. */ +}; -#define CPUFREQ_ETERNAL (-1) struct cpufreq_cpuinfo { unsigned int max_freq; unsigned int min_freq; @@ -117,102 +87,53 @@ struct cpufreq_policy { int transition_ongoing; /* Tracks transition status */ }; -#define CPUFREQ_ADJUST (0) -#define CPUFREQ_INCOMPATIBLE (1) -#define CPUFREQ_NOTIFY (2) -#define CPUFREQ_START (3) -#define CPUFREQ_UPDATE_POLICY_CPU (4) - /* Only for ACPI */ #define CPUFREQ_SHARED_TYPE_NONE (0) /* None */ #define CPUFREQ_SHARED_TYPE_HW (1) /* HW does needed coordination */ #define CPUFREQ_SHARED_TYPE_ALL (2) /* All dependent CPUs should set freq */ #define CPUFREQ_SHARED_TYPE_ANY (3) /* Freq can be set from any dependent CPU*/ +struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu); +void cpufreq_cpu_put(struct cpufreq_policy *data); + static inline bool policy_is_shared(struct cpufreq_policy *policy) { return cpumask_weight(policy->cpus) > 1; } -/******************** cpufreq transition notifiers *******************/ +/* /sys/devices/system/cpu/cpufreq: entry point for global variables */ +extern struct kobject *cpufreq_global_kobject; +int cpufreq_get_global_kobject(void); +void cpufreq_put_global_kobject(void); +int cpufreq_sysfs_create_file(const struct attribute *attr); +void cpufreq_sysfs_remove_file(const struct attribute *attr); -#define CPUFREQ_PRECHANGE (0) -#define CPUFREQ_POSTCHANGE (1) -#define CPUFREQ_RESUMECHANGE (8) -#define CPUFREQ_SUSPENDCHANGE (9) +#ifdef CONFIG_CPU_FREQ +unsigned int cpufreq_get(unsigned int cpu); +unsigned int cpufreq_quick_get(unsigned int cpu); +unsigned int cpufreq_quick_get_max(unsigned int cpu); +void disable_cpufreq(void); -struct cpufreq_freqs { - unsigned int cpu; /* cpu nr */ - unsigned int old; - unsigned int new; - u8 flags; /* flags of cpufreq_driver, see below. */ -}; - -/** - * cpufreq_scale - "old * mult / div" calculation for large values (32-bit-arch - * safe) - * @old: old value - * @div: divisor - * @mult: multiplier - * - * - * new = old * mult / div - */ -static inline unsigned long cpufreq_scale(unsigned long old, u_int div, - u_int mult) +u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy); +int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu); +int cpufreq_update_policy(unsigned int cpu); +bool have_governor_per_policy(void); +struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy); +#else +static inline unsigned int cpufreq_get(unsigned int cpu) { -#if BITS_PER_LONG == 32 - - u64 result = ((u64) old) * ((u64) mult); - do_div(result, div); - return (unsigned long) result; - -#elif BITS_PER_LONG == 64 - - unsigned long result = old * ((u64) mult); - result /= div; - return result; - + return 0; +} +static inline unsigned int cpufreq_quick_get(unsigned int cpu) +{ + return 0; +} +static inline unsigned int cpufreq_quick_get_max(unsigned int cpu) +{ + return 0; +} +static inline void disable_cpufreq(void) { } #endif -}; - -/********************************************************************* - * CPUFREQ GOVERNORS * - *********************************************************************/ - -#define CPUFREQ_GOV_START 1 -#define CPUFREQ_GOV_STOP 2 -#define CPUFREQ_GOV_LIMITS 3 -#define CPUFREQ_GOV_POLICY_INIT 4 -#define CPUFREQ_GOV_POLICY_EXIT 5 - -struct cpufreq_governor { - char name[CPUFREQ_NAME_LEN]; - int initialized; - int (*governor) (struct cpufreq_policy *policy, - unsigned int event); - ssize_t (*show_setspeed) (struct cpufreq_policy *policy, - char *buf); - int (*store_setspeed) (struct cpufreq_policy *policy, - unsigned int freq); - unsigned int max_transition_latency; /* HW must be able to switch to - next freq faster than this value in nano secs or we - will fallback to performance governor */ - struct list_head governor_list; - struct module *owner; -}; - -/* - * Pass a target to the cpufreq driver. - */ -extern int cpufreq_driver_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation); -extern int __cpufreq_driver_target(struct cpufreq_policy *policy, - unsigned int target_freq, - unsigned int relation); -int cpufreq_register_governor(struct cpufreq_governor *governor); -void cpufreq_unregister_governor(struct cpufreq_governor *governor); /********************************************************************* * CPUFREQ DRIVER INTERFACE * @@ -221,7 +142,40 @@ void cpufreq_unregister_governor(struct cpufreq_governor *governor); #define CPUFREQ_RELATION_L 0 /* lowest frequency at or above target */ #define CPUFREQ_RELATION_H 1 /* highest frequency below or at target */ -struct freq_attr; +struct freq_attr { + struct attribute attr; + ssize_t (*show)(struct cpufreq_policy *, char *); + ssize_t (*store)(struct cpufreq_policy *, const char *, size_t count); +}; + +#define cpufreq_freq_attr_ro(_name) \ +static struct freq_attr _name = \ +__ATTR(_name, 0444, show_##_name, NULL) + +#define cpufreq_freq_attr_ro_perm(_name, _perm) \ +static struct freq_attr _name = \ +__ATTR(_name, _perm, show_##_name, NULL) + +#define cpufreq_freq_attr_rw(_name) \ +static struct freq_attr _name = \ +__ATTR(_name, 0644, show_##_name, store_##_name) + +struct global_attr { + struct attribute attr; + ssize_t (*show)(struct kobject *kobj, + struct attribute *attr, char *buf); + ssize_t (*store)(struct kobject *a, struct attribute *b, + const char *c, size_t count); +}; + +#define define_one_global_ro(_name) \ +static struct global_attr _name = \ +__ATTR(_name, 0444, show_##_name, NULL) + +#define define_one_global_rw(_name) \ +static struct global_attr _name = \ +__ATTR(_name, 0644, show_##_name, store_##_name) + struct cpufreq_driver { struct module *owner; @@ -258,7 +212,6 @@ struct cpufreq_driver { }; /* flags */ - #define CPUFREQ_STICKY 0x01 /* the driver isn't removed even if * all ->init() calls failed */ #define CPUFREQ_CONST_LOOPS 0x02 /* loops_per_jiffy or other kernel @@ -270,8 +223,7 @@ struct cpufreq_driver { int cpufreq_register_driver(struct cpufreq_driver *driver_data); int cpufreq_unregister_driver(struct cpufreq_driver *driver_data); -void cpufreq_notify_transition(struct cpufreq_policy *policy, - struct cpufreq_freqs *freqs, unsigned int state); +const char *cpufreq_get_current_driver(void); static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy, unsigned int min, unsigned int max) @@ -289,86 +241,117 @@ static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy, return; } -struct freq_attr { - struct attribute attr; - ssize_t (*show)(struct cpufreq_policy *, char *); - ssize_t (*store)(struct cpufreq_policy *, const char *, size_t count); -}; - -#define cpufreq_freq_attr_ro(_name) \ -static struct freq_attr _name = \ -__ATTR(_name, 0444, show_##_name, NULL) - -#define cpufreq_freq_attr_ro_perm(_name, _perm) \ -static struct freq_attr _name = \ -__ATTR(_name, _perm, show_##_name, NULL) - -#define cpufreq_freq_attr_rw(_name) \ -static struct freq_attr _name = \ -__ATTR(_name, 0644, show_##_name, store_##_name) - -struct global_attr { - struct attribute attr; - ssize_t (*show)(struct kobject *kobj, - struct attribute *attr, char *buf); - ssize_t (*store)(struct kobject *a, struct attribute *b, - const char *c, size_t count); -}; - -#define define_one_global_ro(_name) \ -static struct global_attr _name = \ -__ATTR(_name, 0444, show_##_name, NULL) - -#define define_one_global_rw(_name) \ -static struct global_attr _name = \ -__ATTR(_name, 0644, show_##_name, store_##_name) - -struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu); -void cpufreq_cpu_put(struct cpufreq_policy *data); -const char *cpufreq_get_current_driver(void); - /********************************************************************* - * CPUFREQ 2.6. INTERFACE * - *********************************************************************/ -u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy); -int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu); -int cpufreq_update_policy(unsigned int cpu); -bool have_governor_per_policy(void); -struct kobject *get_governor_parent_kobj(struct cpufreq_policy *policy); - -#ifdef CONFIG_CPU_FREQ -/* - * query the current CPU frequency (in kHz). If zero, cpufreq couldn't detect it - */ -unsigned int cpufreq_get(unsigned int cpu); -#else -static inline unsigned int cpufreq_get(unsigned int cpu) -{ - return 0; -} -#endif - -/* - * query the last known CPU freq (in kHz). If zero, cpufreq couldn't detect it - */ -#ifdef CONFIG_CPU_FREQ -unsigned int cpufreq_quick_get(unsigned int cpu); -unsigned int cpufreq_quick_get_max(unsigned int cpu); -#else -static inline unsigned int cpufreq_quick_get(unsigned int cpu) -{ - return 0; -} -static inline unsigned int cpufreq_quick_get_max(unsigned int cpu) -{ - return 0; -} -#endif - -/********************************************************************* - * CPUFREQ DEFAULT GOVERNOR * + * CPUFREQ NOTIFIER INTERFACE * *********************************************************************/ +#define CPUFREQ_TRANSITION_NOTIFIER (0) +#define CPUFREQ_POLICY_NOTIFIER (1) + +/* Transition notifiers */ +#define CPUFREQ_PRECHANGE (0) +#define CPUFREQ_POSTCHANGE (1) +#define CPUFREQ_RESUMECHANGE (8) +#define CPUFREQ_SUSPENDCHANGE (9) + +/* Policy Notifiers */ +#define CPUFREQ_ADJUST (0) +#define CPUFREQ_INCOMPATIBLE (1) +#define CPUFREQ_NOTIFY (2) +#define CPUFREQ_START (3) +#define CPUFREQ_UPDATE_POLICY_CPU (4) + +#ifdef CONFIG_CPU_FREQ +int cpufreq_register_notifier(struct notifier_block *nb, unsigned int list); +int cpufreq_unregister_notifier(struct notifier_block *nb, unsigned int list); + +void cpufreq_notify_transition(struct cpufreq_policy *policy, + struct cpufreq_freqs *freqs, unsigned int state); + +#else /* CONFIG_CPU_FREQ */ +static inline int cpufreq_register_notifier(struct notifier_block *nb, + unsigned int list) +{ + return 0; +} +static inline int cpufreq_unregister_notifier(struct notifier_block *nb, + unsigned int list) +{ + return 0; +} +#endif /* !CONFIG_CPU_FREQ */ + +/** + * cpufreq_scale - "old * mult / div" calculation for large values (32-bit-arch + * safe) + * @old: old value + * @div: divisor + * @mult: multiplier + * + * + * new = old * mult / div + */ +static inline unsigned long cpufreq_scale(unsigned long old, u_int div, + u_int mult) +{ +#if BITS_PER_LONG == 32 + u64 result = ((u64) old) * ((u64) mult); + do_div(result, div); + return (unsigned long) result; + +#elif BITS_PER_LONG == 64 + unsigned long result = old * ((u64) mult); + result /= div; + return result; +#endif +} + +/********************************************************************* + * CPUFREQ GOVERNORS * + *********************************************************************/ + +/* + * If (cpufreq_driver->target) exists, the ->governor decides what frequency + * within the limits is used. If (cpufreq_driver->setpolicy> exists, these + * two generic policies are available: + */ +#define CPUFREQ_POLICY_POWERSAVE (1) +#define CPUFREQ_POLICY_PERFORMANCE (2) + +/* Governor Events */ +#define CPUFREQ_GOV_START 1 +#define CPUFREQ_GOV_STOP 2 +#define CPUFREQ_GOV_LIMITS 3 +#define CPUFREQ_GOV_POLICY_INIT 4 +#define CPUFREQ_GOV_POLICY_EXIT 5 + +struct cpufreq_governor { + char name[CPUFREQ_NAME_LEN]; + int initialized; + int (*governor) (struct cpufreq_policy *policy, + unsigned int event); + ssize_t (*show_setspeed) (struct cpufreq_policy *policy, + char *buf); + int (*store_setspeed) (struct cpufreq_policy *policy, + unsigned int freq); + unsigned int max_transition_latency; /* HW must be able to switch to + next freq faster than this value in nano secs or we + will fallback to performance governor */ + struct list_head governor_list; + struct module *owner; +}; + +/* Pass a target to the cpufreq driver */ +int cpufreq_driver_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation); +int __cpufreq_driver_target(struct cpufreq_policy *policy, + unsigned int target_freq, + unsigned int relation); +int cpufreq_register_governor(struct cpufreq_governor *governor); +void cpufreq_unregister_governor(struct cpufreq_governor *governor); + +/* CPUFREQ DEFAULT GOVERNOR */ /* * Performance governor is fallback governor if any other gov failed to auto * load due latency restrictions @@ -417,18 +400,16 @@ int cpufreq_frequency_table_target(struct cpufreq_policy *policy, unsigned int relation, unsigned int *index); -/* the following 3 funtions are for cpufreq core use only */ +void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy); +ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf); + +/* the following funtion is for cpufreq core use only */ 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; - void cpufreq_frequency_table_get_attr(struct cpufreq_frequency_table *table, unsigned int cpu); -void cpufreq_frequency_table_update_policy_cpu(struct cpufreq_policy *policy); - void cpufreq_frequency_table_put_attr(unsigned int cpu); -ssize_t cpufreq_show_cpus(const struct cpumask *mask, char *buf); - #endif /* _LINUX_CPUFREQ_H */ From 3a3e9e06d0c11b8efa95933a88c9e67209fa4330 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 6 Aug 2013 22:53:05 +0530 Subject: [PATCH 18/25] cpufreq: Give consistent names to cpufreq_policy objects They are called policy, cur_policy, new_policy, data, etc. Just call them policy wherever possible. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 200 ++++++++++++++--------------- drivers/cpufreq/cpufreq_governor.h | 2 +- drivers/cpufreq/cpufreq_ondemand.c | 10 +- drivers/cpufreq/cpufreq_stats.c | 12 +- include/linux/cpufreq.h | 2 +- 5 files changed, 113 insertions(+), 113 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 845837174878..1793fe82595d 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -179,7 +179,7 @@ EXPORT_SYMBOL_GPL(get_cpu_idle_time); static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs) { - struct cpufreq_policy *data; + struct cpufreq_policy *policy; unsigned long flags; if (cpu >= nr_cpu_ids) @@ -195,16 +195,16 @@ static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs) goto err_out_unlock; /* get the CPU */ - data = per_cpu(cpufreq_cpu_data, cpu); + policy = per_cpu(cpufreq_cpu_data, cpu); - if (!data) + if (!policy) goto err_out_put_module; - if (!sysfs && !kobject_get(&data->kobj)) + if (!sysfs && !kobject_get(&policy->kobj)) goto err_out_put_module; read_unlock_irqrestore(&cpufreq_driver_lock, flags); - return data; + return policy; err_out_put_module: module_put(cpufreq_driver->owner); @@ -228,25 +228,25 @@ static struct cpufreq_policy *cpufreq_cpu_get_sysfs(unsigned int cpu) return __cpufreq_cpu_get(cpu, true); } -static void __cpufreq_cpu_put(struct cpufreq_policy *data, bool sysfs) +static void __cpufreq_cpu_put(struct cpufreq_policy *policy, bool sysfs) { if (!sysfs) - kobject_put(&data->kobj); + kobject_put(&policy->kobj); module_put(cpufreq_driver->owner); } -void cpufreq_cpu_put(struct cpufreq_policy *data) +void cpufreq_cpu_put(struct cpufreq_policy *policy) { if (cpufreq_disabled()) return; - __cpufreq_cpu_put(data, false); + __cpufreq_cpu_put(policy, false); } EXPORT_SYMBOL_GPL(cpufreq_cpu_put); -static void cpufreq_cpu_put_sysfs(struct cpufreq_policy *data) +static void cpufreq_cpu_put_sysfs(struct cpufreq_policy *policy) { - __cpufreq_cpu_put(data, true); + __cpufreq_cpu_put(policy, true); } /********************************************************************* @@ -453,8 +453,8 @@ show_one(scaling_min_freq, min); show_one(scaling_max_freq, max); show_one(scaling_cur_freq, cur); -static int __cpufreq_set_policy(struct cpufreq_policy *data, - struct cpufreq_policy *policy); +static int __cpufreq_set_policy(struct cpufreq_policy *policy, + struct cpufreq_policy *new_policy); /** * cpufreq_per_cpu_attr_write() / store_##file_name() - sysfs write access @@ -1136,7 +1136,7 @@ static void update_policy_cpu(struct cpufreq_policy *policy, unsigned int cpu) CPUFREQ_UPDATE_POLICY_CPU, policy); } -static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *data, +static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *policy, unsigned int old_cpu, bool frozen) { struct device *cpu_dev; @@ -1144,27 +1144,27 @@ static int cpufreq_nominate_new_policy_cpu(struct cpufreq_policy *data, int ret; /* first sibling now owns the new sysfs dir */ - cpu_dev = get_cpu_device(cpumask_first(data->cpus)); + cpu_dev = get_cpu_device(cpumask_first(policy->cpus)); /* Don't touch sysfs files during light-weight tear-down */ if (frozen) return cpu_dev->id; sysfs_remove_link(&cpu_dev->kobj, "cpufreq"); - ret = kobject_move(&data->kobj, &cpu_dev->kobj); + ret = kobject_move(&policy->kobj, &cpu_dev->kobj); if (ret) { pr_err("%s: Failed to move kobj: %d", __func__, ret); WARN_ON(lock_policy_rwsem_write(old_cpu)); - cpumask_set_cpu(old_cpu, data->cpus); + cpumask_set_cpu(old_cpu, policy->cpus); write_lock_irqsave(&cpufreq_driver_lock, flags); - per_cpu(cpufreq_cpu_data, old_cpu) = data; + per_cpu(cpufreq_cpu_data, old_cpu) = policy; write_unlock_irqrestore(&cpufreq_driver_lock, flags); unlock_policy_rwsem_write(old_cpu); - ret = sysfs_create_link(&cpu_dev->kobj, &data->kobj, + ret = sysfs_create_link(&cpu_dev->kobj, &policy->kobj, "cpufreq"); return -EINVAL; @@ -1186,7 +1186,7 @@ static int __cpufreq_remove_dev(struct device *dev, unsigned int cpu = dev->id, cpus; int new_cpu; unsigned long flags; - struct cpufreq_policy *data; + struct cpufreq_policy *policy; struct kobject *kobj; struct completion *cmp; @@ -1194,44 +1194,44 @@ static int __cpufreq_remove_dev(struct device *dev, write_lock_irqsave(&cpufreq_driver_lock, flags); - data = per_cpu(cpufreq_cpu_data, cpu); + policy = per_cpu(cpufreq_cpu_data, cpu); per_cpu(cpufreq_cpu_data, cpu) = NULL; /* Save the policy somewhere when doing a light-weight tear-down */ if (frozen) - per_cpu(cpufreq_cpu_data_fallback, cpu) = data; + per_cpu(cpufreq_cpu_data_fallback, cpu) = policy; write_unlock_irqrestore(&cpufreq_driver_lock, flags); - if (!data) { + if (!policy) { pr_debug("%s: No cpu_data found\n", __func__); return -EINVAL; } if (cpufreq_driver->target) - __cpufreq_governor(data, CPUFREQ_GOV_STOP); + __cpufreq_governor(policy, CPUFREQ_GOV_STOP); #ifdef CONFIG_HOTPLUG_CPU if (!cpufreq_driver->setpolicy) strncpy(per_cpu(cpufreq_cpu_governor, cpu), - data->governor->name, CPUFREQ_NAME_LEN); + policy->governor->name, CPUFREQ_NAME_LEN); #endif WARN_ON(lock_policy_rwsem_write(cpu)); - cpus = cpumask_weight(data->cpus); + cpus = cpumask_weight(policy->cpus); if (cpus > 1) - cpumask_clear_cpu(cpu, data->cpus); + cpumask_clear_cpu(cpu, policy->cpus); unlock_policy_rwsem_write(cpu); - if (cpu != data->cpu && !frozen) { + if (cpu != policy->cpu && !frozen) { sysfs_remove_link(&dev->kobj, "cpufreq"); } else if (cpus > 1) { - new_cpu = cpufreq_nominate_new_policy_cpu(data, cpu, frozen); + new_cpu = cpufreq_nominate_new_policy_cpu(policy, cpu, frozen); if (new_cpu >= 0) { WARN_ON(lock_policy_rwsem_write(cpu)); - update_policy_cpu(data, new_cpu); + update_policy_cpu(policy, new_cpu); unlock_policy_rwsem_write(cpu); if (!frozen) { @@ -1244,12 +1244,12 @@ static int __cpufreq_remove_dev(struct device *dev, /* If cpu is last user of policy, free policy */ if (cpus == 1) { if (cpufreq_driver->target) - __cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT); + __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); if (!frozen) { lock_policy_rwsem_read(cpu); - kobj = &data->kobj; - cmp = &data->kobj_unregister; + kobj = &policy->kobj; + cmp = &policy->kobj_unregister; unlock_policy_rwsem_read(cpu); kobject_put(kobj); @@ -1269,14 +1269,14 @@ static int __cpufreq_remove_dev(struct device *dev, * subsequent light-weight ->init() to succeed. */ if (cpufreq_driver->exit) - cpufreq_driver->exit(data); + cpufreq_driver->exit(policy); if (!frozen) - cpufreq_policy_free(data); + cpufreq_policy_free(policy); } else { if (cpufreq_driver->target) { - __cpufreq_governor(data, CPUFREQ_GOV_START); - __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); + __cpufreq_governor(policy, CPUFREQ_GOV_START); + __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); } } @@ -1450,23 +1450,23 @@ static int cpufreq_bp_suspend(void) int ret = 0; int cpu = smp_processor_id(); - struct cpufreq_policy *cpu_policy; + struct cpufreq_policy *policy; pr_debug("suspending cpu %u\n", cpu); /* If there's no policy for the boot CPU, we have nothing to do. */ - cpu_policy = cpufreq_cpu_get(cpu); - if (!cpu_policy) + policy = cpufreq_cpu_get(cpu); + if (!policy) return 0; if (cpufreq_driver->suspend) { - ret = cpufreq_driver->suspend(cpu_policy); + ret = cpufreq_driver->suspend(policy); if (ret) printk(KERN_ERR "cpufreq: suspend failed in ->suspend " - "step on CPU %u\n", cpu_policy->cpu); + "step on CPU %u\n", policy->cpu); } - cpufreq_cpu_put(cpu_policy); + cpufreq_cpu_put(policy); return ret; } @@ -1488,28 +1488,28 @@ static void cpufreq_bp_resume(void) int ret = 0; int cpu = smp_processor_id(); - struct cpufreq_policy *cpu_policy; + struct cpufreq_policy *policy; pr_debug("resuming cpu %u\n", cpu); /* If there's no policy for the boot CPU, we have nothing to do. */ - cpu_policy = cpufreq_cpu_get(cpu); - if (!cpu_policy) + policy = cpufreq_cpu_get(cpu); + if (!policy) return; if (cpufreq_driver->resume) { - ret = cpufreq_driver->resume(cpu_policy); + ret = cpufreq_driver->resume(policy); if (ret) { printk(KERN_ERR "cpufreq: resume failed in ->resume " - "step on CPU %u\n", cpu_policy->cpu); + "step on CPU %u\n", policy->cpu); goto fail; } } - schedule_work(&cpu_policy->update); + schedule_work(&policy->update); fail: - cpufreq_cpu_put(cpu_policy); + cpufreq_cpu_put(policy); } static struct syscore_ops cpufreq_syscore_ops = { @@ -1829,95 +1829,95 @@ EXPORT_SYMBOL(cpufreq_get_policy); * data : current policy. * policy : policy to be set. */ -static int __cpufreq_set_policy(struct cpufreq_policy *data, - struct cpufreq_policy *policy) +static int __cpufreq_set_policy(struct cpufreq_policy *policy, + struct cpufreq_policy *new_policy) { int ret = 0, failed = 1; - pr_debug("setting new policy for CPU %u: %u - %u kHz\n", policy->cpu, - policy->min, policy->max); + pr_debug("setting new policy for CPU %u: %u - %u kHz\n", new_policy->cpu, + new_policy->min, new_policy->max); - memcpy(&policy->cpuinfo, &data->cpuinfo, + memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(struct cpufreq_cpuinfo)); - if (policy->min > data->max || policy->max < data->min) { + if (new_policy->min > policy->max || new_policy->max < policy->min) { ret = -EINVAL; goto error_out; } /* verify the cpu speed can be set within this limit */ - ret = cpufreq_driver->verify(policy); + ret = cpufreq_driver->verify(new_policy); if (ret) goto error_out; /* adjust if necessary - all reasons */ blocking_notifier_call_chain(&cpufreq_policy_notifier_list, - CPUFREQ_ADJUST, policy); + CPUFREQ_ADJUST, new_policy); /* adjust if necessary - hardware incompatibility*/ blocking_notifier_call_chain(&cpufreq_policy_notifier_list, - CPUFREQ_INCOMPATIBLE, policy); + CPUFREQ_INCOMPATIBLE, new_policy); /* * verify the cpu speed can be set within this limit, which might be * different to the first one */ - ret = cpufreq_driver->verify(policy); + ret = cpufreq_driver->verify(new_policy); if (ret) goto error_out; /* notification of the new policy */ blocking_notifier_call_chain(&cpufreq_policy_notifier_list, - CPUFREQ_NOTIFY, policy); + CPUFREQ_NOTIFY, new_policy); - data->min = policy->min; - data->max = policy->max; + policy->min = new_policy->min; + policy->max = new_policy->max; pr_debug("new min and max freqs are %u - %u kHz\n", - data->min, data->max); + policy->min, policy->max); if (cpufreq_driver->setpolicy) { - data->policy = policy->policy; + policy->policy = new_policy->policy; pr_debug("setting range\n"); - ret = cpufreq_driver->setpolicy(policy); + ret = cpufreq_driver->setpolicy(new_policy); } else { - if (policy->governor != data->governor) { + if (new_policy->governor != policy->governor) { /* save old, working values */ - struct cpufreq_governor *old_gov = data->governor; + struct cpufreq_governor *old_gov = policy->governor; pr_debug("governor switch\n"); /* end old governor */ - if (data->governor) { - __cpufreq_governor(data, CPUFREQ_GOV_STOP); - unlock_policy_rwsem_write(policy->cpu); - __cpufreq_governor(data, + if (policy->governor) { + __cpufreq_governor(policy, CPUFREQ_GOV_STOP); + unlock_policy_rwsem_write(new_policy->cpu); + __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); - lock_policy_rwsem_write(policy->cpu); + lock_policy_rwsem_write(new_policy->cpu); } /* start new governor */ - data->governor = policy->governor; - if (!__cpufreq_governor(data, CPUFREQ_GOV_POLICY_INIT)) { - if (!__cpufreq_governor(data, CPUFREQ_GOV_START)) { + policy->governor = new_policy->governor; + if (!__cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT)) { + if (!__cpufreq_governor(policy, CPUFREQ_GOV_START)) { failed = 0; } else { - unlock_policy_rwsem_write(policy->cpu); - __cpufreq_governor(data, + unlock_policy_rwsem_write(new_policy->cpu); + __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); - lock_policy_rwsem_write(policy->cpu); + lock_policy_rwsem_write(new_policy->cpu); } } if (failed) { /* new governor failed, so re-start old one */ pr_debug("starting governor %s failed\n", - data->governor->name); + policy->governor->name); if (old_gov) { - data->governor = old_gov; - __cpufreq_governor(data, + policy->governor = old_gov; + __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_INIT); - __cpufreq_governor(data, + __cpufreq_governor(policy, CPUFREQ_GOV_START); } ret = -EINVAL; @@ -1926,7 +1926,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *data, /* might be a policy change, too, so fall through */ } pr_debug("governor: change or update limits\n"); - __cpufreq_governor(data, CPUFREQ_GOV_LIMITS); + __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); } error_out: @@ -1942,11 +1942,11 @@ error_out: */ int cpufreq_update_policy(unsigned int cpu) { - struct cpufreq_policy *data = cpufreq_cpu_get(cpu); - struct cpufreq_policy policy; + struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); + struct cpufreq_policy new_policy; int ret; - if (!data) { + if (!policy) { ret = -ENODEV; goto no_policy; } @@ -1957,34 +1957,34 @@ int cpufreq_update_policy(unsigned int cpu) } pr_debug("updating policy for CPU %u\n", cpu); - memcpy(&policy, data, sizeof(struct cpufreq_policy)); - policy.min = data->user_policy.min; - policy.max = data->user_policy.max; - policy.policy = data->user_policy.policy; - policy.governor = data->user_policy.governor; + memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); + new_policy.min = policy->user_policy.min; + new_policy.max = policy->user_policy.max; + new_policy.policy = policy->user_policy.policy; + new_policy.governor = policy->user_policy.governor; /* * BIOS might change freq behind our back * -> ask driver for current freq and notify governors about a change */ if (cpufreq_driver->get) { - policy.cur = cpufreq_driver->get(cpu); - if (!data->cur) { + new_policy.cur = cpufreq_driver->get(cpu); + if (!policy->cur) { pr_debug("Driver did not initialize current freq"); - data->cur = policy.cur; + policy->cur = new_policy.cur; } else { - if (data->cur != policy.cur && cpufreq_driver->target) - cpufreq_out_of_sync(cpu, data->cur, - policy.cur); + if (policy->cur != new_policy.cur && cpufreq_driver->target) + cpufreq_out_of_sync(cpu, policy->cur, + new_policy.cur); } } - ret = __cpufreq_set_policy(data, &policy); + ret = __cpufreq_set_policy(policy, &new_policy); unlock_policy_rwsem_write(cpu); fail: - cpufreq_cpu_put(data); + cpufreq_cpu_put(policy); no_policy: return ret; } diff --git a/drivers/cpufreq/cpufreq_governor.h b/drivers/cpufreq/cpufreq_governor.h index cf0b7a4425b0..264e509a9149 100644 --- a/drivers/cpufreq/cpufreq_governor.h +++ b/drivers/cpufreq/cpufreq_governor.h @@ -221,7 +221,7 @@ struct od_ops { void (*powersave_bias_init_cpu)(int cpu); unsigned int (*powersave_bias_target)(struct cpufreq_policy *policy, unsigned int freq_next, unsigned int relation); - void (*freq_increase)(struct cpufreq_policy *p, unsigned int freq); + void (*freq_increase)(struct cpufreq_policy *policy, unsigned int freq); }; struct cs_ops { diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 27c732eee431..47d4b69be7c6 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -132,18 +132,18 @@ static void ondemand_powersave_bias_init(void) } } -static void dbs_freq_increase(struct cpufreq_policy *p, unsigned int freq) +static void dbs_freq_increase(struct cpufreq_policy *policy, unsigned int freq) { - struct dbs_data *dbs_data = p->governor_data; + struct dbs_data *dbs_data = policy->governor_data; struct od_dbs_tuners *od_tuners = dbs_data->tuners; if (od_tuners->powersave_bias) - freq = od_ops.powersave_bias_target(p, freq, + freq = od_ops.powersave_bias_target(policy, freq, CPUFREQ_RELATION_H); - else if (p->cur == p->max) + else if (policy->cur == policy->max) return; - __cpufreq_driver_target(p, freq, od_tuners->powersave_bias ? + __cpufreq_driver_target(policy, freq, od_tuners->powersave_bias ? CPUFREQ_RELATION_L : CPUFREQ_RELATION_H); } diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index a7143b0597af..a17b14ee37d8 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -193,7 +193,7 @@ static int cpufreq_stats_create_table(struct cpufreq_policy *policy, { unsigned int i, j, count = 0, ret = 0; struct cpufreq_stats *stat; - struct cpufreq_policy *data; + struct cpufreq_policy *current_policy; unsigned int alloc_size; unsigned int cpu = policy->cpu; if (per_cpu(cpufreq_stats_table, cpu)) @@ -202,13 +202,13 @@ static int cpufreq_stats_create_table(struct cpufreq_policy *policy, if ((stat) == NULL) return -ENOMEM; - data = cpufreq_cpu_get(cpu); - if (data == NULL) { + current_policy = cpufreq_cpu_get(cpu); + if (current_policy == NULL) { ret = -EINVAL; goto error_get_fail; } - ret = sysfs_create_group(&data->kobj, &stats_attr_group); + ret = sysfs_create_group(¤t_policy->kobj, &stats_attr_group); if (ret) goto error_out; @@ -251,10 +251,10 @@ static int cpufreq_stats_create_table(struct cpufreq_policy *policy, stat->last_time = get_jiffies_64(); stat->last_index = freq_table_get_index(stat, policy->cur); spin_unlock(&cpufreq_stats_lock); - cpufreq_cpu_put(data); + cpufreq_cpu_put(current_policy); return 0; error_out: - cpufreq_cpu_put(data); + cpufreq_cpu_put(current_policy); error_get_fail: kfree(stat); per_cpu(cpufreq_stats_table, cpu) = NULL; diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 0d3b0266bc98..29208923c9d3 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -94,7 +94,7 @@ struct cpufreq_policy { #define CPUFREQ_SHARED_TYPE_ANY (3) /* Freq can be set from any dependent CPU*/ struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu); -void cpufreq_cpu_put(struct cpufreq_policy *data); +void cpufreq_cpu_put(struct cpufreq_policy *policy); static inline bool policy_is_shared(struct cpufreq_policy *policy) { From d5b73cd870e2b049ef566aec2791dbf5fd26a7ec Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 6 Aug 2013 22:53:06 +0530 Subject: [PATCH 19/25] cpufreq: Use sizeof(*ptr) convetion for computing sizes Chapter 14 of Documentation/CodingStyle says: The preferred form for passing a size of a struct is the following: p = kmalloc(sizeof(*p), ...); The alternative form where struct name is spelled out hurts readability and introduces an opportunity for a bug when the pointer variable type is changed but the corresponding sizeof that is passed to a memory allocator is not. This wasn't followed consistently in drivers/cpufreq, let's make it more consistent by always following this rule. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/acpi-cpufreq.c | 4 ++-- drivers/cpufreq/cpufreq.c | 9 ++++----- drivers/cpufreq/cpufreq_conservative.c | 2 +- drivers/cpufreq/cpufreq_ondemand.c | 2 +- drivers/cpufreq/cpufreq_stats.c | 2 +- drivers/cpufreq/e_powersaver.c | 4 ++-- drivers/cpufreq/exynos-cpufreq.c | 2 +- drivers/cpufreq/gx-suspmod.c | 2 +- drivers/cpufreq/ia64-acpi-cpufreq.c | 4 ++-- drivers/cpufreq/pmac64-cpufreq.c | 5 ++--- drivers/cpufreq/powernow-k7.c | 13 ++++++------- drivers/cpufreq/powernow-k8.c | 6 +++--- drivers/cpufreq/s3c24xx-cpufreq.c | 6 +++--- drivers/cpufreq/sparc-us2e-cpufreq.c | 5 ++--- drivers/cpufreq/sparc-us3-cpufreq.c | 5 ++--- 15 files changed, 33 insertions(+), 38 deletions(-) diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index e673670d2321..44758ce9936d 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -709,7 +709,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) return blacklisted; #endif - data = kzalloc(sizeof(struct acpi_cpufreq_data), GFP_KERNEL); + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return -ENOMEM; @@ -799,7 +799,7 @@ static int acpi_cpufreq_cpu_init(struct cpufreq_policy *policy) goto err_unreg; } - data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * + data->freq_table = kmalloc(sizeof(*data->freq_table) * (perf->state_count+1), GFP_KERNEL); if (!data->freq_table) { result = -ENOMEM; diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 1793fe82595d..9e83d9142072 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -873,7 +873,7 @@ static void cpufreq_init_policy(struct cpufreq_policy *policy) struct cpufreq_policy new_policy; int ret = 0; - memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); + memcpy(&new_policy, policy, sizeof(*policy)); /* assure that the starting sequence is run in __cpufreq_set_policy */ policy->governor = NULL; @@ -1818,7 +1818,7 @@ int cpufreq_get_policy(struct cpufreq_policy *policy, unsigned int cpu) if (!cpu_policy) return -EINVAL; - memcpy(policy, cpu_policy, sizeof(struct cpufreq_policy)); + memcpy(policy, cpu_policy, sizeof(*policy)); cpufreq_cpu_put(cpu_policy); return 0; @@ -1837,8 +1837,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *policy, pr_debug("setting new policy for CPU %u: %u - %u kHz\n", new_policy->cpu, new_policy->min, new_policy->max); - memcpy(&new_policy->cpuinfo, &policy->cpuinfo, - sizeof(struct cpufreq_cpuinfo)); + memcpy(&new_policy->cpuinfo, &policy->cpuinfo, sizeof(policy->cpuinfo)); if (new_policy->min > policy->max || new_policy->max < policy->min) { ret = -EINVAL; @@ -1957,7 +1956,7 @@ int cpufreq_update_policy(unsigned int cpu) } pr_debug("updating policy for CPU %u\n", cpu); - memcpy(&new_policy, policy, sizeof(struct cpufreq_policy)); + memcpy(&new_policy, policy, sizeof(*policy)); new_policy.min = policy->user_policy.min; new_policy.max = policy->user_policy.max; new_policy.policy = policy->user_policy.policy; diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c index 841e25699656..c4009241e733 100644 --- a/drivers/cpufreq/cpufreq_conservative.c +++ b/drivers/cpufreq/cpufreq_conservative.c @@ -317,7 +317,7 @@ static int cs_init(struct dbs_data *dbs_data) { struct cs_dbs_tuners *tuners; - tuners = kzalloc(sizeof(struct cs_dbs_tuners), GFP_KERNEL); + tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); if (!tuners) { pr_err("%s: kzalloc failed\n", __func__); return -ENOMEM; diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c index 47d4b69be7c6..117278ab5869 100644 --- a/drivers/cpufreq/cpufreq_ondemand.c +++ b/drivers/cpufreq/cpufreq_ondemand.c @@ -482,7 +482,7 @@ static int od_init(struct dbs_data *dbs_data) u64 idle_time; int cpu; - tuners = kzalloc(sizeof(struct od_dbs_tuners), GFP_KERNEL); + tuners = kzalloc(sizeof(*tuners), GFP_KERNEL); if (!tuners) { pr_err("%s: kzalloc failed\n", __func__); return -ENOMEM; diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index a17b14ee37d8..04452f026ed0 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -198,7 +198,7 @@ static int cpufreq_stats_create_table(struct cpufreq_policy *policy, unsigned int cpu = policy->cpu; if (per_cpu(cpufreq_stats_table, cpu)) return -EBUSY; - stat = kzalloc(sizeof(struct cpufreq_stats), GFP_KERNEL); + stat = kzalloc(sizeof(*stat), GFP_KERNEL); if ((stat) == NULL) return -ENOMEM; diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c index a60efaeb4cf8..de974be6b773 100644 --- a/drivers/cpufreq/e_powersaver.c +++ b/drivers/cpufreq/e_powersaver.c @@ -54,7 +54,7 @@ static struct acpi_processor_performance *eps_acpi_cpu_perf; /* Minimum necessary to get acpi_processor_get_bios_limit() working */ static int eps_acpi_init(void) { - eps_acpi_cpu_perf = kzalloc(sizeof(struct acpi_processor_performance), + eps_acpi_cpu_perf = kzalloc(sizeof(*eps_acpi_cpu_perf), GFP_KERNEL); if (!eps_acpi_cpu_perf) return -ENOMEM; @@ -366,7 +366,7 @@ static int eps_cpu_init(struct cpufreq_policy *policy) states = 2; /* Allocate private data and frequency table for current cpu */ - centaur = kzalloc(sizeof(struct eps_cpu_data) + centaur = kzalloc(sizeof(*centaur) + (states + 1) * sizeof(struct cpufreq_frequency_table), GFP_KERNEL); if (!centaur) diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c index 0d32f02ef4d6..366475161c76 100644 --- a/drivers/cpufreq/exynos-cpufreq.c +++ b/drivers/cpufreq/exynos-cpufreq.c @@ -289,7 +289,7 @@ static int __init exynos_cpufreq_init(void) { int ret = -EINVAL; - exynos_info = kzalloc(sizeof(struct exynos_dvfs_info), GFP_KERNEL); + exynos_info = kzalloc(sizeof(*exynos_info), GFP_KERNEL); if (!exynos_info) return -ENOMEM; diff --git a/drivers/cpufreq/gx-suspmod.c b/drivers/cpufreq/gx-suspmod.c index 3dfc99b9ca86..4f25fb63c097 100644 --- a/drivers/cpufreq/gx-suspmod.c +++ b/drivers/cpufreq/gx-suspmod.c @@ -466,7 +466,7 @@ static int __init cpufreq_gx_init(void) pr_debug("geode suspend modulation available.\n"); - params = kzalloc(sizeof(struct gxfreq_params), GFP_KERNEL); + params = kzalloc(sizeof(*params), GFP_KERNEL); if (params == NULL) return -ENOMEM; diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c index 573c14ea802d..08792dd4d62a 100644 --- a/drivers/cpufreq/ia64-acpi-cpufreq.c +++ b/drivers/cpufreq/ia64-acpi-cpufreq.c @@ -274,7 +274,7 @@ acpi_cpufreq_cpu_init ( pr_debug("acpi_cpufreq_cpu_init\n"); - data = kzalloc(sizeof(struct cpufreq_acpi_io), GFP_KERNEL); + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) return (-ENOMEM); @@ -304,7 +304,7 @@ acpi_cpufreq_cpu_init ( } /* alloc freq_table */ - data->freq_table = kmalloc(sizeof(struct cpufreq_frequency_table) * + data->freq_table = kmalloc(sizeof(*data->freq_table) * (data->acpi_data.state_count + 1), GFP_KERNEL); if (!data->freq_table) { diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c index 7ba423431cfe..4d7799b7af86 100644 --- a/drivers/cpufreq/pmac64-cpufreq.c +++ b/drivers/cpufreq/pmac64-cpufreq.c @@ -447,9 +447,8 @@ static int __init g5_neo2_cpufreq_init(struct device_node *cpus) if (!shdr) goto bail_noprops; g5_fvt_table = (struct smu_sdbp_fvt *)&shdr[1]; - ssize = (shdr->len * sizeof(u32)) - - sizeof(struct smu_sdbp_header); - g5_fvt_count = ssize / sizeof(struct smu_sdbp_fvt); + ssize = (shdr->len * sizeof(u32)) - sizeof(*shdr); + g5_fvt_count = ssize / sizeof(*g5_fvt_table); g5_fvt_cur = 0; /* Sanity checking */ diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index 955870877935..4687d40d0219 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c @@ -177,7 +177,7 @@ static int get_ranges(unsigned char *pst) unsigned int speed; u8 fid, vid; - powernow_table = kzalloc((sizeof(struct cpufreq_frequency_table) * + powernow_table = kzalloc((sizeof(*powernow_table) * (number_scales + 1)), GFP_KERNEL); if (!powernow_table) return -ENOMEM; @@ -309,8 +309,7 @@ static int powernow_acpi_init(void) goto err0; } - acpi_processor_perf = kzalloc(sizeof(struct acpi_processor_performance), - GFP_KERNEL); + acpi_processor_perf = kzalloc(sizeof(*acpi_processor_perf), GFP_KERNEL); if (!acpi_processor_perf) { retval = -ENOMEM; goto err0; @@ -346,7 +345,7 @@ static int powernow_acpi_init(void) goto err2; } - powernow_table = kzalloc((sizeof(struct cpufreq_frequency_table) * + powernow_table = kzalloc((sizeof(*powernow_table) * (number_scales + 1)), GFP_KERNEL); if (!powernow_table) { retval = -ENOMEM; @@ -497,7 +496,7 @@ static int powernow_decode_bios(int maxfid, int startvid) "relevant to this CPU).\n", psb->numpst); - p += sizeof(struct psb_s); + p += sizeof(*psb); pst = (struct pst_s *) p; @@ -510,12 +509,12 @@ static int powernow_decode_bios(int maxfid, int startvid) (maxfid == pst->maxfid) && (startvid == pst->startvid)) { print_pst_entry(pst, j); - p = (char *)pst + sizeof(struct pst_s); + p = (char *)pst + sizeof(*pst); ret = get_ranges(p); return ret; } else { unsigned int k; - p = (char *)pst + sizeof(struct pst_s); + p = (char *)pst + sizeof(*pst); for (k = 0; k < number_scales; k++) p += 2; } diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index c39d189217cb..3f3c6cae91d0 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -623,7 +623,7 @@ static int fill_powernow_table(struct powernow_k8_data *data, if (check_pst_table(data, pst, maxvid)) return -EINVAL; - powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) + powernow_table = kmalloc((sizeof(*powernow_table) * (data->numps + 1)), GFP_KERNEL); if (!powernow_table) { printk(KERN_ERR PFX "powernow_table memory alloc failure\n"); @@ -793,7 +793,7 @@ static int powernow_k8_cpu_init_acpi(struct powernow_k8_data *data) } /* fill in data->powernow_table */ - powernow_table = kmalloc((sizeof(struct cpufreq_frequency_table) + powernow_table = kmalloc((sizeof(*powernow_table) * (data->acpi_data.state_count + 1)), GFP_KERNEL); if (!powernow_table) { pr_debug("powernow_table memory alloc failure\n"); @@ -1106,7 +1106,7 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol) if (rc) return -ENODEV; - data = kzalloc(sizeof(struct powernow_k8_data), GFP_KERNEL); + data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) { printk(KERN_ERR PFX "unable to alloc powernow_k8_data"); return -ENOMEM; diff --git a/drivers/cpufreq/s3c24xx-cpufreq.c b/drivers/cpufreq/s3c24xx-cpufreq.c index 87781eb20d6d..f169ee52e6eb 100644 --- a/drivers/cpufreq/s3c24xx-cpufreq.c +++ b/drivers/cpufreq/s3c24xx-cpufreq.c @@ -522,7 +522,7 @@ int __init s3c_cpufreq_setboard(struct s3c_cpufreq_board *board) /* Copy the board information so that each board can make this * initdata. */ - ours = kzalloc(sizeof(struct s3c_cpufreq_board), GFP_KERNEL); + ours = kzalloc(sizeof(*ours), GFP_KERNEL); if (ours == NULL) { printk(KERN_ERR "%s: no memory\n", __func__); return -ENOMEM; @@ -615,7 +615,7 @@ static int s3c_cpufreq_build_freq(void) size = cpu_cur.info->calc_freqtable(&cpu_cur, NULL, 0); size++; - ftab = kmalloc(sizeof(struct cpufreq_frequency_table) * size, GFP_KERNEL); + ftab = kmalloc(sizeof(*ftab) * size, GFP_KERNEL); if (!ftab) { printk(KERN_ERR "%s: no memory for tables\n", __func__); return -ENOMEM; @@ -691,7 +691,7 @@ int __init s3c_plltab_register(struct cpufreq_frequency_table *plls, struct cpufreq_frequency_table *vals; unsigned int size; - size = sizeof(struct cpufreq_frequency_table) * (plls_no + 1); + size = sizeof(*vals) * (plls_no + 1); vals = kmalloc(size, GFP_KERNEL); if (vals) { diff --git a/drivers/cpufreq/sparc-us2e-cpufreq.c b/drivers/cpufreq/sparc-us2e-cpufreq.c index 93061a408773..7c43a725e5da 100644 --- a/drivers/cpufreq/sparc-us2e-cpufreq.c +++ b/drivers/cpufreq/sparc-us2e-cpufreq.c @@ -351,12 +351,11 @@ static int __init us2e_freq_init(void) struct cpufreq_driver *driver; ret = -ENOMEM; - driver = kzalloc(sizeof(struct cpufreq_driver), GFP_KERNEL); + driver = kzalloc(sizeof(*driver), GFP_KERNEL); if (!driver) goto err_out; - us2e_freq_table = kzalloc( - (NR_CPUS * sizeof(struct us2e_freq_percpu_info)), + us2e_freq_table = kzalloc((NR_CPUS * sizeof(*us2e_freq_table)), GFP_KERNEL); if (!us2e_freq_table) goto err_out; diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c index 880ee293d61e..7f500c140bc3 100644 --- a/drivers/cpufreq/sparc-us3-cpufreq.c +++ b/drivers/cpufreq/sparc-us3-cpufreq.c @@ -212,12 +212,11 @@ static int __init us3_freq_init(void) struct cpufreq_driver *driver; ret = -ENOMEM; - driver = kzalloc(sizeof(struct cpufreq_driver), GFP_KERNEL); + driver = kzalloc(sizeof(*driver), GFP_KERNEL); if (!driver) goto err_out; - us3_freq_table = kzalloc( - (NR_CPUS * sizeof(struct us3_freq_percpu_info)), + us3_freq_table = kzalloc((NR_CPUS * sizeof(*us3_freq_table)), GFP_KERNEL); if (!us3_freq_table) goto err_out; From c88a1f8b96e7384627b918dfabbfc0c615a4a914 Mon Sep 17 00:00:00 2001 From: Lukasz Majewski Date: Tue, 6 Aug 2013 22:53:08 +0530 Subject: [PATCH 20/25] cpufreq: Store cpufreq policies in a list Policies available in the cpufreq framework are now linked together. They are accessible via cpufreq_policy_list defined in the cpufreq core. [rjw: Fix from Yinghai Lu folded in] Signed-off-by: Lukasz Majewski Signed-off-by: Myungjoo Ham Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 12 ++++++++++++ include/linux/cpufreq.h | 1 + 2 files changed, 13 insertions(+) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 9e83d9142072..75c5bd424d59 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -40,6 +40,7 @@ static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data); static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data_fallback); static DEFINE_RWLOCK(cpufreq_driver_lock); static DEFINE_MUTEX(cpufreq_governor_lock); +static LIST_HEAD(cpufreq_policy_list); #ifdef CONFIG_HOTPLUG_CPU /* This one keeps track of the previously set governor of a removed CPU */ @@ -952,6 +953,7 @@ static struct cpufreq_policy *cpufreq_policy_alloc(void) if (!zalloc_cpumask_var(&policy->related_cpus, GFP_KERNEL)) goto err_free_cpumask; + INIT_LIST_HEAD(&policy->policy_list); return policy; err_free_cpumask: @@ -964,6 +966,12 @@ err_free_policy: static void cpufreq_policy_free(struct cpufreq_policy *policy) { + unsigned long flags; + + write_lock_irqsave(&cpufreq_driver_lock, flags); + list_del(&policy->policy_list); + write_unlock_irqrestore(&cpufreq_driver_lock, flags); + free_cpumask_var(policy->related_cpus); free_cpumask_var(policy->cpus); kfree(policy); @@ -1077,6 +1085,10 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, ret = cpufreq_add_dev_interface(policy, dev); if (ret) goto err_out_unregister; + + write_lock_irqsave(&cpufreq_driver_lock, flags); + list_add(&policy->policy_list, &cpufreq_policy_list); + write_unlock_irqrestore(&cpufreq_driver_lock, flags); } cpufreq_init_policy(policy); diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 29208923c9d3..431a05d4b4c9 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -82,6 +82,7 @@ struct cpufreq_policy { struct cpufreq_real_policy user_policy; + struct list_head policy_list; struct kobject kobj; struct completion kobj_unregister; int transition_ongoing; /* Tracks transition status */ From eb608521f1e25a8c14295b6d9a3853c3cd8c6cf8 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 6 Aug 2013 22:53:09 +0530 Subject: [PATCH 21/25] cpufreq: Use cpufreq_policy_list for iterating over policies To iterate over all policies we currently iterate over all CPUs and then get the policy for each of them. Let's use the newly created cpufreq_policy_list for this purpose. [rjw: Changelog] Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 75c5bd424d59..37af929746af 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -985,8 +985,8 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, struct cpufreq_policy *policy; unsigned long flags; #ifdef CONFIG_HOTPLUG_CPU + struct cpufreq_policy *tpolicy; struct cpufreq_governor *gov; - int sibling; #endif if (cpu_is_offline(cpu)) @@ -1006,11 +1006,11 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, #ifdef CONFIG_HOTPLUG_CPU /* Check if this cpu was hot-unplugged earlier and has siblings */ read_lock_irqsave(&cpufreq_driver_lock, flags); - for_each_online_cpu(sibling) { - struct cpufreq_policy *cp = per_cpu(cpufreq_cpu_data, sibling); - if (cp && cpumask_test_cpu(cpu, cp->related_cpus)) { + list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) { + if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) { read_unlock_irqrestore(&cpufreq_driver_lock, flags); - return cpufreq_add_policy_cpu(cp, cpu, dev, frozen); + return cpufreq_add_policy_cpu(tpolicy, cpu, dev, + frozen); } } read_unlock_irqrestore(&cpufreq_driver_lock, flags); From fe492f3f0332e23cc6ca4913e5a2ed78e1888902 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 6 Aug 2013 22:53:10 +0530 Subject: [PATCH 22/25] cpufreq: Fix broken usage of governor->owner's refcount The cpufreq governor owner refcount usage is broken. We should only increment that refcount when a CPUFREQ_GOV_POLICY_INIT event has come and it should only be decremented if CPUFREQ_GOV_POLICY_EXIT has come. Currently, there can be situations where the governor is in use, but we have allowed it to be unloaded which may result in undefined behavior. Let's fix it. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 37af929746af..f149e14f77c7 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -1709,8 +1709,9 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, } } - if (!try_module_get(policy->governor->owner)) - return -EINVAL; + if (event == CPUFREQ_GOV_POLICY_INIT) + if (!try_module_get(policy->governor->owner)) + return -EINVAL; pr_debug("__cpufreq_governor for CPU %u, event %u\n", policy->cpu, event); @@ -1719,6 +1720,8 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, if ((!policy->governor_enabled && (event == CPUFREQ_GOV_STOP)) || (policy->governor_enabled && (event == CPUFREQ_GOV_START))) { mutex_unlock(&cpufreq_governor_lock); + if (event == CPUFREQ_GOV_POLICY_INIT) + module_put(policy->governor->owner); return -EBUSY; } @@ -1746,11 +1749,8 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, mutex_unlock(&cpufreq_governor_lock); } - /* we keep one module reference alive for - each CPU governed by this CPU */ - if ((event != CPUFREQ_GOV_START) || ret) - module_put(policy->governor->owner); - if ((event == CPUFREQ_GOV_STOP) && !ret) + if (((event == CPUFREQ_GOV_POLICY_INIT) && ret) || + ((event == CPUFREQ_GOV_POLICY_EXIT) && !ret)) module_put(policy->governor->owner); return ret; From 6eed9404ab3c4baea54ce4c7e862e69df1d39f38 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 6 Aug 2013 22:53:11 +0530 Subject: [PATCH 23/25] cpufreq: Use rwsem for protecting critical sections Critical sections of the cpufreq core are protected with the help of the driver module owner's refcount, which isn't the correct approach, because it causes rmmod to return an error when some routine has updated that refcount. Let's use rwsem for this purpose instead. Only cpufreq_unregister_driver() will use write sem and everybody else will use read sem. [rjw: Subject & changelog] Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 135 ++++++++++++++++---------------------- 1 file changed, 57 insertions(+), 78 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index f149e14f77c7..c9bbfeef92e3 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -91,6 +91,12 @@ static void unlock_policy_rwsem_##mode(int cpu) \ unlock_policy_rwsem(read, cpu); unlock_policy_rwsem(write, cpu); +/* + * rwsem to guarantee that cpufreq driver module doesn't unload during critical + * sections + */ +static DECLARE_RWSEM(cpufreq_rwsem); + /* internal prototypes */ static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event); @@ -178,78 +184,46 @@ u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy) } EXPORT_SYMBOL_GPL(get_cpu_idle_time); -static struct cpufreq_policy *__cpufreq_cpu_get(unsigned int cpu, bool sysfs) +struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu) { - struct cpufreq_policy *policy; + struct cpufreq_policy *policy = NULL; unsigned long flags; - if (cpu >= nr_cpu_ids) - goto err_out; + if (cpufreq_disabled() || (cpu >= nr_cpu_ids)) + return NULL; + + if (!down_read_trylock(&cpufreq_rwsem)) + return NULL; /* get the cpufreq driver */ read_lock_irqsave(&cpufreq_driver_lock, flags); - if (!cpufreq_driver) - goto err_out_unlock; + if (cpufreq_driver) { + /* get the CPU */ + policy = per_cpu(cpufreq_cpu_data, cpu); + if (policy) + kobject_get(&policy->kobj); + } - if (!try_module_get(cpufreq_driver->owner)) - goto err_out_unlock; - - /* get the CPU */ - policy = per_cpu(cpufreq_cpu_data, cpu); + read_unlock_irqrestore(&cpufreq_driver_lock, flags); if (!policy) - goto err_out_put_module; + up_read(&cpufreq_rwsem); - if (!sysfs && !kobject_get(&policy->kobj)) - goto err_out_put_module; - - read_unlock_irqrestore(&cpufreq_driver_lock, flags); return policy; - -err_out_put_module: - module_put(cpufreq_driver->owner); -err_out_unlock: - read_unlock_irqrestore(&cpufreq_driver_lock, flags); -err_out: - return NULL; -} - -struct cpufreq_policy *cpufreq_cpu_get(unsigned int cpu) -{ - if (cpufreq_disabled()) - return NULL; - - return __cpufreq_cpu_get(cpu, false); } EXPORT_SYMBOL_GPL(cpufreq_cpu_get); -static struct cpufreq_policy *cpufreq_cpu_get_sysfs(unsigned int cpu) -{ - return __cpufreq_cpu_get(cpu, true); -} - -static void __cpufreq_cpu_put(struct cpufreq_policy *policy, bool sysfs) -{ - if (!sysfs) - kobject_put(&policy->kobj); - module_put(cpufreq_driver->owner); -} - void cpufreq_cpu_put(struct cpufreq_policy *policy) { if (cpufreq_disabled()) return; - __cpufreq_cpu_put(policy, false); + kobject_put(&policy->kobj); + up_read(&cpufreq_rwsem); } EXPORT_SYMBOL_GPL(cpufreq_cpu_put); -static void cpufreq_cpu_put_sysfs(struct cpufreq_policy *policy) -{ - __cpufreq_cpu_put(policy, true); -} - /********************************************************************* * EXTERNALLY AFFECTING FREQUENCY CHANGES * *********************************************************************/ @@ -694,12 +668,12 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) struct cpufreq_policy *policy = to_policy(kobj); struct freq_attr *fattr = to_attr(attr); ssize_t ret = -EINVAL; - policy = cpufreq_cpu_get_sysfs(policy->cpu); - if (!policy) - goto no_policy; + + if (!down_read_trylock(&cpufreq_rwsem)) + goto exit; if (lock_policy_rwsem_read(policy->cpu) < 0) - goto fail; + goto up_read; if (fattr->show) ret = fattr->show(policy, buf); @@ -707,9 +681,10 @@ static ssize_t show(struct kobject *kobj, struct attribute *attr, char *buf) ret = -EIO; unlock_policy_rwsem_read(policy->cpu); -fail: - cpufreq_cpu_put_sysfs(policy); -no_policy: + +up_read: + up_read(&cpufreq_rwsem); +exit: return ret; } @@ -719,12 +694,12 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, struct cpufreq_policy *policy = to_policy(kobj); struct freq_attr *fattr = to_attr(attr); ssize_t ret = -EINVAL; - policy = cpufreq_cpu_get_sysfs(policy->cpu); - if (!policy) - goto no_policy; + + if (!down_read_trylock(&cpufreq_rwsem)) + goto exit; if (lock_policy_rwsem_write(policy->cpu) < 0) - goto fail; + goto up_read; if (fattr->store) ret = fattr->store(policy, buf, count); @@ -732,9 +707,10 @@ static ssize_t store(struct kobject *kobj, struct attribute *attr, ret = -EIO; unlock_policy_rwsem_write(policy->cpu); -fail: - cpufreq_cpu_put_sysfs(policy); -no_policy: + +up_read: + up_read(&cpufreq_rwsem); +exit: return ret; } @@ -1003,25 +979,24 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, return 0; } + if (!down_read_trylock(&cpufreq_rwsem)) + return 0; + #ifdef CONFIG_HOTPLUG_CPU /* Check if this cpu was hot-unplugged earlier and has siblings */ read_lock_irqsave(&cpufreq_driver_lock, flags); list_for_each_entry(tpolicy, &cpufreq_policy_list, policy_list) { if (cpumask_test_cpu(cpu, tpolicy->related_cpus)) { read_unlock_irqrestore(&cpufreq_driver_lock, flags); - return cpufreq_add_policy_cpu(tpolicy, cpu, dev, - frozen); + ret = cpufreq_add_policy_cpu(tpolicy, cpu, dev, frozen); + up_read(&cpufreq_rwsem); + return ret; } } read_unlock_irqrestore(&cpufreq_driver_lock, flags); #endif #endif - if (!try_module_get(cpufreq_driver->owner)) { - ret = -EINVAL; - goto module_out; - } - if (frozen) /* Restore the saved policy when doing light-weight init */ policy = cpufreq_policy_restore(cpu); @@ -1094,7 +1069,8 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif, cpufreq_init_policy(policy); kobject_uevent(&policy->kobj, KOBJ_ADD); - module_put(cpufreq_driver->owner); + up_read(&cpufreq_rwsem); + pr_debug("initialization complete\n"); return 0; @@ -1112,8 +1088,8 @@ err_set_policy_cpu: per_cpu(cpufreq_policy_cpu, cpu) = -1; cpufreq_policy_free(policy); nomem_out: - module_put(cpufreq_driver->owner); -module_out: + up_read(&cpufreq_rwsem); + return ret; } @@ -1425,10 +1401,9 @@ static unsigned int __cpufreq_get(unsigned int cpu) unsigned int cpufreq_get(unsigned int cpu) { unsigned int ret_freq = 0; - struct cpufreq_policy *policy = cpufreq_cpu_get(cpu); - if (!policy) - goto out; + if (!down_read_trylock(&cpufreq_rwsem)) + return 0; if (unlikely(lock_policy_rwsem_read(cpu))) goto out_policy; @@ -1438,8 +1413,8 @@ unsigned int cpufreq_get(unsigned int cpu) unlock_policy_rwsem_read(cpu); out_policy: - cpufreq_cpu_put(policy); -out: + up_read(&cpufreq_rwsem); + return ret_freq; } EXPORT_SYMBOL(cpufreq_get); @@ -2132,9 +2107,13 @@ int cpufreq_unregister_driver(struct cpufreq_driver *driver) subsys_interface_unregister(&cpufreq_interface); unregister_hotcpu_notifier(&cpufreq_cpu_notifier); + down_write(&cpufreq_rwsem); write_lock_irqsave(&cpufreq_driver_lock, flags); + cpufreq_driver = NULL; + write_unlock_irqrestore(&cpufreq_driver_lock, flags); + up_write(&cpufreq_rwsem); return 0; } From adc97d6a735dbb1e94cb4f1bf0b55f258b349941 Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 6 Aug 2013 22:53:12 +0530 Subject: [PATCH 24/25] cpufreq: Drop the owner field from struct cpufreq_driver We don't need to set .owner = THIS_MODULE any more in cpufreq drivers as this field isn't used any more by the cpufreq core. This patch removes it and updates all dependent drivers accordingly. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- Documentation/cpu-freq/cpu-drivers.txt | 2 -- drivers/cpufreq/acpi-cpufreq.c | 1 - drivers/cpufreq/at32ap-cpufreq.c | 1 - drivers/cpufreq/blackfin-cpufreq.c | 1 - drivers/cpufreq/cpufreq-nforce2.c | 1 - drivers/cpufreq/cris-artpec3-cpufreq.c | 1 - drivers/cpufreq/cris-etraxfs-cpufreq.c | 1 - drivers/cpufreq/e_powersaver.c | 1 - drivers/cpufreq/elanfreq.c | 1 - drivers/cpufreq/gx-suspmod.c | 1 - drivers/cpufreq/ia64-acpi-cpufreq.c | 1 - drivers/cpufreq/intel_pstate.c | 1 - drivers/cpufreq/kirkwood-cpufreq.c | 1 - drivers/cpufreq/longhaul.c | 1 - drivers/cpufreq/longrun.c | 1 - drivers/cpufreq/loongson2_cpufreq.c | 1 - drivers/cpufreq/maple-cpufreq.c | 1 - drivers/cpufreq/p4-clockmod.c | 1 - drivers/cpufreq/pasemi-cpufreq.c | 1 - drivers/cpufreq/pcc-cpufreq.c | 1 - drivers/cpufreq/pmac32-cpufreq.c | 1 - drivers/cpufreq/pmac64-cpufreq.c | 1 - drivers/cpufreq/powernow-k6.c | 1 - drivers/cpufreq/powernow-k7.c | 1 - drivers/cpufreq/powernow-k8.c | 1 - drivers/cpufreq/ppc-corenet-cpufreq.c | 1 - drivers/cpufreq/ppc_cbe_cpufreq.c | 1 - drivers/cpufreq/s3c2416-cpufreq.c | 1 - drivers/cpufreq/s3c64xx-cpufreq.c | 1 - drivers/cpufreq/sc520_freq.c | 1 - drivers/cpufreq/sh-cpufreq.c | 1 - drivers/cpufreq/sparc-us2e-cpufreq.c | 1 - drivers/cpufreq/sparc-us3-cpufreq.c | 1 - drivers/cpufreq/speedstep-centrino.c | 1 - drivers/cpufreq/speedstep-ich.c | 1 - drivers/cpufreq/speedstep-smi.c | 1 - include/linux/cpufreq.h | 1 - 37 files changed, 38 deletions(-) diff --git a/Documentation/cpu-freq/cpu-drivers.txt b/Documentation/cpu-freq/cpu-drivers.txt index 19fa98e07bf7..40282e617913 100644 --- a/Documentation/cpu-freq/cpu-drivers.txt +++ b/Documentation/cpu-freq/cpu-drivers.txt @@ -50,8 +50,6 @@ What shall this struct cpufreq_driver contain? cpufreq_driver.name - The name of this driver. -cpufreq_driver.owner - THIS_MODULE; - cpufreq_driver.init - A pointer to the per-CPU initialization function. diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c index 44758ce9936d..9b5d1b1a9c03 100644 --- a/drivers/cpufreq/acpi-cpufreq.c +++ b/drivers/cpufreq/acpi-cpufreq.c @@ -936,7 +936,6 @@ static struct cpufreq_driver acpi_cpufreq_driver = { .exit = acpi_cpufreq_cpu_exit, .resume = acpi_cpufreq_resume, .name = "acpi-cpufreq", - .owner = THIS_MODULE, .attr = acpi_cpufreq_attr, }; diff --git a/drivers/cpufreq/at32ap-cpufreq.c b/drivers/cpufreq/at32ap-cpufreq.c index 654488723cb5..e0c38d938997 100644 --- a/drivers/cpufreq/at32ap-cpufreq.c +++ b/drivers/cpufreq/at32ap-cpufreq.c @@ -108,7 +108,6 @@ static int __init at32_cpufreq_driver_init(struct cpufreq_policy *policy) static struct cpufreq_driver at32_driver = { .name = "at32ap", - .owner = THIS_MODULE, .init = at32_cpufreq_driver_init, .verify = at32_verify_speed, .target = at32_set_target, diff --git a/drivers/cpufreq/blackfin-cpufreq.c b/drivers/cpufreq/blackfin-cpufreq.c index 9cdbbd278a80..ef05978a7237 100644 --- a/drivers/cpufreq/blackfin-cpufreq.c +++ b/drivers/cpufreq/blackfin-cpufreq.c @@ -225,7 +225,6 @@ static struct cpufreq_driver bfin_driver = { .get = bfin_getfreq_khz, .init = __bfin_cpu_init, .name = "bfin cpufreq", - .owner = THIS_MODULE, .attr = bfin_freq_attr, }; diff --git a/drivers/cpufreq/cpufreq-nforce2.c b/drivers/cpufreq/cpufreq-nforce2.c index af1542d41440..b83d45f68574 100644 --- a/drivers/cpufreq/cpufreq-nforce2.c +++ b/drivers/cpufreq/cpufreq-nforce2.c @@ -379,7 +379,6 @@ static struct cpufreq_driver nforce2_driver = { .get = nforce2_get, .init = nforce2_cpu_init, .exit = nforce2_cpu_exit, - .owner = THIS_MODULE, }; #ifdef MODULE diff --git a/drivers/cpufreq/cris-artpec3-cpufreq.c b/drivers/cpufreq/cris-artpec3-cpufreq.c index ee142c490575..cb8276dd19ca 100644 --- a/drivers/cpufreq/cris-artpec3-cpufreq.c +++ b/drivers/cpufreq/cris-artpec3-cpufreq.c @@ -111,7 +111,6 @@ static struct cpufreq_driver cris_freq_driver = { .init = cris_freq_cpu_init, .exit = cris_freq_cpu_exit, .name = "cris_freq", - .owner = THIS_MODULE, .attr = cris_freq_attr, }; diff --git a/drivers/cpufreq/cris-etraxfs-cpufreq.c b/drivers/cpufreq/cris-etraxfs-cpufreq.c index 12952235d5db..72328f77dc53 100644 --- a/drivers/cpufreq/cris-etraxfs-cpufreq.c +++ b/drivers/cpufreq/cris-etraxfs-cpufreq.c @@ -108,7 +108,6 @@ static struct cpufreq_driver cris_freq_driver = { .init = cris_freq_cpu_init, .exit = cris_freq_cpu_exit, .name = "cris_freq", - .owner = THIS_MODULE, .attr = cris_freq_attr, }; diff --git a/drivers/cpufreq/e_powersaver.c b/drivers/cpufreq/e_powersaver.c index de974be6b773..09f64cc83019 100644 --- a/drivers/cpufreq/e_powersaver.c +++ b/drivers/cpufreq/e_powersaver.c @@ -436,7 +436,6 @@ static struct cpufreq_driver eps_driver = { .exit = eps_cpu_exit, .get = eps_get, .name = "e_powersaver", - .owner = THIS_MODULE, .attr = eps_attr, }; diff --git a/drivers/cpufreq/elanfreq.c b/drivers/cpufreq/elanfreq.c index 658d860344b0..823a400d98fd 100644 --- a/drivers/cpufreq/elanfreq.c +++ b/drivers/cpufreq/elanfreq.c @@ -274,7 +274,6 @@ static struct cpufreq_driver elanfreq_driver = { .init = elanfreq_cpu_init, .exit = elanfreq_cpu_exit, .name = "elanfreq", - .owner = THIS_MODULE, .attr = elanfreq_attr, }; diff --git a/drivers/cpufreq/gx-suspmod.c b/drivers/cpufreq/gx-suspmod.c index 4f25fb63c097..ef5fee7dc0b3 100644 --- a/drivers/cpufreq/gx-suspmod.c +++ b/drivers/cpufreq/gx-suspmod.c @@ -446,7 +446,6 @@ static struct cpufreq_driver gx_suspmod_driver = { .target = cpufreq_gx_target, .init = cpufreq_gx_cpu_init, .name = "gx-suspmod", - .owner = THIS_MODULE, }; static int __init cpufreq_gx_init(void) diff --git a/drivers/cpufreq/ia64-acpi-cpufreq.c b/drivers/cpufreq/ia64-acpi-cpufreq.c index 08792dd4d62a..3e14f0317175 100644 --- a/drivers/cpufreq/ia64-acpi-cpufreq.c +++ b/drivers/cpufreq/ia64-acpi-cpufreq.c @@ -409,7 +409,6 @@ static struct cpufreq_driver acpi_cpufreq_driver = { .init = acpi_cpufreq_cpu_init, .exit = acpi_cpufreq_cpu_exit, .name = "acpi-cpufreq", - .owner = THIS_MODULE, .attr = acpi_cpufreq_attr, }; diff --git a/drivers/cpufreq/intel_pstate.c b/drivers/cpufreq/intel_pstate.c index 7cde885011ed..6efd96c196b2 100644 --- a/drivers/cpufreq/intel_pstate.c +++ b/drivers/cpufreq/intel_pstate.c @@ -665,7 +665,6 @@ static struct cpufreq_driver intel_pstate_driver = { .init = intel_pstate_cpu_init, .exit = intel_pstate_cpu_exit, .name = "intel_pstate", - .owner = THIS_MODULE, }; static int __initdata no_load; diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c index c233ea617366..45e4d7fc261d 100644 --- a/drivers/cpufreq/kirkwood-cpufreq.c +++ b/drivers/cpufreq/kirkwood-cpufreq.c @@ -158,7 +158,6 @@ static struct cpufreq_driver kirkwood_cpufreq_driver = { .init = kirkwood_cpufreq_cpu_init, .exit = kirkwood_cpufreq_cpu_exit, .name = "kirkwood-cpufreq", - .owner = THIS_MODULE, .attr = kirkwood_cpufreq_attr, }; diff --git a/drivers/cpufreq/longhaul.c b/drivers/cpufreq/longhaul.c index 8c49261df57d..4ada1cccb052 100644 --- a/drivers/cpufreq/longhaul.c +++ b/drivers/cpufreq/longhaul.c @@ -948,7 +948,6 @@ static struct cpufreq_driver longhaul_driver = { .init = longhaul_cpu_init, .exit = longhaul_cpu_exit, .name = "longhaul", - .owner = THIS_MODULE, .attr = longhaul_attr, }; diff --git a/drivers/cpufreq/longrun.c b/drivers/cpufreq/longrun.c index 0fe041d1f77f..5aa031612d53 100644 --- a/drivers/cpufreq/longrun.c +++ b/drivers/cpufreq/longrun.c @@ -286,7 +286,6 @@ static struct cpufreq_driver longrun_driver = { .get = longrun_get, .init = longrun_cpu_init, .name = "longrun", - .owner = THIS_MODULE, }; static const struct x86_cpu_id longrun_ids[] = { diff --git a/drivers/cpufreq/loongson2_cpufreq.c b/drivers/cpufreq/loongson2_cpufreq.c index bb838b985077..e65de91b534b 100644 --- a/drivers/cpufreq/loongson2_cpufreq.c +++ b/drivers/cpufreq/loongson2_cpufreq.c @@ -157,7 +157,6 @@ static struct freq_attr *loongson2_table_attr[] = { }; static struct cpufreq_driver loongson2_cpufreq_driver = { - .owner = THIS_MODULE, .name = "loongson2", .init = loongson2_cpufreq_cpu_init, .verify = loongson2_cpufreq_verify, diff --git a/drivers/cpufreq/maple-cpufreq.c b/drivers/cpufreq/maple-cpufreq.c index cdd62915efaf..41c601f4631e 100644 --- a/drivers/cpufreq/maple-cpufreq.c +++ b/drivers/cpufreq/maple-cpufreq.c @@ -190,7 +190,6 @@ static int maple_cpufreq_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver maple_cpufreq_driver = { .name = "maple", - .owner = THIS_MODULE, .flags = CPUFREQ_CONST_LOOPS, .init = maple_cpufreq_cpu_init, .verify = maple_cpufreq_verify, diff --git a/drivers/cpufreq/p4-clockmod.c b/drivers/cpufreq/p4-clockmod.c index 9ee78170ff86..2f0a2a65c37f 100644 --- a/drivers/cpufreq/p4-clockmod.c +++ b/drivers/cpufreq/p4-clockmod.c @@ -279,7 +279,6 @@ static struct cpufreq_driver p4clockmod_driver = { .exit = cpufreq_p4_cpu_exit, .get = cpufreq_p4_get, .name = "p4-clockmod", - .owner = THIS_MODULE, .attr = p4clockmod_attr, }; diff --git a/drivers/cpufreq/pasemi-cpufreq.c b/drivers/cpufreq/pasemi-cpufreq.c index b704da404067..534e43a60d1f 100644 --- a/drivers/cpufreq/pasemi-cpufreq.c +++ b/drivers/cpufreq/pasemi-cpufreq.c @@ -297,7 +297,6 @@ static int pas_cpufreq_target(struct cpufreq_policy *policy, static struct cpufreq_driver pas_cpufreq_driver = { .name = "pas-cpufreq", - .owner = THIS_MODULE, .flags = CPUFREQ_CONST_LOOPS, .init = pas_cpufreq_cpu_init, .exit = pas_cpufreq_cpu_exit, diff --git a/drivers/cpufreq/pcc-cpufreq.c b/drivers/cpufreq/pcc-cpufreq.c index 1581fcc4cf4a..d81c4e5ea0ad 100644 --- a/drivers/cpufreq/pcc-cpufreq.c +++ b/drivers/cpufreq/pcc-cpufreq.c @@ -587,7 +587,6 @@ static struct cpufreq_driver pcc_cpufreq_driver = { .init = pcc_cpufreq_cpu_init, .exit = pcc_cpufreq_cpu_exit, .name = "pcc-cpufreq", - .owner = THIS_MODULE, }; static int __init pcc_cpufreq_init(void) diff --git a/drivers/cpufreq/pmac32-cpufreq.c b/drivers/cpufreq/pmac32-cpufreq.c index 3104fad82480..38cdc63c38da 100644 --- a/drivers/cpufreq/pmac32-cpufreq.c +++ b/drivers/cpufreq/pmac32-cpufreq.c @@ -477,7 +477,6 @@ static struct cpufreq_driver pmac_cpufreq_driver = { .flags = CPUFREQ_PM_NO_WARN, .attr = pmac_cpu_freqs_attr, .name = "powermac", - .owner = THIS_MODULE, }; diff --git a/drivers/cpufreq/pmac64-cpufreq.c b/drivers/cpufreq/pmac64-cpufreq.c index 4d7799b7af86..b6850d97f0d5 100644 --- a/drivers/cpufreq/pmac64-cpufreq.c +++ b/drivers/cpufreq/pmac64-cpufreq.c @@ -371,7 +371,6 @@ static int g5_cpufreq_cpu_init(struct cpufreq_policy *policy) static struct cpufreq_driver g5_cpufreq_driver = { .name = "powermac", - .owner = THIS_MODULE, .flags = CPUFREQ_CONST_LOOPS, .init = g5_cpufreq_cpu_init, .verify = g5_cpufreq_verify, diff --git a/drivers/cpufreq/powernow-k6.c b/drivers/cpufreq/powernow-k6.c index ea8e10382ec5..85f1c8c25ddc 100644 --- a/drivers/cpufreq/powernow-k6.c +++ b/drivers/cpufreq/powernow-k6.c @@ -207,7 +207,6 @@ static struct cpufreq_driver powernow_k6_driver = { .exit = powernow_k6_cpu_exit, .get = powernow_k6_get, .name = "powernow-k6", - .owner = THIS_MODULE, .attr = powernow_k6_attr, }; diff --git a/drivers/cpufreq/powernow-k7.c b/drivers/cpufreq/powernow-k7.c index 4687d40d0219..14ce480be8ab 100644 --- a/drivers/cpufreq/powernow-k7.c +++ b/drivers/cpufreq/powernow-k7.c @@ -716,7 +716,6 @@ static struct cpufreq_driver powernow_driver = { .init = powernow_cpu_init, .exit = powernow_cpu_exit, .name = "powernow-k7", - .owner = THIS_MODULE, .attr = powernow_table_attr, }; diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 3f3c6cae91d0..2344a9ed17f3 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1240,7 +1240,6 @@ static struct cpufreq_driver cpufreq_amd64_driver = { .exit = powernowk8_cpu_exit, .get = powernowk8_get, .name = "powernow-k8", - .owner = THIS_MODULE, .attr = powernow_k8_attr, }; diff --git a/drivers/cpufreq/ppc-corenet-cpufreq.c b/drivers/cpufreq/ppc-corenet-cpufreq.c index 3cae4529f959..60e81d524ea8 100644 --- a/drivers/cpufreq/ppc-corenet-cpufreq.c +++ b/drivers/cpufreq/ppc-corenet-cpufreq.c @@ -300,7 +300,6 @@ static struct freq_attr *corenet_cpufreq_attr[] = { static struct cpufreq_driver ppc_corenet_cpufreq_driver = { .name = "ppc_cpufreq", - .owner = THIS_MODULE, .flags = CPUFREQ_CONST_LOOPS, .init = corenet_cpufreq_cpu_init, .exit = __exit_p(corenet_cpufreq_cpu_exit), diff --git a/drivers/cpufreq/ppc_cbe_cpufreq.c b/drivers/cpufreq/ppc_cbe_cpufreq.c index 5936f8d6f2cc..2e448f0bbdc5 100644 --- a/drivers/cpufreq/ppc_cbe_cpufreq.c +++ b/drivers/cpufreq/ppc_cbe_cpufreq.c @@ -181,7 +181,6 @@ static struct cpufreq_driver cbe_cpufreq_driver = { .init = cbe_cpufreq_cpu_init, .exit = cbe_cpufreq_cpu_exit, .name = "cbe-cpufreq", - .owner = THIS_MODULE, .flags = CPUFREQ_CONST_LOOPS, }; diff --git a/drivers/cpufreq/s3c2416-cpufreq.c b/drivers/cpufreq/s3c2416-cpufreq.c index ce5b9fca9c18..22dcb81ef9d0 100644 --- a/drivers/cpufreq/s3c2416-cpufreq.c +++ b/drivers/cpufreq/s3c2416-cpufreq.c @@ -524,7 +524,6 @@ static struct freq_attr *s3c2416_cpufreq_attr[] = { }; static struct cpufreq_driver s3c2416_cpufreq_driver = { - .owner = THIS_MODULE, .flags = 0, .verify = s3c2416_cpufreq_verify_speed, .target = s3c2416_cpufreq_set_target, diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c index 13bb4bae64ee..8a72b0c555f8 100644 --- a/drivers/cpufreq/s3c64xx-cpufreq.c +++ b/drivers/cpufreq/s3c64xx-cpufreq.c @@ -263,7 +263,6 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy) } static struct cpufreq_driver s3c64xx_cpufreq_driver = { - .owner = THIS_MODULE, .flags = 0, .verify = s3c64xx_cpufreq_verify_speed, .target = s3c64xx_cpufreq_set_target, diff --git a/drivers/cpufreq/sc520_freq.c b/drivers/cpufreq/sc520_freq.c index 77a210975fc4..d6f6c6f4efa7 100644 --- a/drivers/cpufreq/sc520_freq.c +++ b/drivers/cpufreq/sc520_freq.c @@ -147,7 +147,6 @@ static struct cpufreq_driver sc520_freq_driver = { .init = sc520_freq_cpu_init, .exit = sc520_freq_cpu_exit, .name = "sc520_freq", - .owner = THIS_MODULE, .attr = sc520_freq_attr, }; diff --git a/drivers/cpufreq/sh-cpufreq.c b/drivers/cpufreq/sh-cpufreq.c index 73adb64651e8..ffc6d24b0cfb 100644 --- a/drivers/cpufreq/sh-cpufreq.c +++ b/drivers/cpufreq/sh-cpufreq.c @@ -160,7 +160,6 @@ static struct freq_attr *sh_freq_attr[] = { }; static struct cpufreq_driver sh_cpufreq_driver = { - .owner = THIS_MODULE, .name = "sh", .get = sh_cpufreq_get, .target = sh_cpufreq_target, diff --git a/drivers/cpufreq/sparc-us2e-cpufreq.c b/drivers/cpufreq/sparc-us2e-cpufreq.c index 7c43a725e5da..cf5bc2ca16fa 100644 --- a/drivers/cpufreq/sparc-us2e-cpufreq.c +++ b/drivers/cpufreq/sparc-us2e-cpufreq.c @@ -365,7 +365,6 @@ static int __init us2e_freq_init(void) driver->target = us2e_freq_target; driver->get = us2e_freq_get; driver->exit = us2e_freq_cpu_exit; - driver->owner = THIS_MODULE, strcpy(driver->name, "UltraSPARC-IIe"); cpufreq_us2e_driver = driver; diff --git a/drivers/cpufreq/sparc-us3-cpufreq.c b/drivers/cpufreq/sparc-us3-cpufreq.c index 7f500c140bc3..ac76b489979d 100644 --- a/drivers/cpufreq/sparc-us3-cpufreq.c +++ b/drivers/cpufreq/sparc-us3-cpufreq.c @@ -226,7 +226,6 @@ static int __init us3_freq_init(void) driver->target = us3_freq_target; driver->get = us3_freq_get; driver->exit = us3_freq_cpu_exit; - driver->owner = THIS_MODULE, strcpy(driver->name, "UltraSPARC-III"); cpufreq_us3_driver = driver; diff --git a/drivers/cpufreq/speedstep-centrino.c b/drivers/cpufreq/speedstep-centrino.c index 0915e712fbdc..f897d5105842 100644 --- a/drivers/cpufreq/speedstep-centrino.c +++ b/drivers/cpufreq/speedstep-centrino.c @@ -575,7 +575,6 @@ static struct cpufreq_driver centrino_driver = { .target = centrino_target, .get = get_cur_freq, .attr = centrino_attr, - .owner = THIS_MODULE, }; /* diff --git a/drivers/cpufreq/speedstep-ich.c b/drivers/cpufreq/speedstep-ich.c index e2e5aa971452..5355abb69afc 100644 --- a/drivers/cpufreq/speedstep-ich.c +++ b/drivers/cpufreq/speedstep-ich.c @@ -378,7 +378,6 @@ static struct cpufreq_driver speedstep_driver = { .init = speedstep_cpu_init, .exit = speedstep_cpu_exit, .get = speedstep_get, - .owner = THIS_MODULE, .attr = speedstep_attr, }; diff --git a/drivers/cpufreq/speedstep-smi.c b/drivers/cpufreq/speedstep-smi.c index f5a6b70ee6c0..abfba4f731eb 100644 --- a/drivers/cpufreq/speedstep-smi.c +++ b/drivers/cpufreq/speedstep-smi.c @@ -375,7 +375,6 @@ static struct cpufreq_driver speedstep_driver = { .exit = speedstep_cpu_exit, .get = speedstep_get, .resume = speedstep_resume, - .owner = THIS_MODULE, .attr = speedstep_attr, }; diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 431a05d4b4c9..d568f3975eeb 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -179,7 +179,6 @@ __ATTR(_name, 0644, show_##_name, store_##_name) struct cpufreq_driver { - struct module *owner; char name[CPUFREQ_NAME_LEN]; u8 flags; /* From 3de9bdeb28638e164d1f0eb38dd68e3f5d2ac95c Mon Sep 17 00:00:00 2001 From: Viresh Kumar Date: Tue, 6 Aug 2013 22:53:13 +0530 Subject: [PATCH 25/25] cpufreq: improve error checking on return values of __cpufreq_governor() The __cpufreq_governor() function can fail in rare cases especially if there are bugs in cpufreq drivers. Thus we must stop processing as soon as this routine fails, otherwise it may result in undefined behavior. This patch adds error checking code whenever this routine is called from any place. Signed-off-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 48 +++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index c9bbfeef92e3..37a687467329 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -874,8 +874,13 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, int ret = 0, has_target = !!cpufreq_driver->target; unsigned long flags; - if (has_target) - __cpufreq_governor(policy, CPUFREQ_GOV_STOP); + if (has_target) { + ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP); + if (ret) { + pr_err("%s: Failed to stop governor\n", __func__); + return ret; + } + } lock_policy_rwsem_write(policy->cpu); @@ -889,8 +894,11 @@ static int cpufreq_add_policy_cpu(struct cpufreq_policy *policy, unlock_policy_rwsem_write(policy->cpu); if (has_target) { - __cpufreq_governor(policy, CPUFREQ_GOV_START); - __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); + if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) || + (ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) { + pr_err("%s: Failed to start governor\n", __func__); + return ret; + } } /* Don't touch sysfs links during light-weight init */ @@ -1172,7 +1180,7 @@ static int __cpufreq_remove_dev(struct device *dev, struct subsys_interface *sif, bool frozen) { unsigned int cpu = dev->id, cpus; - int new_cpu; + int new_cpu, ret; unsigned long flags; struct cpufreq_policy *policy; struct kobject *kobj; @@ -1196,8 +1204,13 @@ static int __cpufreq_remove_dev(struct device *dev, return -EINVAL; } - if (cpufreq_driver->target) - __cpufreq_governor(policy, CPUFREQ_GOV_STOP); + if (cpufreq_driver->target) { + ret = __cpufreq_governor(policy, CPUFREQ_GOV_STOP); + if (ret) { + pr_err("%s: Failed to stop governor\n", __func__); + return ret; + } + } #ifdef CONFIG_HOTPLUG_CPU if (!cpufreq_driver->setpolicy) @@ -1231,8 +1244,15 @@ static int __cpufreq_remove_dev(struct device *dev, /* If cpu is last user of policy, free policy */ if (cpus == 1) { - if (cpufreq_driver->target) - __cpufreq_governor(policy, CPUFREQ_GOV_POLICY_EXIT); + if (cpufreq_driver->target) { + ret = __cpufreq_governor(policy, + CPUFREQ_GOV_POLICY_EXIT); + if (ret) { + pr_err("%s: Failed to exit governor\n", + __func__); + return ret; + } + } if (!frozen) { lock_policy_rwsem_read(cpu); @@ -1263,8 +1283,12 @@ static int __cpufreq_remove_dev(struct device *dev, cpufreq_policy_free(policy); } else { if (cpufreq_driver->target) { - __cpufreq_governor(policy, CPUFREQ_GOV_START); - __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); + if ((ret = __cpufreq_governor(policy, CPUFREQ_GOV_START)) || + (ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS))) { + pr_err("%s: Failed to start governor\n", + __func__); + return ret; + } } } @@ -1912,7 +1936,7 @@ static int __cpufreq_set_policy(struct cpufreq_policy *policy, /* might be a policy change, too, so fall through */ } pr_debug("governor: change or update limits\n"); - __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); + ret = __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS); } error_out: