aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc
diff options
context:
space:
mode:
authorKumar Gala <galak@kernel.crashing.org>2008-10-28 14:01:39 -0400
committerPaul Mackerras <paulus@samba.org>2008-10-31 01:13:50 -0400
commit3c10c9c45e290022ca7d2aa1ad33a0b6ed767520 (patch)
tree002769098cd2b53aad995acac3c42f0331302588 /arch/powerpc
parentf9226d572d2f8b5f564596db8c6a13e458c46191 (diff)
powerpc/mpic: Fix regression caused by change of default IRQ affinity
The Freescale implementation of MPIC only allows a single CPU destination for non-IPI interrupts. We add a flag to the mpic_init to distinquish these variants of MPIC. We pull in the irq_choose_cpu from sparc64 to select a single CPU as the destination of the interrupt. This is to deal with the fact that the default smp affinity was changed by commit 18404756765c713a0be4eb1082920c04822ce588 ("genirq: Expose default irq affinity mask (take 3)") to be all CPUs. Signed-off-by: Kumar Gala <galak@kernel.crashing.org> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc')
-rw-r--r--arch/powerpc/include/asm/mpic.h2
-rw-r--r--arch/powerpc/platforms/85xx/mpc85xx_ds.c3
-rw-r--r--arch/powerpc/platforms/86xx/pic.c3
-rw-r--r--arch/powerpc/sysdev/mpic.c59
4 files changed, 61 insertions, 6 deletions
diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h
index 34d9ac433ace..c2ccca53b991 100644
--- a/arch/powerpc/include/asm/mpic.h
+++ b/arch/powerpc/include/asm/mpic.h
@@ -355,6 +355,8 @@ struct mpic
355#define MPIC_NO_BIAS 0x00000400 355#define MPIC_NO_BIAS 0x00000400
356/* Ignore NIRQS as reported by FRR */ 356/* Ignore NIRQS as reported by FRR */
357#define MPIC_BROKEN_FRR_NIRQS 0x00000800 357#define MPIC_BROKEN_FRR_NIRQS 0x00000800
358/* Destination only supports a single CPU at a time */
359#define MPIC_SINGLE_DEST_CPU 0x00001000
358 360
359/* MPIC HW modification ID */ 361/* MPIC HW modification ID */
360#define MPIC_REGSET_MASK 0xf0000000 362#define MPIC_REGSET_MASK 0xf0000000
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
index 483b65cbabae..613bf8c2e30d 100644
--- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c
+++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c
@@ -78,7 +78,8 @@ void __init mpc85xx_ds_pic_init(void)
78 78
79 mpic = mpic_alloc(np, r.start, 79 mpic = mpic_alloc(np, r.start,
80 MPIC_PRIMARY | MPIC_WANTS_RESET | 80 MPIC_PRIMARY | MPIC_WANTS_RESET |
81 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS, 81 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
82 MPIC_SINGLE_DEST_CPU,
82 0, 256, " OpenPIC "); 83 0, 256, " OpenPIC ");
83 BUG_ON(mpic == NULL); 84 BUG_ON(mpic == NULL);
84 of_node_put(np); 85 of_node_put(np);
diff --git a/arch/powerpc/platforms/86xx/pic.c b/arch/powerpc/platforms/86xx/pic.c
index 8881c5de500d..668275d9e668 100644
--- a/arch/powerpc/platforms/86xx/pic.c
+++ b/arch/powerpc/platforms/86xx/pic.c
@@ -44,7 +44,8 @@ void __init mpc86xx_init_irq(void)
44 44
45 mpic = mpic_alloc(np, res.start, 45 mpic = mpic_alloc(np, res.start,
46 MPIC_PRIMARY | MPIC_WANTS_RESET | 46 MPIC_PRIMARY | MPIC_WANTS_RESET |
47 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS, 47 MPIC_BIG_ENDIAN | MPIC_BROKEN_FRR_NIRQS |
48 MPIC_SINGLE_DEST_CPU,
48 0, 256, " MPIC "); 49 0, 256, " MPIC ");
49 of_node_put(np); 50 of_node_put(np);
50 BUG_ON(mpic == NULL); 51 BUG_ON(mpic == NULL);
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index 8e3478c995ef..f6299cca7814 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -563,6 +563,51 @@ static void __init mpic_scan_ht_pics(struct mpic *mpic)
563 563
564#endif /* CONFIG_MPIC_U3_HT_IRQS */ 564#endif /* CONFIG_MPIC_U3_HT_IRQS */
565 565
566#ifdef CONFIG_SMP
567static int irq_choose_cpu(unsigned int virt_irq)
568{
569 cpumask_t mask = irq_desc[virt_irq].affinity;
570 int cpuid;
571
572 if (cpus_equal(mask, CPU_MASK_ALL)) {
573 static int irq_rover;
574 static DEFINE_SPINLOCK(irq_rover_lock);
575 unsigned long flags;
576
577 /* Round-robin distribution... */
578 do_round_robin:
579 spin_lock_irqsave(&irq_rover_lock, flags);
580
581 while (!cpu_online(irq_rover)) {
582 if (++irq_rover >= NR_CPUS)
583 irq_rover = 0;
584 }
585 cpuid = irq_rover;
586 do {
587 if (++irq_rover >= NR_CPUS)
588 irq_rover = 0;
589 } while (!cpu_online(irq_rover));
590
591 spin_unlock_irqrestore(&irq_rover_lock, flags);
592 } else {
593 cpumask_t tmp;
594
595 cpus_and(tmp, cpu_online_map, mask);
596
597 if (cpus_empty(tmp))
598 goto do_round_robin;
599
600 cpuid = first_cpu(tmp);
601 }
602
603 return cpuid;
604}
605#else
606static int irq_choose_cpu(unsigned int virt_irq)
607{
608 return hard_smp_processor_id();
609}
610#endif
566 611
567#define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) 612#define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq)
568 613
@@ -777,12 +822,18 @@ void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
777 struct mpic *mpic = mpic_from_irq(irq); 822 struct mpic *mpic = mpic_from_irq(irq);
778 unsigned int src = mpic_irq_to_hw(irq); 823 unsigned int src = mpic_irq_to_hw(irq);
779 824
780 cpumask_t tmp; 825 if (mpic->flags & MPIC_SINGLE_DEST_CPU) {
826 int cpuid = irq_choose_cpu(irq);
781 827
782 cpus_and(tmp, cpumask, cpu_online_map); 828 mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid);
829 } else {
830 cpumask_t tmp;
783 831
784 mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 832 cpus_and(tmp, cpumask, cpu_online_map);
785 mpic_physmask(cpus_addr(tmp)[0])); 833
834 mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION),
835 mpic_physmask(cpus_addr(tmp)[0]));
836 }
786} 837}
787 838
788static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type) 839static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)