From: Park Bumgyu Date: Wed, 14 Mar 2018 10:45:28 +0000 (+0900) Subject: cpufreq: acme: disable cluster-wide power mode while getting/setting frequency X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=862aee9e42aad2bb3b9b35af64c6cfe266fd5497;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git cpufreq: acme: disable cluster-wide power mode while getting/setting frequency Change-Id: I0d999d112d4785544e3f89b41055e51f55bf1921 Signed-off-by: Park Bumgyu --- diff --git a/drivers/cpufreq/exynos-acme.c b/drivers/cpufreq/exynos-acme.c index 204306e05d60..763c5482b8e3 100644 --- a/drivers/cpufreq/exynos-acme.c +++ b/drivers/cpufreq/exynos-acme.c @@ -26,6 +26,7 @@ #include #include #include +#include #include "exynos-acme.h" @@ -134,13 +135,24 @@ static unsigned int index_to_freq(struct cpufreq_frequency_table *table, /********************************************************************* * FREQUENCY SCALING * *********************************************************************/ +/* + * Depending on cluster structure, it cannot be possible to get/set + * cpu frequency while cluster is off. For this, disable cluster-wide + * power mode while getting/setting frequency. + */ static unsigned int get_freq(struct exynos_cpufreq_domain *domain) { - unsigned int freq = (unsigned int)cal_dfs_get_rate(domain->cal_id); + unsigned int freq; + + disable_power_mode(cpumask_any(&domain->cpus), POWERMODE_TYPE_CLUSTER); - /* On changing state, CAL returns 0 */ - if (!freq) - return domain->old; + freq = (unsigned int)cal_dfs_get_rate(domain->cal_id); + if (!freq) { + /* On changing state, CAL returns 0 */ + freq = domain->old; + } + + enable_power_mode(cpumask_any(&domain->cpus), POWERMODE_TYPE_CLUSTER); return freq; } @@ -150,6 +162,8 @@ static int set_freq(struct exynos_cpufreq_domain *domain, { int err; + disable_power_mode(cpumask_any(&domain->cpus), POWERMODE_TYPE_CLUSTER); + exynos_ss_printk("ID %d: %d -> %d (%d)\n", domain->id, domain->old, target_freq, ESS_FLAG_IN); @@ -161,6 +175,8 @@ static int set_freq(struct exynos_cpufreq_domain *domain, exynos_ss_printk("ID %d: %d -> %d (%d)\n", domain->id, domain->old, target_freq, ESS_FLAG_OUT); + enable_power_mode(cpumask_any(&domain->cpus), POWERMODE_TYPE_CLUSTER); + return err; } diff --git a/drivers/soc/samsung/exynos-cpupm.c b/drivers/soc/samsung/exynos-cpupm.c index 55f6721f3f92..fb6ff4025503 100644 --- a/drivers/soc/samsung/exynos-cpupm.c +++ b/drivers/soc/samsung/exynos-cpupm.c @@ -440,7 +440,7 @@ static void awake_cpus(const struct cpumask *cpus) struct cpumask mask; cpumask_and(&mask, cpus, cpu_online_mask); - smp_call_function_many(&mask, do_nothing, NULL, 0); + smp_call_function_single(cpumask_any(&mask), do_nothing, NULL, 1); } /* @@ -455,13 +455,19 @@ void disable_power_mode(int cpu, int type) struct power_mode *mode; int pos; - spin_lock(&cpupm_lock); pm = &per_cpu(cpupm, cpu); for_each_mode(mode, pm->modes, pos) { if (IS_NULL(mode)) break; + /* + * There are no entry allowed cpus, it means that mode is + * disabled, skip awaking cpus. + */ + if (cpumask_empty(&mode->entry_allowed)) + continue; + if (mode->type == type) { /* * The first mode disable request wakes the cpus to @@ -471,7 +477,6 @@ void disable_power_mode(int cpu, int type) awake_cpus(&mode->siblings); } } - spin_unlock(&cpupm_lock); } void enable_power_mode(int cpu, int type) @@ -480,7 +485,6 @@ void enable_power_mode(int cpu, int type) struct power_mode *mode; int pos; - spin_lock(&cpupm_lock); pm = &per_cpu(cpupm, cpu); for_each_mode(mode, pm->modes, pos) { @@ -490,7 +494,6 @@ void enable_power_mode(int cpu, int type) if (mode->type == type) atomic_dec(&mode->disable); } - spin_unlock(&cpupm_lock); } /* get sleep length of given cpu from tickless framework */ diff --git a/include/soc/samsung/exynos-cpupm.h b/include/soc/samsung/exynos-cpupm.h index 460628c5014c..0914f0557062 100644 --- a/include/soc/samsung/exynos-cpupm.h +++ b/include/soc/samsung/exynos-cpupm.h @@ -17,8 +17,8 @@ enum { POWERMODE_TYPE_SYSTEM, }; -extern void disable_mode(int cpu, int type); -extern void enable_mode(int cpu, int type); +extern void disable_power_mode(int cpu, int type); +extern void enable_power_mode(int cpu, int type); #ifdef CONFIG_CPU_IDLE void exynos_update_ip_idle_status(int index, int idle);