diff options
Diffstat (limited to 'arch/powerpc/sysdev/mpic.c')
| -rw-r--r-- | arch/powerpc/sysdev/mpic.c | 59 |
1 files changed, 55 insertions, 4 deletions
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) |
