Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

cpufreq: imx6q: call CPUFREQ_POSTCHANGE notfier in error cases

PRECHANGE and POSTCHANGE notifiers must be called in groups, i.e either both
should be called or both shouldn't be.

In case we have started PRECHANGE notifier and found an error, we must call
POSTCHANGE notifier with freqs.new = freqs.old to guarantee that sequence of
calling notifiers is complete.

This patch fixes it.

This also moves PRECHANGE notifier down so that we call it just before starting
frequency transition.

Acked-by: Shawn Guo <shawn.guo@linaro.org>
Signed-off-by: Viresh Kumar <viresh.kumar@linaro.org>

+11 -6
+11 -6
drivers/cpufreq/imx6q-cpufreq.c
··· 68 68 if (freqs.old == freqs.new) 69 69 return 0; 70 70 71 - cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); 72 - 73 71 rcu_read_lock(); 74 72 opp = opp_find_freq_ceil(cpu_dev, &freq_hz); 75 73 if (IS_ERR(opp)) { ··· 84 86 freqs.old / 1000, volt_old / 1000, 85 87 freqs.new / 1000, volt / 1000); 86 88 89 + cpufreq_notify_transition(policy, &freqs, CPUFREQ_PRECHANGE); 90 + 87 91 /* scaling up? scale voltage before frequency */ 88 92 if (freqs.new > freqs.old) { 89 93 ret = regulator_set_voltage_tol(arm_reg, volt, 0); 90 94 if (ret) { 91 95 dev_err(cpu_dev, 92 96 "failed to scale vddarm up: %d\n", ret); 93 - return ret; 97 + freqs.new = freqs.old; 98 + goto post_notify; 94 99 } 95 100 96 101 /* ··· 146 145 if (ret) { 147 146 dev_err(cpu_dev, "failed to set clock rate: %d\n", ret); 148 147 regulator_set_voltage_tol(arm_reg, volt_old, 0); 149 - return ret; 148 + freqs.new = freqs.old; 149 + goto post_notify; 150 150 } 151 151 152 152 /* scaling down? scale voltage after frequency */ 153 153 if (freqs.new < freqs.old) { 154 154 ret = regulator_set_voltage_tol(arm_reg, volt, 0); 155 - if (ret) 155 + if (ret) { 156 156 dev_warn(cpu_dev, 157 157 "failed to scale vddarm down: %d\n", ret); 158 + ret = 0; 159 + } 158 160 159 161 if (freqs.old == FREQ_1P2_GHZ / 1000) { 160 162 regulator_set_voltage_tol(pu_reg, ··· 167 163 } 168 164 } 169 165 166 + post_notify: 170 167 cpufreq_notify_transition(policy, &freqs, CPUFREQ_POSTCHANGE); 171 168 172 - return 0; 169 + return ret; 173 170 } 174 171 175 172 static int imx6q_cpufreq_init(struct cpufreq_policy *policy)