aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Martin <dave.martin@linaro.org>2012-08-17 11:07:02 -0400
committerNicolas Pitre <nicolas.pitre@linaro.org>2013-04-24 10:37:01 -0400
commit1ae98561b16f305e43151405f226727c00ee52bc (patch)
treef48c7fa44fdd147340f00d4a51555cbd7c476e27
parent9762f12d3e05c8d6a0651f4c7e76ae72ce27fc3a (diff)
ARM: mcpm_head.S: vlock-based first man election
Instead of requiring the first man to be elected in advance (which can be suboptimal in some situations), this patch uses a per- cluster mutex to co-ordinate selection of the first man. This should also make it more feasible to reuse this code path for asynchronous cluster resume (as in CPUidle scenarios). We must ensure that the vlock data doesn't share a cacheline with anything else, or dirty cache eviction could corrupt it. Signed-off-by: Dave Martin <dave.martin@linaro.org> Signed-off-by: Nicolas Pitre <nicolas.pitre@linaro.org> Reviewed-by: Santosh Shilimkar <santosh.shilimkar@ti.com> Reviewed-by: Will Deacon <will.deacon@arm.com>
-rw-r--r--arch/arm/common/Makefile2
-rw-r--r--arch/arm/common/mcpm_head.S41
-rw-r--r--arch/arm/kernel/asm-offsets.c1
3 files changed, 38 insertions, 6 deletions
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index b070671033ae..9ec273188ccb 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -11,4 +11,4 @@ obj-$(CONFIG_SHARP_PARAM) += sharpsl_param.o
11obj-$(CONFIG_SHARP_SCOOP) += scoop.o 11obj-$(CONFIG_SHARP_SCOOP) += scoop.o
12obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o 12obj-$(CONFIG_PCI_HOST_ITE8152) += it8152.o
13obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o 13obj-$(CONFIG_ARM_TIMER_SP804) += timer-sp.o
14obj-$(CONFIG_MCPM) += mcpm_head.o mcpm_entry.o 14obj-$(CONFIG_MCPM) += mcpm_head.o mcpm_entry.o vlock.o
diff --git a/arch/arm/common/mcpm_head.S b/arch/arm/common/mcpm_head.S
index 7d729bd72674..8178705c4b24 100644
--- a/arch/arm/common/mcpm_head.S
+++ b/arch/arm/common/mcpm_head.S
@@ -16,6 +16,8 @@
16#include <linux/linkage.h> 16#include <linux/linkage.h>
17#include <asm/mcpm.h> 17#include <asm/mcpm.h>
18 18
19#include "vlock.h"
20
19.if MCPM_SYNC_CLUSTER_CPUS 21.if MCPM_SYNC_CLUSTER_CPUS
20.error "cpus must be the first member of struct mcpm_sync_struct" 22.error "cpus must be the first member of struct mcpm_sync_struct"
21.endif 23.endif
@@ -69,10 +71,11 @@ ENTRY(mcpm_entry_point)
69 * position independent way. 71 * position independent way.
70 */ 72 */
71 adr r5, 3f 73 adr r5, 3f
72 ldmia r5, {r6, r7, r8} 74 ldmia r5, {r6, r7, r8, r11}
73 add r6, r5, r6 @ r6 = mcpm_entry_vectors 75 add r6, r5, r6 @ r6 = mcpm_entry_vectors
74 ldr r7, [r5, r7] @ r7 = mcpm_power_up_setup_phys 76 ldr r7, [r5, r7] @ r7 = mcpm_power_up_setup_phys
75 add r8, r5, r8 @ r8 = mcpm_sync 77 add r8, r5, r8 @ r8 = mcpm_sync
78 add r11, r5, r11 @ r11 = first_man_locks
76 79
77 mov r0, #MCPM_SYNC_CLUSTER_SIZE 80 mov r0, #MCPM_SYNC_CLUSTER_SIZE
78 mla r8, r0, r10, r8 @ r8 = sync cluster base 81 mla r8, r0, r10, r8 @ r8 = sync cluster base
@@ -86,13 +89,22 @@ ENTRY(mcpm_entry_point)
86 @ At this point, the cluster cannot unexpectedly enter the GOING_DOWN 89 @ At this point, the cluster cannot unexpectedly enter the GOING_DOWN
87 @ state, because there is at least one active CPU (this CPU). 90 @ state, because there is at least one active CPU (this CPU).
88 91
89 @ Note: the following is racy as another CPU might be testing 92 mov r0, #VLOCK_SIZE
90 @ the same flag at the same moment. That'll be fixed later. 93 mla r11, r0, r10, r11 @ r11 = cluster first man lock
94 mov r0, r11
95 mov r1, r9 @ cpu
96 bl vlock_trylock @ implies DMB
97
98 cmp r0, #0 @ failed to get the lock?
99 bne mcpm_setup_wait @ wait for cluster setup if so
100
91 ldrb r0, [r8, #MCPM_SYNC_CLUSTER_CLUSTER] 101 ldrb r0, [r8, #MCPM_SYNC_CLUSTER_CLUSTER]
92 cmp r0, #CLUSTER_UP @ cluster already up? 102 cmp r0, #CLUSTER_UP @ cluster already up?
93 bne mcpm_setup @ if not, set up the cluster 103 bne mcpm_setup @ if not, set up the cluster
94 104
95 @ Otherwise, skip setup: 105 @ Otherwise, release the first man lock and skip setup:
106 mov r0, r11
107 bl vlock_unlock
96 b mcpm_setup_complete 108 b mcpm_setup_complete
97 109
98mcpm_setup: 110mcpm_setup:
@@ -142,6 +154,19 @@ mcpm_setup_leave:
142 dsb 154 dsb
143 sev 155 sev
144 156
157 mov r0, r11
158 bl vlock_unlock @ implies DMB
159 b mcpm_setup_complete
160
161 @ In the contended case, non-first men wait here for cluster setup
162 @ to complete:
163mcpm_setup_wait:
164 ldrb r0, [r8, #MCPM_SYNC_CLUSTER_CLUSTER]
165 cmp r0, #CLUSTER_UP
166 wfene
167 bne mcpm_setup_wait
168 dmb
169
145mcpm_setup_complete: 170mcpm_setup_complete:
146 @ If a platform-specific CPU setup hook is needed, it is 171 @ If a platform-specific CPU setup hook is needed, it is
147 @ called from here. 172 @ called from here.
@@ -173,11 +198,17 @@ mcpm_entry_gated:
1733: .word mcpm_entry_vectors - . 1983: .word mcpm_entry_vectors - .
174 .word mcpm_power_up_setup_phys - 3b 199 .word mcpm_power_up_setup_phys - 3b
175 .word mcpm_sync - 3b 200 .word mcpm_sync - 3b
201 .word first_man_locks - 3b
176 202
177ENDPROC(mcpm_entry_point) 203ENDPROC(mcpm_entry_point)
178 204
179 .bss 205 .bss
180 .align 5 206
207 .align CACHE_WRITEBACK_ORDER
208 .type first_man_locks, #object
209first_man_locks:
210 .space VLOCK_SIZE * MAX_NR_CLUSTERS
211 .align CACHE_WRITEBACK_ORDER
181 212
182 .type mcpm_entry_vectors, #object 213 .type mcpm_entry_vectors, #object
183ENTRY(mcpm_entry_vectors) 214ENTRY(mcpm_entry_vectors)
diff --git a/arch/arm/kernel/asm-offsets.c b/arch/arm/kernel/asm-offsets.c
index 1bed82a0a9e0..3f088225e71c 100644
--- a/arch/arm/kernel/asm-offsets.c
+++ b/arch/arm/kernel/asm-offsets.c
@@ -150,6 +150,7 @@ int main(void)
150 DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE); 150 DEFINE(DMA_TO_DEVICE, DMA_TO_DEVICE);
151 DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE); 151 DEFINE(DMA_FROM_DEVICE, DMA_FROM_DEVICE);
152 BLANK(); 152 BLANK();
153 DEFINE(CACHE_WRITEBACK_ORDER, __CACHE_WRITEBACK_ORDER);
153 DEFINE(CACHE_WRITEBACK_GRANULE, __CACHE_WRITEBACK_GRANULE); 154 DEFINE(CACHE_WRITEBACK_GRANULE, __CACHE_WRITEBACK_GRANULE);
154 BLANK(); 155 BLANK();
155#ifdef CONFIG_KVM_ARM_HOST 156#ifdef CONFIG_KVM_ARM_HOST