diff options
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r-- | arch/powerpc/sysdev/mpic.c | 68 |
1 files changed, 62 insertions, 6 deletions
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 8e3478c995ef..1890fb085cde 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 get_hard_smp_processor_id(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); | ||
827 | |||
828 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); | ||
829 | } else { | ||
830 | cpumask_t tmp; | ||
781 | 831 | ||
782 | cpus_and(tmp, cpumask, cpu_online_map); | 832 | cpus_and(tmp, cpumask, cpu_online_map); |
783 | 833 | ||
784 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), | 834 | mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), |
785 | mpic_physmask(cpus_addr(tmp)[0])); | 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) |
@@ -1220,6 +1271,7 @@ void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count) | |||
1220 | void __init mpic_init(struct mpic *mpic) | 1271 | void __init mpic_init(struct mpic *mpic) |
1221 | { | 1272 | { |
1222 | int i; | 1273 | int i; |
1274 | int cpu; | ||
1223 | 1275 | ||
1224 | BUG_ON(mpic->num_sources == 0); | 1276 | BUG_ON(mpic->num_sources == 0); |
1225 | 1277 | ||
@@ -1262,6 +1314,11 @@ void __init mpic_init(struct mpic *mpic) | |||
1262 | 1314 | ||
1263 | mpic_pasemi_msi_init(mpic); | 1315 | mpic_pasemi_msi_init(mpic); |
1264 | 1316 | ||
1317 | if (mpic->flags & MPIC_PRIMARY) | ||
1318 | cpu = hard_smp_processor_id(); | ||
1319 | else | ||
1320 | cpu = 0; | ||
1321 | |||
1265 | for (i = 0; i < mpic->num_sources; i++) { | 1322 | for (i = 0; i < mpic->num_sources; i++) { |
1266 | /* start with vector = source number, and masked */ | 1323 | /* start with vector = source number, and masked */ |
1267 | u32 vecpri = MPIC_VECPRI_MASK | i | | 1324 | u32 vecpri = MPIC_VECPRI_MASK | i | |
@@ -1272,8 +1329,7 @@ void __init mpic_init(struct mpic *mpic) | |||
1272 | continue; | 1329 | continue; |
1273 | /* init hw */ | 1330 | /* init hw */ |
1274 | mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); | 1331 | mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri); |
1275 | mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), | 1332 | mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu); |
1276 | 1 << hard_smp_processor_id()); | ||
1277 | } | 1333 | } |
1278 | 1334 | ||
1279 | /* Init spurious vector */ | 1335 | /* Init spurious vector */ |