aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/kernel/dbell.c2
-rw-r--r--arch/powerpc/kernel/smp.c11
-rw-r--r--arch/powerpc/sysdev/xics/icp-hv.c6
3 files changed, 16 insertions, 3 deletions
diff --git a/arch/powerpc/kernel/dbell.c b/arch/powerpc/kernel/dbell.c
index 5b25c8060fd..a892680668d 100644
--- a/arch/powerpc/kernel/dbell.c
+++ b/arch/powerpc/kernel/dbell.c
@@ -28,6 +28,8 @@ void doorbell_setup_this_cpu(void)
28 28
29void doorbell_cause_ipi(int cpu, unsigned long data) 29void doorbell_cause_ipi(int cpu, unsigned long data)
30{ 30{
31 /* Order previous accesses vs. msgsnd, which is treated as a store */
32 mb();
31 ppc_msgsnd(PPC_DBELL, 0, data); 33 ppc_msgsnd(PPC_DBELL, 0, data);
32} 34}
33 35
diff --git a/arch/powerpc/kernel/smp.c b/arch/powerpc/kernel/smp.c
index 0321007086f..8d4214afc21 100644
--- a/arch/powerpc/kernel/smp.c
+++ b/arch/powerpc/kernel/smp.c
@@ -198,8 +198,15 @@ void smp_muxed_ipi_message_pass(int cpu, int msg)
198 struct cpu_messages *info = &per_cpu(ipi_message, cpu); 198 struct cpu_messages *info = &per_cpu(ipi_message, cpu);
199 char *message = (char *)&info->messages; 199 char *message = (char *)&info->messages;
200 200
201 /*
202 * Order previous accesses before accesses in the IPI handler.
203 */
204 smp_mb();
201 message[msg] = 1; 205 message[msg] = 1;
202 mb(); 206 /*
207 * cause_ipi functions are required to include a full barrier
208 * before doing whatever causes the IPI.
209 */
203 smp_ops->cause_ipi(cpu, info->data); 210 smp_ops->cause_ipi(cpu, info->data);
204} 211}
205 212
@@ -211,7 +218,7 @@ irqreturn_t smp_ipi_demux(void)
211 mb(); /* order any irq clear */ 218 mb(); /* order any irq clear */
212 219
213 do { 220 do {
214 all = xchg_local(&info->messages, 0); 221 all = xchg(&info->messages, 0);
215 222
216#ifdef __BIG_ENDIAN 223#ifdef __BIG_ENDIAN
217 if (all & (1 << (24 - 8 * PPC_MSG_CALL_FUNCTION))) 224 if (all & (1 << (24 - 8 * PPC_MSG_CALL_FUNCTION)))
diff --git a/arch/powerpc/sysdev/xics/icp-hv.c b/arch/powerpc/sysdev/xics/icp-hv.c
index 14469cf9df6..df0fc582146 100644
--- a/arch/powerpc/sysdev/xics/icp-hv.c
+++ b/arch/powerpc/sysdev/xics/icp-hv.c
@@ -65,7 +65,11 @@ static inline void icp_hv_set_xirr(unsigned int value)
65static inline void icp_hv_set_qirr(int n_cpu , u8 value) 65static inline void icp_hv_set_qirr(int n_cpu , u8 value)
66{ 66{
67 int hw_cpu = get_hard_smp_processor_id(n_cpu); 67 int hw_cpu = get_hard_smp_processor_id(n_cpu);
68 long rc = plpar_hcall_norets(H_IPI, hw_cpu, value); 68 long rc;
69
70 /* Make sure all previous accesses are ordered before IPI sending */
71 mb();
72 rc = plpar_hcall_norets(H_IPI, hw_cpu, value);
69 if (rc != H_SUCCESS) { 73 if (rc != H_SUCCESS) {
70 pr_err("%s: bad return code qirr cpu=%d hw_cpu=%d mfrr=0x%x " 74 pr_err("%s: bad return code qirr cpu=%d hw_cpu=%d mfrr=0x%x "
71 "returned %ld\n", __func__, n_cpu, hw_cpu, value, rc); 75 "returned %ld\n", __func__, n_cpu, hw_cpu, value, rc);