|
@@ -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)
|