diff options
author | Kumar Gala <galak@kernel.crashing.org> | 2008-10-28 14:01:39 -0400 |
---|---|---|
committer | Paul Mackerras <paulus@samba.org> | 2008-10-31 01:13:50 -0400 |
commit | 3c10c9c45e290022ca7d2aa1ad33a0b6ed767520 (patch) | |
tree | 002769098cd2b53aad995acac3c42f0331302588 /arch | |
parent | f9226d572d2f8b5f564596db8c6a13e458c46191 (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')
-rw-r--r-- | arch/powerpc/include/asm/mpic.h | 2 | ||||
-rw-r--r-- | arch/powerpc/platforms/85xx/mpc85xx_ds.c | 3 | ||||
-rw-r--r-- | arch/powerpc/platforms/86xx/pic.c | 3 | ||||
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 59 |
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 | ||
567 | static 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 | ||
606 | static 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 | ||
788 | static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type) | 839 | static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type) |