aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/sysdev/mpic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
-rw-r--r--arch/powerpc/sysdev/mpic.c68
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
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 get_hard_smp_processor_id(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);
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
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)
@@ -1220,6 +1271,7 @@ void __init mpic_set_default_senses(struct mpic *mpic, u8 *senses, int count)
1220void __init mpic_init(struct mpic *mpic) 1271void __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 */