X-Git-Url: http://www.pilppa.org/gitweb/gitweb.cgi?a=blobdiff_plain;f=arch%2Fpowerpc%2Fsysdev%2Fmpic.c;h=f6299cca7814b8eda0434e94953db9fe6b38ba9e;hb=3c10c9c45e290022ca7d2aa1ad33a0b6ed767520;hp=8e3478c995ef6ebc34d30a150dde4b6533730393;hpb=f9226d572d2f8b5f564596db8c6a13e458c46191;p=linux-2.6-omap-h63xx.git diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c index 8e3478c995e..f6299cca781 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) #endif /* CONFIG_MPIC_U3_HT_IRQS */ +#ifdef CONFIG_SMP +static int irq_choose_cpu(unsigned int virt_irq) +{ + cpumask_t mask = irq_desc[virt_irq].affinity; + int cpuid; + + if (cpus_equal(mask, CPU_MASK_ALL)) { + static int irq_rover; + static DEFINE_SPINLOCK(irq_rover_lock); + unsigned long flags; + + /* Round-robin distribution... */ + do_round_robin: + spin_lock_irqsave(&irq_rover_lock, flags); + + while (!cpu_online(irq_rover)) { + if (++irq_rover >= NR_CPUS) + irq_rover = 0; + } + cpuid = irq_rover; + do { + if (++irq_rover >= NR_CPUS) + irq_rover = 0; + } while (!cpu_online(irq_rover)); + + spin_unlock_irqrestore(&irq_rover_lock, flags); + } else { + cpumask_t tmp; + + cpus_and(tmp, cpu_online_map, mask); + + if (cpus_empty(tmp)) + goto do_round_robin; + + cpuid = first_cpu(tmp); + } + + return cpuid; +} +#else +static int irq_choose_cpu(unsigned int virt_irq) +{ + return hard_smp_processor_id(); +} +#endif #define mpic_irq_to_hw(virq) ((unsigned int)irq_map[virq].hwirq) @@ -777,12 +822,18 @@ void mpic_set_affinity(unsigned int irq, cpumask_t cpumask) struct mpic *mpic = mpic_from_irq(irq); unsigned int src = mpic_irq_to_hw(irq); - cpumask_t tmp; + if (mpic->flags & MPIC_SINGLE_DEST_CPU) { + int cpuid = irq_choose_cpu(irq); - cpus_and(tmp, cpumask, cpu_online_map); + mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid); + } else { + cpumask_t tmp; - mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), - mpic_physmask(cpus_addr(tmp)[0])); + cpus_and(tmp, cpumask, cpu_online_map); + + mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), + mpic_physmask(cpus_addr(tmp)[0])); + } } static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)