msm: spm_devices: Fix failure to set vdd during cpu_up
To avoid a core vdd being set when the core could be executing the SPM
finite state machine, set the call to set vdd to execute on that
particular core using smp_call_function_single(). However, the call can
only be executed on a core thats online.
When a core is brought online, the acpuclk driver needs to ensure that
the core vdd is set correctly before the core can be brought online.
But, since smp_call_function_single() works on cores that are online,
the call to set vdd will fail and therefore the core will cannot be
onlined.
The error that would be seen when the kernel command line parameters has
maxcpus=2
[244.759529] saw_set_voltage: 8821_s0: msm_spm_set_vdd failed -6
[244.764687] acpuclk-8064 acpuclk-8064: regulator_set_voltage(krait2)(-6)
[244.771463] _cpu_up: attempt to bring up CPU 2 failed
It is safe to do a set the vdd of an offline core when called at cpu_up,
so bypass smp_call_function_single() and set the voltage of the core
directly from cpu0.
This chicken and egg problem will not be seen if the cores were
initialized by calling boot_secondary() at init.
CRs-fixed: 407553
Change-Id: Ifdc9a645b5a9715d0fda065b4b0c2bab056a3ade
Signed-off-by: Praveen Chidambaram <pchidamb@codeaurora.org>
(cherry picked from commit 8624ce7c52bba5acf7a2321690def8c732680199)
Signed-off-by: Dhivya Subramanian <dthiru@codeaurora.org>
diff --git a/arch/arm/mach-msm/spm_devices.c b/arch/arm/mach-msm/spm_devices.c
index db2c626..6fb693f 100644
--- a/arch/arm/mach-msm/spm_devices.c
+++ b/arch/arm/mach-msm/spm_devices.c
@@ -48,7 +48,6 @@
static DEFINE_PER_CPU_SHARED_ALIGNED(struct msm_spm_device, msm_cpu_spm_device);
-/* Must be called on the same cpu as the one being set to */
static void msm_spm_smp_set_vdd(void *data)
{
struct msm_spm_device *dev;
@@ -66,10 +65,27 @@
info.cpu = cpu;
info.vlevel = vlevel;
- /* Set to true to block on vdd change */
- ret = smp_call_function_single(cpu, msm_spm_smp_set_vdd, &info, true);
- if (!ret)
+ if (cpu_online(cpu)) {
+ /**
+ * We do not want to set the voltage of another core from
+ * this core, as its possible that we may race the vdd change
+ * with the SPM state machine of that core, which could also
+ * be changing the voltage of that core during power collapse.
+ * Hence, set the function to be executed on that core and block
+ * until the vdd change is complete.
+ */
+ ret = smp_call_function_single(cpu, msm_spm_smp_set_vdd,
+ &info, true);
+ if (!ret)
+ ret = info.err;
+ } else {
+ /**
+ * Since the core is not online, it is safe to set the vdd
+ * directly.
+ */
+ msm_spm_smp_set_vdd(&info);
ret = info.err;
+ }
return ret;
}