From 5408211a8f290ace85147858f4e05e18b942f489 Mon Sep 17 00:00:00 2001 From: Dietmar Eggemann Date: Tue, 26 Sep 2017 17:41:06 +0100 Subject: drivers base/arch_topology: free cpumask cpus_to_visit Free cpumask cpus_to_visit in case registering init_cpu_capacity_notifier has failed or the parsing of the cpu capacity-dmips-mhz property is done. The cpumask cpus_to_visit is only used inside the notifier call init_cpu_capacity_callback. Reported-by: Vincent Guittot Signed-off-by: Dietmar Eggemann Acked-by: Vincent Guittot Acked-by: Viresh Kumar Tested-by: Juri Lelli Reviewed-by: Juri Lelli Signed-off-by: Rafael J. Wysocki --- drivers/base/arch_topology.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 41be9ff7d70a..e9bb368f32b3 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -212,6 +212,8 @@ static struct notifier_block init_cpu_capacity_notifier = { static int __init register_cpufreq_notifier(void) { + int ret; + /* * on ACPI-based systems we need to use the default cpu capacity * until we have the necessary code to parse the cpu capacity, so @@ -227,8 +229,13 @@ static int __init register_cpufreq_notifier(void) cpumask_copy(cpus_to_visit, cpu_possible_mask); - return cpufreq_register_notifier(&init_cpu_capacity_notifier, - CPUFREQ_POLICY_NOTIFIER); + ret = cpufreq_register_notifier(&init_cpu_capacity_notifier, + CPUFREQ_POLICY_NOTIFIER); + + if (ret) + free_cpumask_var(cpus_to_visit); + + return ret; } core_initcall(register_cpufreq_notifier); @@ -236,6 +243,7 @@ static void parsing_done_workfn(struct work_struct *work) { cpufreq_unregister_notifier(&init_cpu_capacity_notifier, CPUFREQ_POLICY_NOTIFIER); + free_cpumask_var(cpus_to_visit); } #else -- cgit v1.2.3 From e7d5459dfaf613799915e901189d296bdc7534f9 Mon Sep 17 00:00:00 2001 From: Dietmar Eggemann Date: Tue, 26 Sep 2017 17:41:07 +0100 Subject: cpufreq: provide default frequency-invariance setter function Frequency-invariant accounting support based on the ratio of current frequency and maximum supported frequency is an optional feature an arch can implement. Since there are cpufreq drivers (e.g. cpufreq-dt) which can be build for different arch's a default implementation of the frequency-invariance setter function arch_set_freq_scale() is needed. This default implementation is an empty weak function which will be overwritten by a strong function in case the arch provides one. The setter function passes the cpumask of related (to the frequency change) cpus (online and offline cpus), the (new) current frequency and the maximum supported frequency. Signed-off-by: Dietmar Eggemann Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq.c | 6 ++++++ include/linux/cpufreq.h | 3 +++ 2 files changed, 9 insertions(+) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index ea43b147a7fe..41d148af7748 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -161,6 +161,12 @@ u64 get_cpu_idle_time(unsigned int cpu, u64 *wall, int io_busy) } EXPORT_SYMBOL_GPL(get_cpu_idle_time); +__weak void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq, + unsigned long max_freq) +{ +} +EXPORT_SYMBOL_GPL(arch_set_freq_scale); + /* * This is a generic cpufreq init() routine which can be used by cpufreq * drivers of SMP systems. It will do following: diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index 537ff842ff73..28734ee185a7 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -919,6 +919,9 @@ static inline bool policy_has_boost_freq(struct cpufreq_policy *policy) extern unsigned int arch_freq_get_on_cpu(int cpu); +extern void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq, + unsigned long max_freq); + /* the following are really really optional */ extern struct freq_attr cpufreq_freq_attr_scaling_available_freqs; extern struct freq_attr cpufreq_freq_attr_scaling_boost_freqs; -- cgit v1.2.3 From 518accf2062971344310ee85d7fdab55e8c11337 Mon Sep 17 00:00:00 2001 From: Dietmar Eggemann Date: Tue, 26 Sep 2017 17:41:08 +0100 Subject: cpufreq: arm_big_little: invoke frequency-invariance setter function Call the frequency-invariance setter function arch_set_freq_scale() if the new frequency has been successfully set which is indicated by bL_cpufreq_set_rate() returning 0. Signed-off-by: Dietmar Eggemann Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/arm_big_little.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 17504129fd77..0c41ab3b16eb 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -213,6 +213,7 @@ static int bL_cpufreq_set_target(struct cpufreq_policy *policy, { u32 cpu = policy->cpu, cur_cluster, new_cluster, actual_cluster; unsigned int freqs_new; + int ret; cur_cluster = cpu_to_cluster(cpu); new_cluster = actual_cluster = per_cpu(physical_cluster, cpu); @@ -229,7 +230,14 @@ static int bL_cpufreq_set_target(struct cpufreq_policy *policy, } } - return bL_cpufreq_set_rate(cpu, actual_cluster, new_cluster, freqs_new); + ret = bL_cpufreq_set_rate(cpu, actual_cluster, new_cluster, freqs_new); + + if (!ret) { + arch_set_freq_scale(policy->related_cpus, freqs_new, + policy->cpuinfo.max_freq); + } + + return ret; } static inline u32 get_table_count(struct cpufreq_frequency_table *table) -- cgit v1.2.3 From 400ec74d3b3784a48b09db9518aa2c4b6d4e497f Mon Sep 17 00:00:00 2001 From: Dietmar Eggemann Date: Tue, 26 Sep 2017 17:41:09 +0100 Subject: cpufreq: dt: invoke frequency-invariance setter function Call the frequency-invariance setter function arch_set_freq_scale() if the new frequency has been successfully set which is indicated by dev_pm_opp_set_rate() returning 0. Signed-off-by: Dietmar Eggemann Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq-dt.c b/drivers/cpufreq/cpufreq-dt.c index d83ab94d041a..545946ad0752 100644 --- a/drivers/cpufreq/cpufreq-dt.c +++ b/drivers/cpufreq/cpufreq-dt.c @@ -43,9 +43,17 @@ static struct freq_attr *cpufreq_dt_attr[] = { static int set_target(struct cpufreq_policy *policy, unsigned int index) { struct private_data *priv = policy->driver_data; + unsigned long freq = policy->freq_table[index].frequency; + int ret; + + ret = dev_pm_opp_set_rate(priv->cpu_dev, freq * 1000); - return dev_pm_opp_set_rate(priv->cpu_dev, - policy->freq_table[index].frequency * 1000); + if (!ret) { + arch_set_freq_scale(policy->related_cpus, freq, + policy->cpuinfo.max_freq); + } + + return ret; } /* -- cgit v1.2.3 From 0e27c567d1673137b06aa96bb7aef635fb657dee Mon Sep 17 00:00:00 2001 From: Dietmar Eggemann Date: Tue, 26 Sep 2017 17:41:10 +0100 Subject: drivers base/arch_topology: provide frequency-invariant accounting support Implements the arch-specific (arm and arm64) frequency-invariance setter function arch_set_freq_scale() which provides the following frequency scaling factor: current_freq(cpu) << SCHED_CAPACITY_SHIFT / max_supported_freq(cpu) One possible consumer of the frequency-invariance getter function topology_get_freq_scale() is the Per-Entity Load Tracking (PELT) mechanism of the task scheduler. Allow inlining of topology_get_freq_scale() into the task scheduler fast path (e.g. __update_load_avg_se()) by coding it as a static inline function in the arch topology header file. Signed-off-by: Dietmar Eggemann Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/base/arch_topology.c | 14 ++++++++++++++ include/linux/arch_topology.h | 9 +++++++++ 2 files changed, 23 insertions(+) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index e9bb368f32b3..416ec2f5211d 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -22,6 +22,20 @@ #include #include +DEFINE_PER_CPU(unsigned long, freq_scale) = SCHED_CAPACITY_SCALE; + +void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq, + unsigned long max_freq) +{ + unsigned long scale; + int i; + + scale = (cur_freq << SCHED_CAPACITY_SHIFT) / max_freq; + + for_each_cpu(i, cpus) + per_cpu(freq_scale, i) = scale; +} + static DEFINE_MUTEX(cpu_scale_mutex); static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE; diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h index 716ce587247e..f6e490312e4d 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -5,6 +5,7 @@ #define _LINUX_ARCH_TOPOLOGY_H_ #include +#include void topology_normalize_cpu_scale(void); @@ -16,4 +17,12 @@ unsigned long topology_get_cpu_scale(struct sched_domain *sd, int cpu); void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity); +DECLARE_PER_CPU(unsigned long, freq_scale); + +static inline +unsigned long topology_get_freq_scale(struct sched_domain *sd, int cpu) +{ + return per_cpu(freq_scale, cpu); +} + #endif /* _LINUX_ARCH_TOPOLOGY_H_ */ -- cgit v1.2.3 From 8216f588b52b61ce36fc0080218e4730435e58b7 Mon Sep 17 00:00:00 2001 From: Dietmar Eggemann Date: Tue, 26 Sep 2017 17:41:11 +0100 Subject: drivers base/arch_topology: allow inlining cpu-invariant accounting support Allow inlining of topology_get_cpu_scale() into the task scheduler fast path (e.g. __update_load_avg_se()) by coding it as a static inline function in the arch topology header file. Signed-off-by: Dietmar Eggemann Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/base/arch_topology.c | 7 +------ include/linux/arch_topology.h | 8 +++++++- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/base/arch_topology.c b/drivers/base/arch_topology.c index 416ec2f5211d..aea0b9d521f6 100644 --- a/drivers/base/arch_topology.c +++ b/drivers/base/arch_topology.c @@ -37,12 +37,7 @@ void arch_set_freq_scale(struct cpumask *cpus, unsigned long cur_freq, } static DEFINE_MUTEX(cpu_scale_mutex); -static DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE; - -unsigned long topology_get_cpu_scale(struct sched_domain *sd, int cpu) -{ - return per_cpu(cpu_scale, cpu); -} +DEFINE_PER_CPU(unsigned long, cpu_scale) = SCHED_CAPACITY_SCALE; void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity) { diff --git a/include/linux/arch_topology.h b/include/linux/arch_topology.h index f6e490312e4d..c189de3ef5df 100644 --- a/include/linux/arch_topology.h +++ b/include/linux/arch_topology.h @@ -12,8 +12,14 @@ void topology_normalize_cpu_scale(void); struct device_node; bool topology_parse_cpu_capacity(struct device_node *cpu_node, int cpu); +DECLARE_PER_CPU(unsigned long, cpu_scale); + struct sched_domain; -unsigned long topology_get_cpu_scale(struct sched_domain *sd, int cpu); +static inline +unsigned long topology_get_cpu_scale(struct sched_domain *sd, int cpu) +{ + return per_cpu(cpu_scale, cpu); +} void topology_set_cpu_scale(unsigned int cpu, unsigned long capacity); -- cgit v1.2.3 From 3a1ed9cfaf2849195886b80274008526ff2b5f02 Mon Sep 17 00:00:00 2001 From: Dietmar Eggemann Date: Tue, 26 Sep 2017 17:41:12 +0100 Subject: arm: wire frequency-invariant accounting support up to the task scheduler Commit dfbca41f3479 ("sched: Optimize freq invariant accounting") changed the wiring which now has to be done by associating arch_scale_freq_capacity with the actual implementation provided by the architecture. Define arch_scale_freq_capacity to use the arch_topology "driver" function topology_get_freq_scale() for the task scheduler's frequency-invariant accounting instead of the default arch_scale_freq_capacity() in kernel/sched/sched.h. Signed-off-by: Dietmar Eggemann Acked-by: Vincent Guittot Acked-by: Russell King Tested-by: Juri Lelli Reviewed-by: Juri Lelli Signed-off-by: Rafael J. Wysocki --- arch/arm/include/asm/topology.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h index 370f7a732900..a56a9e24f4c0 100644 --- a/arch/arm/include/asm/topology.h +++ b/arch/arm/include/asm/topology.h @@ -24,6 +24,11 @@ void init_cpu_topology(void); void store_cpu_topology(unsigned int cpuid); const struct cpumask *cpu_coregroup_mask(int cpu); +#include + +/* Replace task scheduler's default frequency-invariant accounting */ +#define arch_scale_freq_capacity topology_get_freq_scale + #else static inline void init_cpu_topology(void) { } -- cgit v1.2.3 From 552c4653bf89147c945bd676d28d4746c9500002 Mon Sep 17 00:00:00 2001 From: Dietmar Eggemann Date: Tue, 26 Sep 2017 17:41:13 +0100 Subject: arm: wire cpu-invariant accounting support up to the task scheduler Commit 8cd5601c5060 ("sched/fair: Convert arch_scale_cpu_capacity() from weak function to #define") changed the wiring which now has to be done by associating arch_scale_cpu_capacity with the actual implementation provided by the architecture. Define arch_scale_cpu_capacity to use the arch_topology "driver" function topology_get_cpu_scale() for the task scheduler's cpu-invariant accounting instead of the default arch_scale_cpu_capacity() in kernel/sched/sched.h. Signed-off-by: Dietmar Eggemann Acked-by: Vincent Guittot Acked-by: Russell King Tested-by: Juri Lelli Reviewed-by: Juri Lelli Signed-off-by: Rafael J. Wysocki --- arch/arm/include/asm/topology.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/include/asm/topology.h b/arch/arm/include/asm/topology.h index a56a9e24f4c0..b713e7223bc4 100644 --- a/arch/arm/include/asm/topology.h +++ b/arch/arm/include/asm/topology.h @@ -29,6 +29,9 @@ const struct cpumask *cpu_coregroup_mask(int cpu); /* Replace task scheduler's default frequency-invariant accounting */ #define arch_scale_freq_capacity topology_get_freq_scale +/* Replace task scheduler's default cpu-invariant accounting */ +#define arch_scale_cpu_capacity topology_get_cpu_scale + #else static inline void init_cpu_topology(void) { } -- cgit v1.2.3 From 4e63ebe50d456d7284600822d414d69da35f6977 Mon Sep 17 00:00:00 2001 From: Dietmar Eggemann Date: Tue, 26 Sep 2017 17:41:14 +0100 Subject: arm64: wire frequency-invariant accounting support up to the task scheduler Commit dfbca41f3479 ("sched: Optimize freq invariant accounting") changed the wiring which now has to be done by associating arch_scale_freq_capacity with the actual implementation provided by the architecture. Define arch_scale_freq_capacity to use the arch_topology "driver" function topology_get_freq_scale() for the task scheduler's frequency-invariant accounting instead of the default arch_scale_freq_capacity() in kernel/sched/sched.h. Signed-off-by: Dietmar Eggemann Acked-by: Catalin Marinas Acked-by: Vincent Guittot Tested-by: Juri Lelli Reviewed-by: Juri Lelli Signed-off-by: Rafael J. Wysocki --- arch/arm64/include/asm/topology.h | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h index 8b57339823e9..44598a86ec4a 100644 --- a/arch/arm64/include/asm/topology.h +++ b/arch/arm64/include/asm/topology.h @@ -32,6 +32,11 @@ int pcibus_to_node(struct pci_bus *bus); #endif /* CONFIG_NUMA */ +#include + +/* Replace task scheduler's default frequency-invariant accounting */ +#define arch_scale_freq_capacity topology_get_freq_scale + #include #endif /* _ASM_ARM_TOPOLOGY_H */ -- cgit v1.2.3 From 431ead0ff19b440b1ba25c72d732190b44615cdb Mon Sep 17 00:00:00 2001 From: Dietmar Eggemann Date: Tue, 26 Sep 2017 17:41:15 +0100 Subject: arm64: wire cpu-invariant accounting support up to the task scheduler Commit 8cd5601c5060 ("sched/fair: Convert arch_scale_cpu_capacity() from weak function to #define") changed the wiring which now has to be done by associating arch_scale_cpu_capacity with the actual implementation provided by the architecture. Define arch_scale_cpu_capacity to use the arch_topology "driver" function topology_get_cpu_scale() for the task scheduler's cpu-invariant accounting instead of the default arch_scale_cpu_capacity() in kernel/sched/sched.h. Signed-off-by: Dietmar Eggemann Acked-by: Catalin Marinas Acked-by: Vincent Guittot Tested-by: Juri Lelli Reviewed-by: Juri Lelli Signed-off-by: Rafael J. Wysocki --- arch/arm64/include/asm/topology.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm64/include/asm/topology.h b/arch/arm64/include/asm/topology.h index 44598a86ec4a..e313eeb10756 100644 --- a/arch/arm64/include/asm/topology.h +++ b/arch/arm64/include/asm/topology.h @@ -37,6 +37,9 @@ int pcibus_to_node(struct pci_bus *bus); /* Replace task scheduler's default frequency-invariant accounting */ #define arch_scale_freq_capacity topology_get_freq_scale +/* Replace task scheduler's default cpu-invariant accounting */ +#define arch_scale_cpu_capacity topology_get_cpu_scale + #include #endif /* _ASM_ARM_TOPOLOGY_H */ -- cgit v1.2.3 From 3eba6e121155d56e2b50305a48fa11749c503a2e Mon Sep 17 00:00:00 2001 From: Masahiro Yamada Date: Wed, 30 Aug 2017 00:37:03 +0900 Subject: cpufreq: dt-platdev: drop socionext,uniphier-ld6b from whitelist As you see arch/arm/boot/dts/uniphier-ld6b.dtsi, it includes uniphier-pxs2.dtsi, which uses "operating-points-v2" property and whose cpufreq device is automatically created. Signed-off-by: Masahiro Yamada Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt-platdev.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index a753c50e9e41..de659fc564f4 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -83,8 +83,6 @@ static const struct of_device_id whitelist[] __initconst = { { .compatible = "rockchip,rk3368", }, { .compatible = "rockchip,rk3399", }, - { .compatible = "socionext,uniphier-ld6b", }, - { .compatible = "st-ericsson,u8500", }, { .compatible = "st-ericsson,u8540", }, { .compatible = "st-ericsson,u9500", }, -- cgit v1.2.3 From 86d806b55fb9a8b99c8a4802d27c771dabecc206 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 25 Sep 2017 15:10:11 +0530 Subject: cpufreq: powernow-k8: pr_err() strings should end with newlines pr_err() messages should terminated with a new-line to avoid other messages being concatenated onto the end. Signed-off-by: Arvind Yadav Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/powernow-k8.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c index 062d71434e47..b01e31db5f83 100644 --- a/drivers/cpufreq/powernow-k8.c +++ b/drivers/cpufreq/powernow-k8.c @@ -1043,7 +1043,7 @@ static int powernowk8_cpu_init(struct cpufreq_policy *pol) data = kzalloc(sizeof(*data), GFP_KERNEL); if (!data) { - pr_err("unable to alloc powernow_k8_data"); + pr_err("unable to alloc powernow_k8_data\n"); return -ENOMEM; } -- cgit v1.2.3 From 699b52528eff8863e2c104d22d444d229236ce62 Mon Sep 17 00:00:00 2001 From: Arvind Yadav Date: Mon, 25 Sep 2017 15:43:49 +0530 Subject: cpufreq: SPEAr: pr_err() strings should end with newlines pr_err() messages should terminated with a new-line to avoid other messages being concatenated onto the end. Signed-off-by: Arvind Yadav Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/spear-cpufreq.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/spear-cpufreq.c b/drivers/cpufreq/spear-cpufreq.c index 4894924a3ca2..195f27f9c1cb 100644 --- a/drivers/cpufreq/spear-cpufreq.c +++ b/drivers/cpufreq/spear-cpufreq.c @@ -177,7 +177,7 @@ static int spear_cpufreq_probe(struct platform_device *pdev) np = of_cpu_device_node_get(0); if (!np) { - pr_err("No cpu node found"); + pr_err("No cpu node found\n"); return -ENODEV; } @@ -187,7 +187,7 @@ static int spear_cpufreq_probe(struct platform_device *pdev) prop = of_find_property(np, "cpufreq_tbl", NULL); if (!prop || !prop->value) { - pr_err("Invalid cpufreq_tbl"); + pr_err("Invalid cpufreq_tbl\n"); ret = -ENODEV; goto out_put_node; } -- cgit v1.2.3 From 05829d9431df1bf6de98679fbcfbad282c1c55a4 Mon Sep 17 00:00:00 2001 From: Zumeng Chen Date: Wed, 27 Sep 2017 15:08:17 +0800 Subject: cpufreq: ti-cpufreq: kfree opp_data when failure memory leakage was found by kmemleak. opp_data needs to be freed when failure, including fail_put_node. unreferenced object 0xccdd4c40 (size 64): comm "swapper", pid 1, jiffies 4294938465 (age 888.520s) hex dump (first 32 bytes): 00 7c 00 c1 98 69 d8 ce 00 24 03 ce 00 24 03 ce .|...i...$...$.. 20 35 23 c1 00 00 00 00 00 00 00 00 00 00 00 00 5#............. backtrace: [] kmem_cache_alloc_trace+0x2c4/0x3cc [] ti_cpufreq_probe+0x6c/0x334 [] platform_drv_probe+0x60/0xc0 [] driver_probe_device+0x218/0x2c4 [] __device_attach_driver+0xa8/0xdc [] bus_for_each_drv+0x70/0xa4 [] __device_attach+0xc0/0x124 [] device_initial_probe+0x1c/0x20 [] bus_probe_device+0x94/0x9c [] device_add+0x404/0x590 [] platform_device_add+0x11c/0x230 [] platform_device_register_full+0x10c/0x128 [] ti_cpufreq_init+0x44/0x50 [] do_one_initcall+0x54/0x180 [] kernel_init_freeable+0x270/0x33c [] kernel_init+0x18/0x124 Signed-off-by: Zumeng Chen Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/ti-cpufreq.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c index 4bf47de6101f..ffcddcd4c5e6 100644 --- a/drivers/cpufreq/ti-cpufreq.c +++ b/drivers/cpufreq/ti-cpufreq.c @@ -217,7 +217,8 @@ static int ti_cpufreq_init(void) opp_data->cpu_dev = get_cpu_device(0); if (!opp_data->cpu_dev) { pr_err("%s: Failed to get device for CPU0\n", __func__); - return -ENODEV; + ret = ENODEV; + goto free_opp_data; } opp_data->opp_node = dev_pm_opp_of_get_opp_desc_node(opp_data->cpu_dev); @@ -262,6 +263,8 @@ register_cpufreq_dt: fail_put_node: of_node_put(opp_data->opp_node); +free_opp_data: + kfree(opp_data); return ret; } -- cgit v1.2.3 From 2b3d58a3adca9b7dec9bd289c5c0fda82eeebfa8 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Sat, 30 Sep 2017 12:16:46 -0300 Subject: cpufreq: imx6q: Move speed grading check to cpufreq driver On some i.MX6 SoCs (like i.MX6SL, i.MX6SX and i.MX6UL) that do not have speed grading check, opp table will not be created in platform code, so cpufreq driver prints the following error message: cpu cpu0: dev_pm_opp_get_opp_count: OPP table not found (-19) However, this is not really an error in this case because the imx6q-cpufreq driver first calls dev_pm_opp_get_opp_count() and if it fails, it means that platform code does not provide OPP and then dev_pm_opp_of_add_table() will be called. In order to avoid such confusing error message, move the speed grading check from platform code to the imx6q-cpufreq driver. This way the imx6q-cpufreq no longer has to check whether OPP table is supplied by platform code. Tested on a i.MX6Q and i.MX6UL based boards. Signed-off-by: Fabio Estevam Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- arch/arm/mach-imx/mach-imx6q.c | 88 +---------------------------------------- drivers/cpufreq/imx6q-cpufreq.c | 85 +++++++++++++++++++++++++++++---------- 2 files changed, 67 insertions(+), 106 deletions(-) diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c index 45801b27ee5c..b5f89fdbbb4b 100644 --- a/arch/arm/mach-imx/mach-imx6q.c +++ b/arch/arm/mach-imx/mach-imx6q.c @@ -286,88 +286,6 @@ static void __init imx6q_init_machine(void) imx6q_axi_init(); } -#define OCOTP_CFG3 0x440 -#define OCOTP_CFG3_SPEED_SHIFT 16 -#define OCOTP_CFG3_SPEED_1P2GHZ 0x3 -#define OCOTP_CFG3_SPEED_996MHZ 0x2 -#define OCOTP_CFG3_SPEED_852MHZ 0x1 - -static void __init imx6q_opp_check_speed_grading(struct device *cpu_dev) -{ - struct device_node *np; - void __iomem *base; - u32 val; - - np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp"); - if (!np) { - pr_warn("failed to find ocotp node\n"); - return; - } - - base = of_iomap(np, 0); - if (!base) { - pr_warn("failed to map ocotp\n"); - goto put_node; - } - - /* - * SPEED_GRADING[1:0] defines the max speed of ARM: - * 2b'11: 1200000000Hz; - * 2b'10: 996000000Hz; - * 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz. - * 2b'00: 792000000Hz; - * We need to set the max speed of ARM according to fuse map. - */ - val = readl_relaxed(base + OCOTP_CFG3); - val >>= OCOTP_CFG3_SPEED_SHIFT; - val &= 0x3; - - if ((val != OCOTP_CFG3_SPEED_1P2GHZ) && cpu_is_imx6q()) - if (dev_pm_opp_disable(cpu_dev, 1200000000)) - pr_warn("failed to disable 1.2 GHz OPP\n"); - if (val < OCOTP_CFG3_SPEED_996MHZ) - if (dev_pm_opp_disable(cpu_dev, 996000000)) - pr_warn("failed to disable 996 MHz OPP\n"); - if (cpu_is_imx6q()) { - if (val != OCOTP_CFG3_SPEED_852MHZ) - if (dev_pm_opp_disable(cpu_dev, 852000000)) - pr_warn("failed to disable 852 MHz OPP\n"); - } - iounmap(base); -put_node: - of_node_put(np); -} - -static void __init imx6q_opp_init(void) -{ - struct device_node *np; - struct device *cpu_dev = get_cpu_device(0); - - if (!cpu_dev) { - pr_warn("failed to get cpu0 device\n"); - return; - } - np = of_node_get(cpu_dev->of_node); - if (!np) { - pr_warn("failed to find cpu0 node\n"); - return; - } - - if (dev_pm_opp_of_add_table(cpu_dev)) { - pr_warn("failed to init OPP table\n"); - goto put_node; - } - - imx6q_opp_check_speed_grading(cpu_dev); - -put_node: - of_node_put(np); -} - -static struct platform_device imx6q_cpufreq_pdev = { - .name = "imx6q-cpufreq", -}; - static void __init imx6q_init_late(void) { /* @@ -377,10 +295,8 @@ static void __init imx6q_init_late(void) if (imx_get_soc_revision() > IMX_CHIP_REVISION_1_1) imx6q_cpuidle_init(); - if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) { - imx6q_opp_init(); - platform_device_register(&imx6q_cpufreq_pdev); - } + if (IS_ENABLED(CONFIG_ARM_IMX6Q_CPUFREQ)) + platform_device_register_simple("imx6q-cpufreq", -1, NULL, 0); } static void __init imx6q_map_io(void) diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c index 14466a9b01c0..628fe899cb48 100644 --- a/drivers/cpufreq/imx6q-cpufreq.c +++ b/drivers/cpufreq/imx6q-cpufreq.c @@ -12,6 +12,7 @@ #include #include #include +#include #include #include #include @@ -191,6 +192,57 @@ static struct cpufreq_driver imx6q_cpufreq_driver = { .suspend = cpufreq_generic_suspend, }; +#define OCOTP_CFG3 0x440 +#define OCOTP_CFG3_SPEED_SHIFT 16 +#define OCOTP_CFG3_SPEED_1P2GHZ 0x3 +#define OCOTP_CFG3_SPEED_996MHZ 0x2 +#define OCOTP_CFG3_SPEED_852MHZ 0x1 + +static void imx6q_opp_check_speed_grading(struct device *dev) +{ + struct device_node *np; + void __iomem *base; + u32 val; + + np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-ocotp"); + if (!np) + return; + + base = of_iomap(np, 0); + if (!base) { + dev_err(dev, "failed to map ocotp\n"); + goto put_node; + } + + /* + * SPEED_GRADING[1:0] defines the max speed of ARM: + * 2b'11: 1200000000Hz; + * 2b'10: 996000000Hz; + * 2b'01: 852000000Hz; -- i.MX6Q Only, exclusive with 996MHz. + * 2b'00: 792000000Hz; + * We need to set the max speed of ARM according to fuse map. + */ + val = readl_relaxed(base + OCOTP_CFG3); + val >>= OCOTP_CFG3_SPEED_SHIFT; + val &= 0x3; + + if ((val != OCOTP_CFG3_SPEED_1P2GHZ) && + of_machine_is_compatible("fsl,imx6q")) + if (dev_pm_opp_disable(dev, 1200000000)) + dev_warn(dev, "failed to disable 1.2GHz OPP\n"); + if (val < OCOTP_CFG3_SPEED_996MHZ) + if (dev_pm_opp_disable(dev, 996000000)) + dev_warn(dev, "failed to disable 996MHz OPP\n"); + if (of_machine_is_compatible("fsl,imx6q")) { + if (val != OCOTP_CFG3_SPEED_852MHZ) + if (dev_pm_opp_disable(dev, 852000000)) + dev_warn(dev, "failed to disable 852MHz OPP\n"); + } + iounmap(base); +put_node: + of_node_put(np); +} + static int imx6q_cpufreq_probe(struct platform_device *pdev) { struct device_node *np; @@ -252,28 +304,21 @@ static int imx6q_cpufreq_probe(struct platform_device *pdev) goto put_reg; } - /* - * We expect an OPP table supplied by platform. - * Just, incase the platform did not supply the OPP - * table, it will try to get it. - */ - num = dev_pm_opp_get_opp_count(cpu_dev); - if (num < 0) { - ret = dev_pm_opp_of_add_table(cpu_dev); - if (ret < 0) { - dev_err(cpu_dev, "failed to init OPP table: %d\n", ret); - goto put_reg; - } + ret = dev_pm_opp_of_add_table(cpu_dev); + if (ret < 0) { + dev_err(cpu_dev, "failed to init OPP table: %d\n", ret); + goto put_reg; + } - /* Because we have added the OPPs here, we must free them */ - free_opp = true; + imx6q_opp_check_speed_grading(cpu_dev); - num = dev_pm_opp_get_opp_count(cpu_dev); - if (num < 0) { - ret = num; - dev_err(cpu_dev, "no OPP table is found: %d\n", ret); - goto out_free_opp; - } + /* Because we have added the OPPs here, we must free them */ + free_opp = true; + num = dev_pm_opp_get_opp_count(cpu_dev); + if (num < 0) { + ret = num; + dev_err(cpu_dev, "no OPP table is found: %d\n", ret); + goto out_free_opp; } ret = dev_pm_opp_init_cpufreq_table(cpu_dev, &freq_table); -- cgit v1.2.3 From 11f2c0d77ca856ce146a3e05e7bdfc0c5e6e0f61 Mon Sep 17 00:00:00 2001 From: Marek Szyprowski Date: Wed, 4 Oct 2017 08:38:28 +0200 Subject: cpufreq: dt: Remove support for Exynos4212 SoCs Support for Exynos4212 SoCs has been removed by commit bca9085e0ae9 "ARM: dts: exynos: remove Exynos4212 support (dead code)", so there is no need to keep remaining dead code related to this SoC version. Signed-off-by: Marek Szyprowski Acked-by: Viresh Kumar Acked-by: Krzysztof Kozlowski Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/cpufreq-dt-platdev.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/cpufreq/cpufreq-dt-platdev.c b/drivers/cpufreq/cpufreq-dt-platdev.c index de659fc564f4..ecc56e26f8f6 100644 --- a/drivers/cpufreq/cpufreq-dt-platdev.c +++ b/drivers/cpufreq/cpufreq-dt-platdev.c @@ -48,7 +48,6 @@ static const struct of_device_id whitelist[] __initconst = { { .compatible = "samsung,exynos3250", }, { .compatible = "samsung,exynos4210", }, - { .compatible = "samsung,exynos4212", }, { .compatible = "samsung,exynos5250", }, #ifndef CONFIG_BL_SWITCHER { .compatible = "samsung,exynos5800", }, -- cgit v1.2.3 From 248aefdcc3a7e0cfbd014946b4dead63e750e71b Mon Sep 17 00:00:00 2001 From: Zumeng Chen Date: Tue, 10 Oct 2017 21:27:20 +0800 Subject: cpufreq: ti-cpufreq: add missing of_node_put() call of_node_put to release the refcount of np. Signed-off-by: Zumeng Chen Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/ti-cpufreq.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/ti-cpufreq.c b/drivers/cpufreq/ti-cpufreq.c index ffcddcd4c5e6..923317f03b4b 100644 --- a/drivers/cpufreq/ti-cpufreq.c +++ b/drivers/cpufreq/ti-cpufreq.c @@ -205,6 +205,7 @@ static int ti_cpufreq_init(void) np = of_find_node_by_path("/"); match = of_match_node(ti_cpufreq_of_match, np); + of_node_put(np); if (!match) return -ENODEV; -- cgit v1.2.3 From 9bc70e6919f8cab80d5b240493007e4cce85559c Mon Sep 17 00:00:00 2001 From: "Gustavo A. R. Silva" Date: Thu, 12 Oct 2017 17:41:03 -0500 Subject: cpufreq: speedstep-lib: mark expected switch fall-through In preparation to enabling -Wimplicit-fallthrough, mark switch cases where we are expecting to fall through. Signed-off-by: Gustavo A. R. Silva Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/speedstep-lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/speedstep-lib.c b/drivers/cpufreq/speedstep-lib.c index ccab452a4ef5..8085ec9000d1 100644 --- a/drivers/cpufreq/speedstep-lib.c +++ b/drivers/cpufreq/speedstep-lib.c @@ -367,7 +367,7 @@ unsigned int speedstep_detect_processor(void) } else return SPEEDSTEP_CPU_PIII_C; } - + /* fall through */ default: return 0; } -- cgit v1.2.3 From d9278077385fd9207c00104fe6797283a099b061 Mon Sep 17 00:00:00 2001 From: Robert Jarzmik Date: Sat, 14 Oct 2017 23:51:02 +0200 Subject: cpufreq: pxa: convert to clock API As the clock settings have been introduced into the clock pxa drivers, which are now available to change the CPU clock by themselves, remove the clock handling from this driver, and rely on pxa clock drivers. Signed-off-by: Robert Jarzmik Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/pxa2xx-cpufreq.c | 191 ++++++++------------------------------- 1 file changed, 39 insertions(+), 152 deletions(-) diff --git a/drivers/cpufreq/pxa2xx-cpufreq.c b/drivers/cpufreq/pxa2xx-cpufreq.c index ce345bf34d5d..06b024a3e474 100644 --- a/drivers/cpufreq/pxa2xx-cpufreq.c +++ b/drivers/cpufreq/pxa2xx-cpufreq.c @@ -58,56 +58,40 @@ module_param(pxa27x_maxfreq, uint, 0); MODULE_PARM_DESC(pxa27x_maxfreq, "Set the pxa27x maxfreq in MHz" "(typically 624=>pxa270, 416=>pxa271, 520=>pxa272)"); +struct pxa_cpufreq_data { + struct clk *clk_core; +}; +static struct pxa_cpufreq_data pxa_cpufreq_data; + struct pxa_freqs { unsigned int khz; - unsigned int membus; - unsigned int cccr; - unsigned int div2; - unsigned int cclkcfg; int vmin; int vmax; }; -/* Define the refresh period in mSec for the SDRAM and the number of rows */ -#define SDRAM_TREF 64 /* standard 64ms SDRAM */ -static unsigned int sdram_rows; - -#define CCLKCFG_TURBO 0x1 -#define CCLKCFG_FCS 0x2 -#define CCLKCFG_HALFTURBO 0x4 -#define CCLKCFG_FASTBUS 0x8 -#define MDREFR_DB2_MASK (MDREFR_K2DB2 | MDREFR_K1DB2) -#define MDREFR_DRI_MASK 0xFFF - -#define MDCNFG_DRAC2(mdcnfg) (((mdcnfg) >> 21) & 0x3) -#define MDCNFG_DRAC0(mdcnfg) (((mdcnfg) >> 5) & 0x3) - /* * PXA255 definitions */ -/* Use the run mode frequencies for the CPUFREQ_POLICY_PERFORMANCE policy */ -#define CCLKCFG CCLKCFG_TURBO | CCLKCFG_FCS - static const struct pxa_freqs pxa255_run_freqs[] = { - /* CPU MEMBUS CCCR DIV2 CCLKCFG run turbo PXbus SDRAM */ - { 99500, 99500, 0x121, 1, CCLKCFG, -1, -1}, /* 99, 99, 50, 50 */ - {132700, 132700, 0x123, 1, CCLKCFG, -1, -1}, /* 133, 133, 66, 66 */ - {199100, 99500, 0x141, 0, CCLKCFG, -1, -1}, /* 199, 199, 99, 99 */ - {265400, 132700, 0x143, 1, CCLKCFG, -1, -1}, /* 265, 265, 133, 66 */ - {331800, 165900, 0x145, 1, CCLKCFG, -1, -1}, /* 331, 331, 166, 83 */ - {398100, 99500, 0x161, 0, CCLKCFG, -1, -1}, /* 398, 398, 196, 99 */ + /* CPU MEMBUS run turbo PXbus SDRAM */ + { 99500, -1, -1}, /* 99, 99, 50, 50 */ + {132700, -1, -1}, /* 133, 133, 66, 66 */ + {199100, -1, -1}, /* 199, 199, 99, 99 */ + {265400, -1, -1}, /* 265, 265, 133, 66 */ + {331800, -1, -1}, /* 331, 331, 166, 83 */ + {398100, -1, -1}, /* 398, 398, 196, 99 */ }; /* Use the turbo mode frequencies for the CPUFREQ_POLICY_POWERSAVE policy */ static const struct pxa_freqs pxa255_turbo_freqs[] = { - /* CPU MEMBUS CCCR DIV2 CCLKCFG run turbo PXbus SDRAM */ - { 99500, 99500, 0x121, 1, CCLKCFG, -1, -1}, /* 99, 99, 50, 50 */ - {199100, 99500, 0x221, 0, CCLKCFG, -1, -1}, /* 99, 199, 50, 99 */ - {298500, 99500, 0x321, 0, CCLKCFG, -1, -1}, /* 99, 287, 50, 99 */ - {298600, 99500, 0x1c1, 0, CCLKCFG, -1, -1}, /* 199, 287, 99, 99 */ - {398100, 99500, 0x241, 0, CCLKCFG, -1, -1}, /* 199, 398, 99, 99 */ + /* CPU run turbo PXbus SDRAM */ + { 99500, -1, -1}, /* 99, 99, 50, 50 */ + {199100, -1, -1}, /* 99, 199, 50, 99 */ + {298500, -1, -1}, /* 99, 287, 50, 99 */ + {298600, -1, -1}, /* 199, 287, 99, 99 */ + {398100, -1, -1}, /* 199, 398, 99, 99 */ }; #define NUM_PXA25x_RUN_FREQS ARRAY_SIZE(pxa255_run_freqs) @@ -122,47 +106,14 @@ static unsigned int pxa255_turbo_table; module_param(pxa255_turbo_table, uint, 0); MODULE_PARM_DESC(pxa255_turbo_table, "Selects the frequency table (0 = run table, !0 = turbo table)"); -/* - * PXA270 definitions - * - * For the PXA27x: - * Control variables are A, L, 2N for CCCR; B, HT, T for CLKCFG. - * - * A = 0 => memory controller clock from table 3-7, - * A = 1 => memory controller clock = system bus clock - * Run mode frequency = 13 MHz * L - * Turbo mode frequency = 13 MHz * L * N - * System bus frequency = 13 MHz * L / (B + 1) - * - * In CCCR: - * A = 1 - * L = 16 oscillator to run mode ratio - * 2N = 6 2 * (turbo mode to run mode ratio) - * - * In CCLKCFG: - * B = 1 Fast bus mode - * HT = 0 Half-Turbo mode - * T = 1 Turbo mode - * - * For now, just support some of the combinations in table 3-7 of - * PXA27x Processor Family Developer's Manual to simplify frequency - * change sequences. - */ -#define PXA27x_CCCR(A, L, N2) (A << 25 | N2 << 7 | L) -#define CCLKCFG2(B, HT, T) \ - (CCLKCFG_FCS | \ - ((B) ? CCLKCFG_FASTBUS : 0) | \ - ((HT) ? CCLKCFG_HALFTURBO : 0) | \ - ((T) ? CCLKCFG_TURBO : 0)) - static struct pxa_freqs pxa27x_freqs[] = { - {104000, 104000, PXA27x_CCCR(1, 8, 2), 0, CCLKCFG2(1, 0, 1), 900000, 1705000 }, - {156000, 104000, PXA27x_CCCR(1, 8, 3), 0, CCLKCFG2(1, 0, 1), 1000000, 1705000 }, - {208000, 208000, PXA27x_CCCR(0, 16, 2), 1, CCLKCFG2(0, 0, 1), 1180000, 1705000 }, - {312000, 208000, PXA27x_CCCR(1, 16, 3), 1, CCLKCFG2(1, 0, 1), 1250000, 1705000 }, - {416000, 208000, PXA27x_CCCR(1, 16, 4), 1, CCLKCFG2(1, 0, 1), 1350000, 1705000 }, - {520000, 208000, PXA27x_CCCR(1, 16, 5), 1, CCLKCFG2(1, 0, 1), 1450000, 1705000 }, - {624000, 208000, PXA27x_CCCR(1, 16, 6), 1, CCLKCFG2(1, 0, 1), 1550000, 1705000 } + {104000, 900000, 1705000 }, + {156000, 1000000, 1705000 }, + {208000, 1180000, 1705000 }, + {312000, 1250000, 1705000 }, + {416000, 1350000, 1705000 }, + {520000, 1450000, 1705000 }, + {624000, 1550000, 1705000 } }; #define NUM_PXA27x_FREQS ARRAY_SIZE(pxa27x_freqs) @@ -241,51 +192,29 @@ static void pxa27x_guess_max_freq(void) } } -static void init_sdram_rows(void) -{ - uint32_t mdcnfg = __raw_readl(MDCNFG); - unsigned int drac2 = 0, drac0 = 0; - - if (mdcnfg & (MDCNFG_DE2 | MDCNFG_DE3)) - drac2 = MDCNFG_DRAC2(mdcnfg); - - if (mdcnfg & (MDCNFG_DE0 | MDCNFG_DE1)) - drac0 = MDCNFG_DRAC0(mdcnfg); - - sdram_rows = 1 << (11 + max(drac0, drac2)); -} - -static u32 mdrefr_dri(unsigned int freq) -{ - u32 interval = freq * SDRAM_TREF / sdram_rows; - - return (interval - (cpu_is_pxa27x() ? 31 : 0)) / 32; -} - static unsigned int pxa_cpufreq_get(unsigned int cpu) { - return get_clk_frequency_khz(0); + struct pxa_cpufreq_data *data = cpufreq_get_driver_data(); + + return (unsigned int) clk_get_rate(data->clk_core) / 1000; } static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx) { struct cpufreq_frequency_table *pxa_freqs_table; const struct pxa_freqs *pxa_freq_settings; - unsigned long flags; - unsigned int new_freq_cpu, new_freq_mem; - unsigned int unused, preset_mdrefr, postset_mdrefr, cclkcfg; + struct pxa_cpufreq_data *data = cpufreq_get_driver_data(); + unsigned int new_freq_cpu; int ret = 0; /* Get the current policy */ find_freq_tables(&pxa_freqs_table, &pxa_freq_settings); new_freq_cpu = pxa_freq_settings[idx].khz; - new_freq_mem = pxa_freq_settings[idx].membus; if (freq_debug) - pr_debug("Changing CPU frequency to %d Mhz, (SDRAM %d Mhz)\n", - new_freq_cpu / 1000, (pxa_freq_settings[idx].div2) ? - (new_freq_mem / 2000) : (new_freq_mem / 1000)); + pr_debug("Changing CPU frequency from %d Mhz to %d Mhz\n", + policy->cur / 1000, new_freq_cpu / 1000); if (vcc_core && new_freq_cpu > policy->cur) { ret = pxa_cpufreq_change_voltage(&pxa_freq_settings[idx]); @@ -293,53 +222,7 @@ static int pxa_set_target(struct cpufreq_policy *policy, unsigned int idx) return ret; } - /* Calculate the next MDREFR. If we're slowing down the SDRAM clock - * we need to preset the smaller DRI before the change. If we're - * speeding up we need to set the larger DRI value after the change. - */ - preset_mdrefr = postset_mdrefr = __raw_readl(MDREFR); - if ((preset_mdrefr & MDREFR_DRI_MASK) > mdrefr_dri(new_freq_mem)) { - preset_mdrefr = (preset_mdrefr & ~MDREFR_DRI_MASK); - preset_mdrefr |= mdrefr_dri(new_freq_mem); - } - postset_mdrefr = - (postset_mdrefr & ~MDREFR_DRI_MASK) | mdrefr_dri(new_freq_mem); - - /* If we're dividing the memory clock by two for the SDRAM clock, this - * must be set prior to the change. Clearing the divide must be done - * after the change. - */ - if (pxa_freq_settings[idx].div2) { - preset_mdrefr |= MDREFR_DB2_MASK; - postset_mdrefr |= MDREFR_DB2_MASK; - } else { - postset_mdrefr &= ~MDREFR_DB2_MASK; - } - - local_irq_save(flags); - - /* Set new the CCCR and prepare CCLKCFG */ - writel(pxa_freq_settings[idx].cccr, CCCR); - cclkcfg = pxa_freq_settings[idx].cclkcfg; - - asm volatile(" \n\ - ldr r4, [%1] /* load MDREFR */ \n\ - b 2f \n\ - .align 5 \n\ -1: \n\ - str %3, [%1] /* preset the MDREFR */ \n\ - mcr p14, 0, %2, c6, c0, 0 /* set CCLKCFG[FCS] */ \n\ - str %4, [%1] /* postset the MDREFR */ \n\ - \n\ - b 3f \n\ -2: b 1b \n\ -3: nop \n\ - " - : "=&r" (unused) - : "r" (MDREFR), "r" (cclkcfg), - "r" (preset_mdrefr), "r" (postset_mdrefr) - : "r4", "r5"); - local_irq_restore(flags); + clk_set_rate(data->clk_core, new_freq_cpu * 1000); /* * Even if voltage setting fails, we don't report it, as the frequency @@ -369,8 +252,6 @@ static int pxa_cpufreq_init(struct cpufreq_policy *policy) pxa_cpufreq_init_voltages(); - init_sdram_rows(); - /* set default policy and cpuinfo */ policy->cpuinfo.transition_latency = 1000; /* FIXME: 1 ms, assumed */ @@ -429,11 +310,17 @@ static struct cpufreq_driver pxa_cpufreq_driver = { .init = pxa_cpufreq_init, .get = pxa_cpufreq_get, .name = "PXA2xx", + .driver_data = &pxa_cpufreq_data, }; static int __init pxa_cpu_init(void) { int ret = -ENODEV; + + pxa_cpufreq_data.clk_core = clk_get_sys(NULL, "core"); + if (IS_ERR(pxa_cpufreq_data.clk_core)) + return PTR_ERR(pxa_cpufreq_data.clk_core); + if (cpu_is_pxa25x() || cpu_is_pxa27x()) ret = cpufreq_register_driver(&pxa_cpufreq_driver); return ret; -- cgit v1.2.3 From cd6ce860eb1920568361cf270fe4f89674cf411b Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Thu, 19 Oct 2017 12:59:14 +0200 Subject: cpufreq: arm_big_little: make function arguments and structure pointer const Make the arguments of functions bL_cpufreq_{register/unregister} as const as the ops pointer does not modify the fields of the cpufreq_arm_bL_ops structure it points to. The pointer arm_bL_ops is also getting initialized with ops but the pointer does not modify the fields. So, make the function argument and the structure pointer const. Add const to function prototypes too. Signed-off-by: Bhumika Goyal Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/arm_big_little.c | 6 +++--- drivers/cpufreq/arm_big_little.h | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/cpufreq/arm_big_little.c b/drivers/cpufreq/arm_big_little.c index 0c41ab3b16eb..65ec5f01aa8d 100644 --- a/drivers/cpufreq/arm_big_little.c +++ b/drivers/cpufreq/arm_big_little.c @@ -57,7 +57,7 @@ static bool bL_switching_enabled; #define VIRT_FREQ(cluster, freq) ((cluster == A7_CLUSTER) ? freq >> 1 : freq) static struct thermal_cooling_device *cdev[MAX_CLUSTERS]; -static struct cpufreq_arm_bL_ops *arm_bL_ops; +static const struct cpufreq_arm_bL_ops *arm_bL_ops; static struct clk *clk[MAX_CLUSTERS]; static struct cpufreq_frequency_table *freq_table[MAX_CLUSTERS + 1]; static atomic_t cluster_usage[MAX_CLUSTERS + 1]; @@ -617,7 +617,7 @@ static int __bLs_register_notifier(void) { return 0; } static int __bLs_unregister_notifier(void) { return 0; } #endif -int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) +int bL_cpufreq_register(const struct cpufreq_arm_bL_ops *ops) { int ret, i; @@ -661,7 +661,7 @@ int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops) } EXPORT_SYMBOL_GPL(bL_cpufreq_register); -void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops) +void bL_cpufreq_unregister(const struct cpufreq_arm_bL_ops *ops) { if (arm_bL_ops != ops) { pr_err("%s: Registered with: %s, can't unregister, exiting\n", diff --git a/drivers/cpufreq/arm_big_little.h b/drivers/cpufreq/arm_big_little.h index 184d7c3a112a..88a176e466c8 100644 --- a/drivers/cpufreq/arm_big_little.h +++ b/drivers/cpufreq/arm_big_little.h @@ -37,7 +37,7 @@ struct cpufreq_arm_bL_ops { void (*free_opp_table)(const struct cpumask *cpumask); }; -int bL_cpufreq_register(struct cpufreq_arm_bL_ops *ops); -void bL_cpufreq_unregister(struct cpufreq_arm_bL_ops *ops); +int bL_cpufreq_register(const struct cpufreq_arm_bL_ops *ops); +void bL_cpufreq_unregister(const struct cpufreq_arm_bL_ops *ops); #endif /* CPUFREQ_ARM_BIG_LITTLE_H */ -- cgit v1.2.3 From 0011c6da99ddc428a35456d5819d6e476005f6f2 Mon Sep 17 00:00:00 2001 From: Bhumika Goyal Date: Thu, 19 Oct 2017 12:59:15 +0200 Subject: cpufreq: arm_big_little: make cpufreq_arm_bL_ops structures const Make these const as they are only getting passed to the functions bL_cpufreq_{register/unregister} having the arguments as const. Signed-off-by: Bhumika Goyal Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/arm_big_little_dt.c | 2 +- drivers/cpufreq/scpi-cpufreq.c | 2 +- drivers/cpufreq/vexpress-spc-cpufreq.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/cpufreq/arm_big_little_dt.c b/drivers/cpufreq/arm_big_little_dt.c index 39b3f51d9a30..b944f290c8a4 100644 --- a/drivers/cpufreq/arm_big_little_dt.c +++ b/drivers/cpufreq/arm_big_little_dt.c @@ -61,7 +61,7 @@ static int dt_get_transition_latency(struct device *cpu_dev) return transition_latency; } -static struct cpufreq_arm_bL_ops dt_bL_ops = { +static const struct cpufreq_arm_bL_ops dt_bL_ops = { .name = "dt-bl", .get_transition_latency = dt_get_transition_latency, .init_opp_table = dev_pm_opp_of_cpumask_add_table, diff --git a/drivers/cpufreq/scpi-cpufreq.c b/drivers/cpufreq/scpi-cpufreq.c index 8de2364b5995..05d299052c5c 100644 --- a/drivers/cpufreq/scpi-cpufreq.c +++ b/drivers/cpufreq/scpi-cpufreq.c @@ -53,7 +53,7 @@ static int scpi_init_opp_table(const struct cpumask *cpumask) return ret; } -static struct cpufreq_arm_bL_ops scpi_cpufreq_ops = { +static const struct cpufreq_arm_bL_ops scpi_cpufreq_ops = { .name = "scpi", .get_transition_latency = scpi_get_transition_latency, .init_opp_table = scpi_init_opp_table, diff --git a/drivers/cpufreq/vexpress-spc-cpufreq.c b/drivers/cpufreq/vexpress-spc-cpufreq.c index 87e5bdc5ec74..53237289e606 100644 --- a/drivers/cpufreq/vexpress-spc-cpufreq.c +++ b/drivers/cpufreq/vexpress-spc-cpufreq.c @@ -42,7 +42,7 @@ static int ve_spc_get_transition_latency(struct device *cpu_dev) return 1000000; /* 1 ms */ } -static struct cpufreq_arm_bL_ops ve_spc_cpufreq_ops = { +static const struct cpufreq_arm_bL_ops ve_spc_cpufreq_ops = { .name = "vexpress-spc", .get_transition_latency = ve_spc_get_transition_latency, .init_opp_table = ve_spc_init_opp_table, -- cgit v1.2.3 From f7bc9b209e27c0b617378400136cc663a6314d0c Mon Sep 17 00:00:00 2001 From: "Gautham R. Shenoy" Date: Tue, 7 Nov 2017 13:39:29 +0530 Subject: cpufreq: stats: Handle the case when trans_table goes beyond PAGE_SIZE On platforms with large number of Pstates, the transition table, which is a NxN matrix, can overflow beyond the PAGE_SIZE boundary. This can be seen on POWER9 which has 100+ Pstates. As a result, each time the trans_table is read for any of the CPUs, we will get the following error. --------------------------------------------------- fill_read_buffer: show+0x0/0xa0 returned bad count --------------------------------------------------- This patch ensures that in case of an overflow, we print a warning once in the dmesg and return FILE TOO LARGE error for this and all subsequent accesses of trans_table. Signed-off-by: Gautham R. Shenoy Acked-by: Viresh Kumar Signed-off-by: Rafael J. Wysocki --- Documentation/cpu-freq/cpufreq-stats.txt | 3 +++ drivers/cpufreq/cpufreq_stats.c | 7 +++++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/Documentation/cpu-freq/cpufreq-stats.txt b/Documentation/cpu-freq/cpufreq-stats.txt index 2bbe207354ed..a873855c811d 100644 --- a/Documentation/cpu-freq/cpufreq-stats.txt +++ b/Documentation/cpu-freq/cpufreq-stats.txt @@ -90,6 +90,9 @@ Freq_i to Freq_j. Freq_i is in descending order with increasing rows and Freq_j is in descending order with increasing columns. The output here also contains the actual freq values for each row and column for better readability. +If the transition table is bigger than PAGE_SIZE, reading this will +return an -EFBIG error. + -------------------------------------------------------------------------------- :/sys/devices/system/cpu/cpu0/cpufreq/stats # cat trans_table From : To diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c index e75880eb037d..1e55b5790853 100644 --- a/drivers/cpufreq/cpufreq_stats.c +++ b/drivers/cpufreq/cpufreq_stats.c @@ -118,8 +118,11 @@ static ssize_t show_trans_table(struct cpufreq_policy *policy, char *buf) break; len += snprintf(buf + len, PAGE_SIZE - len, "\n"); } - if (len >= PAGE_SIZE) - return PAGE_SIZE; + + if (len >= PAGE_SIZE) { + pr_warn_once("cpufreq transition table exceeds PAGE_SIZE. Disabling\n"); + return -EFBIG; + } return len; } cpufreq_freq_attr_ro(trans_table); -- cgit v1.2.3