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

Commit 8c0f5c6c authored by Vikram Mulukutla's avatar Vikram Mulukutla
Browse files

clk: msm: clock-cpu-8996: Workaround a concurrent access bug



Limits Management hardware and the clock controller registers
cannot be accessed concurrently from two CPUs in the same
cluster. Provide mutual exclusion by using the scm_lmh_lock
mutex around the clock APIs that touch the CPU clock controller.

Change-Id: I74e6de7f35e46b3f841a4ac97dd5cf87cf0211a4
Signed-off-by: default avatarVikram Mulukutla <markivx@codeaurora.org>
parent 21f9099c
Loading
Loading
Loading
Loading
+10 −1
Original line number Diff line number Diff line
@@ -534,8 +534,9 @@ static int cpu_clk_8996_set_rate(struct clk *c, unsigned long rate)
			if (cpuclk->alt_pll_freqs[i] < rate &&
			    cpuclk->alt_pll_freqs[i+1] >= rate)
				alt_pll_rate = cpuclk->alt_pll_freqs[i];

		mutex_lock(&scm_lmh_lock);
		ret = clk_set_rate(cpuclk->alt_pll, alt_pll_rate);
		mutex_unlock(&scm_lmh_lock);
		if (ret) {
			pr_err("failed to set rate %lu on alt_pll when setting %lu on %s (%d)\n",
			alt_pll_rate, rate, c->dbg_name, ret);
@@ -555,7 +556,9 @@ static int cpu_clk_8996_set_rate(struct clk *c, unsigned long rate)
	 * CPU frequency to ramp up from 384MHz to 550MHz.
	 */
	if (c->rate > 600000000 && rate < 600000000) {
		mutex_lock(&scm_lmh_lock);
		ret = clk_set_rate(c->parent, c->rate/2);
		mutex_unlock(&scm_lmh_lock);
		if (ret) {
			pr_err("failed to set rate %lu on %s (%d)\n",
				c->rate/2, c->dbg_name, ret);
@@ -563,7 +566,9 @@ static int cpu_clk_8996_set_rate(struct clk *c, unsigned long rate)
		}
	}

	mutex_lock(&scm_lmh_lock);
	ret = clk_set_rate(c->parent, rate);
	mutex_unlock(&scm_lmh_lock);
	if (ret) {
		pr_err("failed to set rate %lu on %s (%d)\n",
			rate, c->dbg_name, ret);
@@ -578,7 +583,9 @@ static int cpu_clk_8996_set_rate(struct clk *c, unsigned long rate)
set_rate_fail:
	/* Restore parent rate if we halved it */
	if (c->rate > 600000000 && rate < 600000000) {
		mutex_lock(&scm_lmh_lock);
		err_ret = clk_set_rate(c->parent, c->rate);
		mutex_unlock(&scm_lmh_lock);
		if (err_ret)
			pr_err("failed to restore %s rate to %lu\n",
			       c->dbg_name, c->rate);
@@ -586,7 +593,9 @@ set_rate_fail:

fail:
	if (cpuclk->alt_pll && (n_alt_freqs > 0)) {
		mutex_lock(&scm_lmh_lock);
		err_ret = clk_set_rate(cpuclk->alt_pll, alt_pll_prev_rate);
		mutex_unlock(&scm_lmh_lock);
		if (err_ret)
			pr_err("failed to reset rate to %lu on alt pll after failing to  set %lu on %s (%d)\n",
				alt_pll_prev_rate, rate, c->dbg_name, err_ret);