Commit 24480d98 authored by Russell King's avatar Russell King

ARM: SMP: avoid using bitmasks and locks for IPIs, use hardware instead

Avoid using bitmasks and locks in the percpu area for IPIs, and instead
use individual software generated interrupts to identify the reason for
the IPI.  This avoids the problems of having spinlocks in the percpu
area.
Reviewed-by: default avatarCatalin Marinas <catalin.marinas@arm.com>
Signed-off-by: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent ad3b6993
...@@ -48,20 +48,15 @@ struct secondary_data secondary_data; ...@@ -48,20 +48,15 @@ struct secondary_data secondary_data;
/* /*
* structures for inter-processor calls * structures for inter-processor calls
* - A collection of single bit ipi messages.
*/ */
struct ipi_data { struct ipi_data {
spinlock_t lock;
unsigned long ipi_count; unsigned long ipi_count;
unsigned long bits;
}; };
static DEFINE_PER_CPU(struct ipi_data, ipi_data) = { static DEFINE_PER_CPU(struct ipi_data, ipi_data);
.lock = SPIN_LOCK_UNLOCKED,
};
enum ipi_msg_type { enum ipi_msg_type {
IPI_TIMER, IPI_TIMER = 2,
IPI_RESCHEDULE, IPI_RESCHEDULE,
IPI_CALL_FUNC, IPI_CALL_FUNC,
IPI_CALL_FUNC_SINGLE, IPI_CALL_FUNC_SINGLE,
...@@ -389,22 +384,13 @@ void __init smp_prepare_boot_cpu(void) ...@@ -389,22 +384,13 @@ void __init smp_prepare_boot_cpu(void)
static void send_ipi_message(const struct cpumask *mask, enum ipi_msg_type msg) static void send_ipi_message(const struct cpumask *mask, enum ipi_msg_type msg)
{ {
unsigned long flags; unsigned long flags;
unsigned int cpu;
local_irq_save(flags); local_irq_save(flags);
for_each_cpu(cpu, mask) {
struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
spin_lock(&ipi->lock);
ipi->bits |= 1 << msg;
spin_unlock(&ipi->lock);
}
/* /*
* Call the platform specific cross-CPU call function. * Call the platform specific cross-CPU call function.
*/ */
smp_cross_call(mask, 1); smp_cross_call(mask, msg);
local_irq_restore(flags); local_irq_restore(flags);
} }
...@@ -546,25 +532,7 @@ asmlinkage void __exception do_IPI(int ipinr, struct pt_regs *regs) ...@@ -546,25 +532,7 @@ asmlinkage void __exception do_IPI(int ipinr, struct pt_regs *regs)
ipi->ipi_count++; ipi->ipi_count++;
for (;;) { switch (ipinr) {
unsigned long msgs;
spin_lock(&ipi->lock);
msgs = ipi->bits;
ipi->bits = 0;
spin_unlock(&ipi->lock);
if (!msgs)
break;
do {
unsigned nextmsg;
nextmsg = msgs & -msgs;
msgs &= ~nextmsg;
nextmsg = ffz(~nextmsg);
switch (nextmsg) {
case IPI_TIMER: case IPI_TIMER:
ipi_timer(); ipi_timer();
break; break;
...@@ -590,12 +558,9 @@ asmlinkage void __exception do_IPI(int ipinr, struct pt_regs *regs) ...@@ -590,12 +558,9 @@ asmlinkage void __exception do_IPI(int ipinr, struct pt_regs *regs)
default: default:
printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
cpu, nextmsg); cpu, ipinr);
break; break;
} }
} while (msgs);
}
set_irq_regs(old_regs); set_irq_regs(old_regs);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment