diff options
author | David Vrabel <david.vrabel@csr.com> | 2008-11-19 14:48:07 +0000 |
---|---|---|
committer | David Vrabel <david.vrabel@csr.com> | 2008-11-19 14:48:07 +0000 |
commit | dba0a918722ee0f0ba3442575e4448c3ab622be4 (patch) | |
tree | fdb466cf09e7916135098d651b18924b2fe9ba5f /arch/powerpc/sysdev/mpic.c | |
parent | 0996e6382482ce9014787693d3884e9468153a5c (diff) | |
parent | 7f0f598a0069d1ab072375965a4b69137233169c (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux-2.6 into for-upstream
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 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) |