Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d4019f0a authored by Viresh Kumar's avatar Viresh Kumar Committed by Rafael J. Wysocki
Browse files

cpufreq: move freq change notifications to cpufreq core



Most of the drivers do following in their ->target_index() routines:

	struct cpufreq_freqs freqs;
	freqs.old = old freq...
	freqs.new = new freq...

	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);

	/* Change rate here */

	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);

This is replicated over all cpufreq drivers today and there doesn't exists a
good enough reason why this shouldn't be moved to cpufreq core instead.

There are few special cases though, like exynos5440, which doesn't do everything
on the call to ->target_index() routine and call some kind of bottom halves for
doing this work, work/tasklet/etc..

They may continue doing notification from their own code as flag:
CPUFREQ_ASYNC_NOTIFICATION is already set for them.

All drivers are also modified in this patch to avoid breaking 'git bisect', as
double notification would happen otherwise.

Acked-by: default avatarHans-Christian Egtvedt <egtvedt@samfundet.no>
Acked-by: default avatarJesper Nilsson <jesper.nilsson@axis.com>
Acked-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Acked-by: default avatarRussell King <linux@arm.linux.org.uk>
Acked-by: default avatarStephen Warren <swarren@nvidia.com>
Tested-by: default avatarAndrew Lunn <andrew@lunn.ch>
Tested-by: default avatarNicolas Pitre <nicolas.pitre@linaro.org>
Reviewed-by: default avatarLan Tianyu <tianyu.lan@intel.com>
Signed-off-by: default avatarViresh Kumar <viresh.kumar@linaro.org>
Signed-off-by: default avatarRafael J. Wysocki <rafael.j.wysocki@intel.com>
parent 7dbf694d
Loading
Loading
Loading
Loading
+2 −12
Original line number Diff line number Diff line
@@ -428,14 +428,10 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
{
	struct acpi_cpufreq_data *data = per_cpu(acfreq_data, policy->cpu);
	struct acpi_processor_performance *perf;
	struct cpufreq_freqs freqs;
	struct drv_cmd cmd;
	unsigned int next_perf_state = 0; /* Index into perf table */
	int result = 0;

	pr_debug("acpi_cpufreq_target %d (%d)\n",
			data->freq_table[index].frequency, policy->cpu);

	if (unlikely(data == NULL ||
	     data->acpi_data == NULL || data->freq_table == NULL)) {
		return -ENODEV;
@@ -483,23 +479,17 @@ static int acpi_cpufreq_target(struct cpufreq_policy *policy,
	else
		cmd.mask = cpumask_of(policy->cpu);

	freqs.old = perf->states[perf->state].core_frequency * 1000;
	freqs.new = data->freq_table[index].frequency;
	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);

	drv_write(&cmd);

	if (acpi_pstate_strict) {
		if (!check_freqs(cmd.mask, freqs.new, data)) {
		if (!check_freqs(cmd.mask, data->freq_table[index].frequency,
					data)) {
			pr_debug("acpi_cpufreq_target failed (%d)\n",
				policy->cpu);
			result = -EAGAIN;
			freqs.new = freqs.old;
		}
	}

	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);

	if (!result)
		perf->state = next_perf_state;

+5 −19
Original line number Diff line number Diff line
@@ -192,39 +192,25 @@ bL_cpufreq_set_rate(u32 cpu, u32 old_cluster, u32 new_cluster, u32 rate)
static int bL_cpufreq_set_target(struct cpufreq_policy *policy,
		unsigned int index)
{
	struct cpufreq_freqs freqs;
	u32 cpu = policy->cpu, cur_cluster, new_cluster, actual_cluster;
	int ret = 0;
	unsigned int freqs_new;

	cur_cluster = cpu_to_cluster(cpu);
	new_cluster = actual_cluster = per_cpu(physical_cluster, cpu);

	freqs.old = bL_cpufreq_get_rate(cpu);
	freqs.new = freq_table[cur_cluster][index].frequency;

	pr_debug("%s: cpu: %d, cluster: %d, oldfreq: %d, target freq: %d, new freq: %d\n",
			__func__, cpu, cur_cluster, freqs.old, freqs.new,
			freqs.new);
	freqs_new = freq_table[cur_cluster][index].frequency;

	if (is_bL_switching_enabled()) {
		if ((actual_cluster == A15_CLUSTER) &&
				(freqs.new < clk_big_min)) {
				(freqs_new < clk_big_min)) {
			new_cluster = A7_CLUSTER;
		} else if ((actual_cluster == A7_CLUSTER) &&
				(freqs.new > clk_little_max)) {
				(freqs_new > clk_little_max)) {
			new_cluster = A15_CLUSTER;
		}
	}

	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);

	ret = bL_cpufreq_set_rate(cpu, actual_cluster, new_cluster, freqs.new);
	if (ret)
		freqs.new = freqs.old;

	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);

	return ret;
	return bL_cpufreq_set_rate(cpu, actual_cluster, new_cluster, freqs_new);
}

static inline u32 get_table_count(struct cpufreq_frequency_table *table)
+9 −13
Original line number Diff line number Diff line
@@ -37,27 +37,23 @@ static unsigned long loops_per_jiffy_ref;

static int at32_set_target(struct cpufreq_policy *policy, unsigned int index)
{
	struct cpufreq_freqs freqs;
	unsigned int old_freq, new_freq;

	freqs.old = at32_get_speed(0);
	freqs.new = freq_table[index].frequency;
	old_freq = at32_get_speed(0);
	new_freq = freq_table[index].frequency;

	if (!ref_freq) {
		ref_freq = freqs.old;
		ref_freq = old_freq;
		loops_per_jiffy_ref = boot_cpu_data.loops_per_jiffy;
	}

	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
	if (freqs.old < freqs.new)
	if (old_freq < new_freq)
		boot_cpu_data.loops_per_jiffy = cpufreq_scale(
				loops_per_jiffy_ref, ref_freq, freqs.new);
	clk_set_rate(cpuclk, freqs.new * 1000);
	if (freqs.new < freqs.old)
				loops_per_jiffy_ref, ref_freq, new_freq);
	clk_set_rate(cpuclk, new_freq * 1000);
	if (new_freq < old_freq)
		boot_cpu_data.loops_per_jiffy = cpufreq_scale(
				loops_per_jiffy_ref, ref_freq, freqs.new);
	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);

	pr_debug("cpufreq: set frequency %u Hz\n", freqs.new * 1000);
				loops_per_jiffy_ref, ref_freq, new_freq);

	return 0;
}
+7 −15
Original line number Diff line number Diff line
@@ -132,27 +132,23 @@ static int bfin_target(struct cpufreq_policy *policy, unsigned int index)
#ifndef CONFIG_BF60x
	unsigned int plldiv;
#endif
	struct cpufreq_freqs freqs;
	static unsigned long lpj_ref;
	static unsigned int  lpj_ref_freq;
	unsigned int old_freq, new_freq;
	int ret = 0;

#if defined(CONFIG_CYCLES_CLOCKSOURCE)
	cycles_t cycles;
#endif

	freqs.old = bfin_getfreq_khz(0);
	freqs.new = bfin_freq_table[index].frequency;
	old_freq = bfin_getfreq_khz(0);
	new_freq = bfin_freq_table[index].frequency;

	pr_debug("cpufreq: changing cclk to %lu; target = %u, oldfreq = %u\n",
			freqs.new, freqs.new, freqs.old);

	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
#ifndef CONFIG_BF60x
	plldiv = (bfin_read_PLL_DIV() & SSEL) | dpm_state_table[index].csel;
	bfin_write_PLL_DIV(plldiv);
#else
	ret = cpu_set_cclk(policy->cpu, freqs.new * 1000);
	ret = cpu_set_cclk(policy->cpu, new_freq * 1000);
	if (ret != 0) {
		WARN_ONCE(ret, "cpufreq set freq failed %d\n", ret);
		return ret;
@@ -168,17 +164,13 @@ static int bfin_target(struct cpufreq_policy *policy, unsigned int index)
#endif
	if (!lpj_ref_freq) {
		lpj_ref = loops_per_jiffy;
		lpj_ref_freq = freqs.old;
		lpj_ref_freq = old_freq;
	}
	if (freqs.new != freqs.old) {
	if (new_freq != old_freq) {
		loops_per_jiffy = cpufreq_scale(lpj_ref,
				lpj_ref_freq, freqs.new);
				lpj_ref_freq, new_freq);
	}

	/* TODO: just test case for cycles clock source, remove later */
	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);

	pr_debug("cpufreq: done\n");
	return ret;
}

+12 −21
Original line number Diff line number Diff line
@@ -37,20 +37,19 @@ static unsigned int cpu0_get_speed(unsigned int cpu)

static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
{
	struct cpufreq_freqs freqs;
	struct dev_pm_opp *opp;
	unsigned long volt = 0, volt_old = 0, tol = 0;
	unsigned int old_freq, new_freq;
	long freq_Hz, freq_exact;
	int ret;

	freq_Hz = clk_round_rate(cpu_clk, freq_table[index].frequency * 1000);
	if (freq_Hz < 0)
		freq_Hz = freq_table[index].frequency * 1000;
	freq_exact = freq_Hz;
	freqs.new = freq_Hz / 1000;
	freqs.old = clk_get_rate(cpu_clk) / 1000;

	cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE);
	freq_exact = freq_Hz;
	new_freq = freq_Hz / 1000;
	old_freq = clk_get_rate(cpu_clk) / 1000;

	if (!IS_ERR(cpu_reg)) {
		rcu_read_lock();
@@ -58,9 +57,7 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
		if (IS_ERR(opp)) {
			rcu_read_unlock();
			pr_err("failed to find OPP for %ld\n", freq_Hz);
			freqs.new = freqs.old;
			ret = PTR_ERR(opp);
			goto post_notify;
			return PTR_ERR(opp);
		}
		volt = dev_pm_opp_get_voltage(opp);
		rcu_read_unlock();
@@ -69,16 +66,15 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
	}

	pr_debug("%u MHz, %ld mV --> %u MHz, %ld mV\n",
		 freqs.old / 1000, volt_old ? volt_old / 1000 : -1,
		 freqs.new / 1000, volt ? volt / 1000 : -1);
		 old_freq / 1000, volt_old ? volt_old / 1000 : -1,
		 new_freq / 1000, volt ? volt / 1000 : -1);

	/* scaling up?  scale voltage before frequency */
	if (!IS_ERR(cpu_reg) && freqs.new > freqs.old) {
	if (!IS_ERR(cpu_reg) && new_freq > old_freq) {
		ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
		if (ret) {
			pr_err("failed to scale voltage up: %d\n", ret);
			freqs.new = freqs.old;
			goto post_notify;
			return ret;
		}
	}

@@ -87,23 +83,18 @@ static int cpu0_set_target(struct cpufreq_policy *policy, unsigned int index)
		pr_err("failed to set clock rate: %d\n", ret);
		if (!IS_ERR(cpu_reg))
			regulator_set_voltage_tol(cpu_reg, volt_old, tol);
		freqs.new = freqs.old;
		goto post_notify;
		return ret;
	}

	/* scaling down?  scale voltage after frequency */
	if (!IS_ERR(cpu_reg) && freqs.new < freqs.old) {
	if (!IS_ERR(cpu_reg) && new_freq < old_freq) {
		ret = regulator_set_voltage_tol(cpu_reg, volt, tol);
		if (ret) {
			pr_err("failed to scale voltage down: %d\n", ret);
			clk_set_rate(cpu_clk, freqs.old * 1000);
			freqs.new = freqs.old;
			clk_set_rate(cpu_clk, old_freq * 1000);
		}
	}

post_notify:
	cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE);

	return ret;
}

Loading