Merge branch 'x86/apic' into irq/numa
authorIngo Molnar <mingo@elte.hu>
Fri, 1 May 2009 17:02:50 +0000 (19:02 +0200)
committerIngo Molnar <mingo@elte.hu>
Fri, 1 May 2009 17:02:50 +0000 (19:02 +0200)
Conflicts:
arch/x86/kernel/apic/io_apic.c

Merge reason: non-trivial interaction between ongoing work in io_apic.c
              and the NUMA migration feature in the irq tree.

Signed-off-by: Ingo Molnar <mingo@elte.hu>
1  2 
Documentation/kernel-parameters.txt
arch/x86/Kconfig
arch/x86/include/asm/io_apic.h
arch/x86/kernel/apic/io_apic.c
arch/x86/kernel/apic/x2apic_uv_x.c
drivers/pci/intr_remapping.c

Simple merge
Simple merge
Simple merge
@@@ -2332,6 -2230,115 +2201,118 @@@ static int ioapic_retrigger_irq(unsigne
   */
  
  #ifdef CONFIG_SMP
 -static void
 -__target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
+ static void send_cleanup_vector(struct irq_cfg *cfg)
+ {
+       cpumask_var_t cleanup_mask;
+       if (unlikely(!alloc_cpumask_var(&cleanup_mask, GFP_ATOMIC))) {
+               unsigned int i;
+               cfg->move_cleanup_count = 0;
+               for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+                       cfg->move_cleanup_count++;
+               for_each_cpu_and(i, cfg->old_domain, cpu_online_mask)
+                       apic->send_IPI_mask(cpumask_of(i), IRQ_MOVE_CLEANUP_VECTOR);
+       } else {
+               cpumask_and(cleanup_mask, cfg->old_domain, cpu_online_mask);
+               cfg->move_cleanup_count = cpumask_weight(cleanup_mask);
+               apic->send_IPI_mask(cleanup_mask, IRQ_MOVE_CLEANUP_VECTOR);
+               free_cpumask_var(cleanup_mask);
+       }
+       cfg->move_in_progress = 0;
+ }
 -      /* check that before desc->addinity get updated */
 -      set_extra_move_desc(desc, mask);
 -
++static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
+ {
+       int apic, pin;
+       struct irq_pin_list *entry;
+       u8 vector = cfg->vector;
+       entry = cfg->irq_2_pin;
+       for (;;) {
+               unsigned int reg;
+               if (!entry)
+                       break;
+               apic = entry->apic;
+               pin = entry->pin;
+               /*
+                * With interrupt-remapping, destination information comes
+                * from interrupt-remapping table entry.
+                */
+               if (!irq_remapped(irq))
+                       io_apic_write(apic, 0x11 + pin*2, dest);
+               reg = io_apic_read(apic, 0x10 + pin*2);
+               reg &= ~IO_APIC_REDIR_VECTOR_MASK;
+               reg |= vector;
+               io_apic_modify(apic, 0x10 + pin*2, reg);
+               if (!entry->next)
+                       break;
+               entry = entry->next;
+       }
+ }
++static int
++assign_irq_vector(int irq, struct irq_cfg *cfg, const struct cpumask *mask);
++
+ /*
+  * Either sets desc->affinity to a valid value, and returns
+  * ->cpu_mask_to_apicid of that, or returns BAD_APICID and
+  * leaves desc->affinity untouched.
+  */
+ static unsigned int
+ set_desc_affinity(struct irq_desc *desc, const struct cpumask *mask)
+ {
+       struct irq_cfg *cfg;
+       unsigned int irq;
+       if (!cpumask_intersects(mask, cpu_online_mask))
+               return BAD_APICID;
+       irq = desc->irq;
+       cfg = desc->chip_data;
+       if (assign_irq_vector(irq, cfg, mask))
+               return BAD_APICID;
 -static void
+       cpumask_copy(desc->affinity, mask);
+       return apic->cpu_mask_to_apicid_and(desc->affinity, cfg->domain);
+ }
 -static void
++static int
+ set_ioapic_affinity_irq_desc(struct irq_desc *desc, const struct cpumask *mask)
+ {
+       struct irq_cfg *cfg;
+       unsigned long flags;
+       unsigned int dest;
+       unsigned int irq;
++      int ret = -1;
+       irq = desc->irq;
+       cfg = desc->chip_data;
+       spin_lock_irqsave(&ioapic_lock, flags);
+       dest = set_desc_affinity(desc, mask);
+       if (dest != BAD_APICID) {
+               /* Only the high 8 bits are valid. */
+               dest = SET_APIC_LOGICAL_ID(dest);
+               __target_IO_APIC_irq(irq, dest, cfg);
++              ret = 0;
+       }
+       spin_unlock_irqrestore(&ioapic_lock, flags);
++
++      return ret;
+ }
 -      set_ioapic_affinity_irq_desc(desc, mask);
++static int
+ set_ioapic_affinity_irq(unsigned int irq, const struct cpumask *mask)
+ {
+       struct irq_desc *desc;
+       desc = irq_to_desc(irq);
++      return set_ioapic_affinity_irq_desc(desc, mask);
+ }
  
  #ifdef CONFIG_INTR_REMAP
  
Simple merge
Simple merge