diff options
author | Shreyas B. Prabhu <shreyas@linux.vnet.ibm.com> | 2015-05-20 00:30:14 +0530 |
---|---|---|
committer | Michael Ellerman <mpe@ellerman.id.au> | 2015-06-17 08:01:03 +1000 |
commit | 3609d819a36c65857816ca1278d80767d6d9b990 (patch) | |
tree | f74a540fb015f9774a22753e4665a1b5aec689b7 /arch/powerpc/sysdev | |
parent | 4bece972fce6e597cb513bdcae4a04e14fc0dd81 (diff) | |
download | op-kernel-dev-3609d819a36c65857816ca1278d80767d6d9b990.zip op-kernel-dev-3609d819a36c65857816ca1278d80767d6d9b990.tar.gz |
powerpc: Make doorbell check preemption safe
Doorbell can be used to cause ipi on cpus which are sibling threads on
the same core. So icp_native_cause_ipi checks if the destination cpu
is a sibling thread of the current cpu and uses doorbell in such cases.
But while running with CONFIG_PREEMPT=y, since this section is
preemtible, we can run into issues if after we check if the destination
cpu is a sibling cpu, the task gets migrated from a sibling cpu to a
cpu on another core.
Fix this by using get_cpu()/ put_cpu()
Signed-off-by: Shreyas B. Prabhu <shreyas@linux.vnet.ibm.com>
Signed-off-by: Michael Neuling <mikey@neuling.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
Diffstat (limited to 'arch/powerpc/sysdev')
-rw-r--r-- | arch/powerpc/sysdev/xics/icp-native.c | 14 |
1 files changed, 9 insertions, 5 deletions
diff --git a/arch/powerpc/sysdev/xics/icp-native.c b/arch/powerpc/sysdev/xics/icp-native.c index 2fc4cf1..eae3265 100644 --- a/arch/powerpc/sysdev/xics/icp-native.c +++ b/arch/powerpc/sysdev/xics/icp-native.c @@ -147,12 +147,16 @@ static void icp_native_cause_ipi(int cpu, unsigned long data) { kvmppc_set_host_ipi(cpu, 1); #ifdef CONFIG_PPC_DOORBELL - if (cpu_has_feature(CPU_FTR_DBELL) && - (cpumask_test_cpu(cpu, cpu_sibling_mask(smp_processor_id())))) - doorbell_cause_ipi(cpu, data); - else + if (cpu_has_feature(CPU_FTR_DBELL)) { + if (cpumask_test_cpu(cpu, cpu_sibling_mask(get_cpu()))) { + doorbell_cause_ipi(cpu, data); + put_cpu(); + return; + } + put_cpu(); + } #endif - icp_native_set_qirr(cpu, IPI_PRIORITY); + icp_native_set_qirr(cpu, IPI_PRIORITY); } /* |