aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/kernel/smp.c87
1 files changed, 26 insertions, 61 deletions
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 7a236db03fb..78d55c681a4 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -48,20 +48,15 @@ struct secondary_data secondary_data;
48 48
49/* 49/*
50 * structures for inter-processor calls 50 * structures for inter-processor calls
51 * - A collection of single bit ipi messages.
52 */ 51 */
53struct ipi_data { 52struct ipi_data {
54 spinlock_t lock;
55 unsigned long ipi_count; 53 unsigned long ipi_count;
56 unsigned long bits;
57}; 54};
58 55
59static DEFINE_PER_CPU(struct ipi_data, ipi_data) = { 56static DEFINE_PER_CPU(struct ipi_data, ipi_data);
60 .lock = SPIN_LOCK_UNLOCKED,
61};
62 57
63enum ipi_msg_type { 58enum ipi_msg_type {
64 IPI_TIMER, 59 IPI_TIMER = 2,
65 IPI_RESCHEDULE, 60 IPI_RESCHEDULE,
66 IPI_CALL_FUNC, 61 IPI_CALL_FUNC,
67 IPI_CALL_FUNC_SINGLE, 62 IPI_CALL_FUNC_SINGLE,
@@ -389,22 +384,13 @@ void __init smp_prepare_boot_cpu(void)
389static void send_ipi_message(const struct cpumask *mask, enum ipi_msg_type msg) 384static void send_ipi_message(const struct cpumask *mask, enum ipi_msg_type msg)
390{ 385{
391 unsigned long flags; 386 unsigned long flags;
392 unsigned int cpu;
393 387
394 local_irq_save(flags); 388 local_irq_save(flags);
395 389
396 for_each_cpu(cpu, mask) {
397 struct ipi_data *ipi = &per_cpu(ipi_data, cpu);
398
399 spin_lock(&ipi->lock);
400 ipi->bits |= 1 << msg;
401 spin_unlock(&ipi->lock);
402 }
403
404 /* 390 /*
405 * Call the platform specific cross-CPU call function. 391 * Call the platform specific cross-CPU call function.
406 */ 392 */
407 smp_cross_call(mask, 1); 393 smp_cross_call(mask, msg);
408 394
409 local_irq_restore(flags); 395 local_irq_restore(flags);
410} 396}
@@ -546,56 +532,35 @@ asmlinkage void __exception do_IPI(int ipinr, struct pt_regs *regs)
546 532
547 ipi->ipi_count++; 533 ipi->ipi_count++;
548 534
549 for (;;) { 535 switch (ipinr) {
550 unsigned long msgs; 536 case IPI_TIMER:
551 537 ipi_timer();
552 spin_lock(&ipi->lock); 538 break;
553 msgs = ipi->bits;
554 ipi->bits = 0;
555 spin_unlock(&ipi->lock);
556
557 if (!msgs)
558 break;
559
560 do {
561 unsigned nextmsg;
562
563 nextmsg = msgs & -msgs;
564 msgs &= ~nextmsg;
565 nextmsg = ffz(~nextmsg);
566
567 switch (nextmsg) {
568 case IPI_TIMER:
569 ipi_timer();
570 break;
571 539
572 case IPI_RESCHEDULE: 540 case IPI_RESCHEDULE:
573 /* 541 /*
574 * nothing more to do - eveything is 542 * nothing more to do - eveything is
575 * done on the interrupt return path 543 * done on the interrupt return path
576 */ 544 */
577 break; 545 break;
578 546
579 case IPI_CALL_FUNC: 547 case IPI_CALL_FUNC:
580 generic_smp_call_function_interrupt(); 548 generic_smp_call_function_interrupt();
581 break; 549 break;
582 550
583 case IPI_CALL_FUNC_SINGLE: 551 case IPI_CALL_FUNC_SINGLE:
584 generic_smp_call_function_single_interrupt(); 552 generic_smp_call_function_single_interrupt();
585 break; 553 break;
586 554
587 case IPI_CPU_STOP: 555 case IPI_CPU_STOP:
588 ipi_cpu_stop(cpu); 556 ipi_cpu_stop(cpu);
589 break; 557 break;
590 558
591 default: 559 default:
592 printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n", 560 printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%x\n",
593 cpu, nextmsg); 561 cpu, ipinr);
594 break; 562 break;
595 }
596 } while (msgs);
597 } 563 }
598
599 set_irq_regs(old_regs); 564 set_irq_regs(old_regs);
600} 565}
601 566