diff options
-rw-r--r-- | arch/arm/common/bL_switcher.c | 24 |
1 files changed, 22 insertions, 2 deletions
diff --git a/arch/arm/common/bL_switcher.c b/arch/arm/common/bL_switcher.c index 34316be404d5..aab7c1274885 100644 --- a/arch/arm/common/bL_switcher.c +++ b/arch/arm/common/bL_switcher.c | |||
@@ -55,9 +55,10 @@ static int read_mpidr(void) | |||
55 | * bL switcher core code. | 55 | * bL switcher core code. |
56 | */ | 56 | */ |
57 | 57 | ||
58 | static void bL_do_switch(void *_unused) | 58 | static void bL_do_switch(void *_arg) |
59 | { | 59 | { |
60 | unsigned ib_mpidr, ib_cpu, ib_cluster; | 60 | unsigned ib_mpidr, ib_cpu, ib_cluster; |
61 | long volatile handshake, **handshake_ptr = _arg; | ||
61 | 62 | ||
62 | pr_debug("%s\n", __func__); | 63 | pr_debug("%s\n", __func__); |
63 | 64 | ||
@@ -65,6 +66,13 @@ static void bL_do_switch(void *_unused) | |||
65 | ib_cpu = MPIDR_AFFINITY_LEVEL(ib_mpidr, 0); | 66 | ib_cpu = MPIDR_AFFINITY_LEVEL(ib_mpidr, 0); |
66 | ib_cluster = MPIDR_AFFINITY_LEVEL(ib_mpidr, 1); | 67 | ib_cluster = MPIDR_AFFINITY_LEVEL(ib_mpidr, 1); |
67 | 68 | ||
69 | /* Advertise our handshake location */ | ||
70 | if (handshake_ptr) { | ||
71 | handshake = 0; | ||
72 | *handshake_ptr = &handshake; | ||
73 | } else | ||
74 | handshake = -1; | ||
75 | |||
68 | /* | 76 | /* |
69 | * Our state has been saved at this point. Let's release our | 77 | * Our state has been saved at this point. Let's release our |
70 | * inbound CPU. | 78 | * inbound CPU. |
@@ -83,6 +91,14 @@ static void bL_do_switch(void *_unused) | |||
83 | * we have none. | 91 | * we have none. |
84 | */ | 92 | */ |
85 | 93 | ||
94 | /* | ||
95 | * Let's wait until our inbound is alive. | ||
96 | */ | ||
97 | while (!handshake) { | ||
98 | wfe(); | ||
99 | smp_mb(); | ||
100 | } | ||
101 | |||
86 | /* Let's put ourself down. */ | 102 | /* Let's put ourself down. */ |
87 | mcpm_cpu_power_down(); | 103 | mcpm_cpu_power_down(); |
88 | 104 | ||
@@ -130,6 +146,7 @@ static int bL_switch_to(unsigned int new_cluster_id) | |||
130 | unsigned int ob_mpidr, ob_cpu, ob_cluster, ib_mpidr, ib_cpu, ib_cluster; | 146 | unsigned int ob_mpidr, ob_cpu, ob_cluster, ib_mpidr, ib_cpu, ib_cluster; |
131 | struct tick_device *tdev; | 147 | struct tick_device *tdev; |
132 | enum clock_event_mode tdev_mode; | 148 | enum clock_event_mode tdev_mode; |
149 | long volatile *handshake_ptr; | ||
133 | int ret; | 150 | int ret; |
134 | 151 | ||
135 | this_cpu = smp_processor_id(); | 152 | this_cpu = smp_processor_id(); |
@@ -198,7 +215,7 @@ static int bL_switch_to(unsigned int new_cluster_id) | |||
198 | cpu_logical_map(that_cpu) = ob_mpidr; | 215 | cpu_logical_map(that_cpu) = ob_mpidr; |
199 | 216 | ||
200 | /* Let's do the actual CPU switch. */ | 217 | /* Let's do the actual CPU switch. */ |
201 | ret = cpu_suspend(0, bL_switchpoint); | 218 | ret = cpu_suspend((unsigned long)&handshake_ptr, bL_switchpoint); |
202 | if (ret > 0) | 219 | if (ret > 0) |
203 | panic("%s: cpu_suspend() returned %d\n", __func__, ret); | 220 | panic("%s: cpu_suspend() returned %d\n", __func__, ret); |
204 | 221 | ||
@@ -220,6 +237,9 @@ static int bL_switch_to(unsigned int new_cluster_id) | |||
220 | local_fiq_enable(); | 237 | local_fiq_enable(); |
221 | local_irq_enable(); | 238 | local_irq_enable(); |
222 | 239 | ||
240 | *handshake_ptr = 1; | ||
241 | dsb_sev(); | ||
242 | |||
223 | if (ret) | 243 | if (ret) |
224 | pr_err("%s exiting with error %d\n", __func__, ret); | 244 | pr_err("%s exiting with error %d\n", __func__, ret); |
225 | return ret; | 245 | return ret; |