[PATCH] x86_64 irq: Simplify assign_irq_vector's arguments.
[powerpc.git] / arch / x86_64 / kernel / io_apic.c
index 74671de..79fa7b2 100644 (file)
 #include <asm/msidef.h>
 #include <asm/hypertransport.h>
 
-static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result);
+struct irq_cfg {
+       cpumask_t domain;
+       u8 vector;
+};
+
+/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
+struct irq_cfg irq_cfg[NR_IRQS] __read_mostly = {
+       [0] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 0 },
+       [1] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 1 },
+       [2] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 2 },
+       [3] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 3 },
+       [4] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 4 },
+       [5] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 5 },
+       [6] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 6 },
+       [7] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 7 },
+       [8] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 8 },
+       [9] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 9 },
+       [10] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 10 },
+       [11] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 11 },
+       [12] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 12 },
+       [13] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 13 },
+       [14] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 14 },
+       [15] = { .domain = CPU_MASK_ALL, .vector = FIRST_EXTERNAL_VECTOR + 15 },
+};
+
+static int assign_irq_vector(int irq, cpumask_t mask);
 
 #define __apicdebuginit  __init
 
@@ -74,7 +99,7 @@ int nr_ioapic_registers[MAX_IO_APICS];
  * Rough estimation of how many shared IRQs there are, can
  * be changed anytime.
  */
-#define MAX_PLUS_SHARED_IRQS NR_IRQ_VECTORS
+#define MAX_PLUS_SHARED_IRQS NR_IRQS
 #define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
 
 /*
@@ -149,11 +174,11 @@ static inline void io_apic_sync(unsigned int apic)
                reg = io_apic_read(entry->apic, 0x10 + R + pin*2);      \
                reg ACTION;                                             \
                io_apic_modify(entry->apic, reg);                       \
+               FINAL;                                                  \
                if (!entry->next)                                       \
                        break;                                          \
                entry = irq_2_pin + entry->next;                        \
        }                                                               \
-       FINAL;                                                          \
 }
 
 union entry_union {
@@ -237,19 +262,19 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
 
 static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
 {
+       struct irq_cfg *cfg = irq_cfg + irq;
        unsigned long flags;
        unsigned int dest;
        cpumask_t tmp;
-       int vector;
 
        cpus_and(tmp, mask, cpu_online_map);
        if (cpus_empty(tmp))
                return;
 
-       vector = assign_irq_vector(irq, mask, &tmp);
-       if (vector < 0)
+       if (assign_irq_vector(irq, mask))
                return;
 
+       cpus_and(tmp, cfg->domain, mask);
        dest = cpu_mask_to_apicid(tmp);
 
        /*
@@ -258,7 +283,7 @@ static void set_ioapic_affinity_irq(unsigned int irq, cpumask_t mask)
        dest = SET_APIC_LOGICAL_ID(dest);
 
        spin_lock_irqsave(&ioapic_lock, flags);
-       __target_IO_APIC_irq(irq, dest, vector);
+       __target_IO_APIC_irq(irq, dest, cfg->vector);
        irq_desc[irq].affinity = mask;
        spin_unlock_irqrestore(&ioapic_lock, flags);
 }
@@ -613,47 +638,7 @@ static int pin_2_irq(int idx, int apic, int pin)
        return irq;
 }
 
-
-/* irq_vectors is indexed by the sum of all RTEs in all I/O APICs. */
-static u8 irq_vector[NR_IRQ_VECTORS] __read_mostly = {
-       [0] = FIRST_EXTERNAL_VECTOR + 0,
-       [1] = FIRST_EXTERNAL_VECTOR + 1,
-       [2] = FIRST_EXTERNAL_VECTOR + 2,
-       [3] = FIRST_EXTERNAL_VECTOR + 3,
-       [4] = FIRST_EXTERNAL_VECTOR + 4,
-       [5] = FIRST_EXTERNAL_VECTOR + 5,
-       [6] = FIRST_EXTERNAL_VECTOR + 6,
-       [7] = FIRST_EXTERNAL_VECTOR + 7,
-       [8] = FIRST_EXTERNAL_VECTOR + 8,
-       [9] = FIRST_EXTERNAL_VECTOR + 9,
-       [10] = FIRST_EXTERNAL_VECTOR + 10,
-       [11] = FIRST_EXTERNAL_VECTOR + 11,
-       [12] = FIRST_EXTERNAL_VECTOR + 12,
-       [13] = FIRST_EXTERNAL_VECTOR + 13,
-       [14] = FIRST_EXTERNAL_VECTOR + 14,
-       [15] = FIRST_EXTERNAL_VECTOR + 15,
-};
-
-static cpumask_t irq_domain[NR_IRQ_VECTORS] __read_mostly = {
-       [0] = CPU_MASK_ALL,
-       [1] = CPU_MASK_ALL,
-       [2] = CPU_MASK_ALL,
-       [3] = CPU_MASK_ALL,
-       [4] = CPU_MASK_ALL,
-       [5] = CPU_MASK_ALL,
-       [6] = CPU_MASK_ALL,
-       [7] = CPU_MASK_ALL,
-       [8] = CPU_MASK_ALL,
-       [9] = CPU_MASK_ALL,
-       [10] = CPU_MASK_ALL,
-       [11] = CPU_MASK_ALL,
-       [12] = CPU_MASK_ALL,
-       [13] = CPU_MASK_ALL,
-       [14] = CPU_MASK_ALL,
-       [15] = CPU_MASK_ALL,
-};
-
-static int __assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
+static int __assign_irq_vector(int irq, cpumask_t mask)
 {
        /*
         * NOTE! The local APIC isn't very good at handling
@@ -668,21 +653,23 @@ static int __assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
         */
        static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
        cpumask_t old_mask = CPU_MASK_NONE;
-       int old_vector = -1;
+       unsigned int old_vector;
        int cpu;
+       struct irq_cfg *cfg;
 
-       BUG_ON((unsigned)irq >= NR_IRQ_VECTORS);
+       BUG_ON((unsigned)irq >= NR_IRQS);
+       cfg = &irq_cfg[irq];
 
        /* Only try and allocate irqs on cpus that are present */
        cpus_and(mask, mask, cpu_online_map);
 
-       if (irq_vector[irq] > 0)
-               old_vector = irq_vector[irq];
-       if (old_vector > 0) {
-               cpus_and(*result, irq_domain[irq], mask);
-               if (!cpus_empty(*result))
-                       return old_vector;
-               cpus_and(old_mask, irq_domain[irq], cpu_online_map);
+       old_vector = cfg->vector;
+       if (old_vector) {
+               cpumask_t tmp;
+               cpus_and(tmp, cfg->domain, mask);
+               if (!cpus_empty(tmp))
+                       return 0;
+               cpus_and(old_mask, cfg->domain, cpu_online_map);
        }
 
        for_each_cpu_mask(cpu, mask) {
@@ -716,39 +703,41 @@ next:
                        per_cpu(vector_irq, old_cpu)[old_vector] = -1;
                for_each_cpu_mask(new_cpu, new_mask)
                        per_cpu(vector_irq, new_cpu)[vector] = irq;
-               irq_vector[irq] = vector;
-               irq_domain[irq] = domain;
-               cpus_and(*result, domain, mask);
-               return vector;
+               cfg->vector = vector;
+               cfg->domain = domain;
+               return 0;
        }
        return -ENOSPC;
 }
 
-static int assign_irq_vector(int irq, cpumask_t mask, cpumask_t *result)
+static int assign_irq_vector(int irq, cpumask_t mask)
 {
-       int vector;
+       int err;
        unsigned long flags;
 
        spin_lock_irqsave(&vector_lock, flags);
-       vector = __assign_irq_vector(irq, mask, result);
+       err = __assign_irq_vector(irq, mask);
        spin_unlock_irqrestore(&vector_lock, flags);
-       return vector;
+       return err;
 }
 
 static void __clear_irq_vector(int irq)
 {
+       struct irq_cfg *cfg;
        cpumask_t mask;
        int cpu, vector;
 
-       BUG_ON(!irq_vector[irq]);
+       BUG_ON((unsigned)irq >= NR_IRQS);
+       cfg = &irq_cfg[irq];
+       BUG_ON(!cfg->vector);
 
-       vector = irq_vector[irq];
-       cpus_and(mask, irq_domain[irq], cpu_online_map);
+       vector = cfg->vector;
+       cpus_and(mask, cfg->domain, cpu_online_map);
        for_each_cpu_mask(cpu, mask)
                per_cpu(vector_irq, cpu)[vector] = -1;
 
-       irq_vector[irq] = 0;
-       irq_domain[irq] = CPU_MASK_NONE;
+       cfg->vector = 0;
+       cfg->domain = CPU_MASK_NONE;
 }
 
 void __setup_vector_irq(int cpu)
@@ -758,10 +747,10 @@ void __setup_vector_irq(int cpu)
        int irq, vector;
 
        /* Mark the inuse vectors */
-       for (irq = 0; irq < NR_IRQ_VECTORS; ++irq) {
-               if (!cpu_isset(cpu, irq_domain[irq]))
+       for (irq = 0; irq < NR_IRQS; ++irq) {
+               if (!cpu_isset(cpu, irq_cfg[irq].domain))
                        continue;
-               vector = irq_vector[irq];
+               vector = irq_cfg[irq].vector;
                per_cpu(vector_irq, cpu)[vector] = irq;
        }
        /* Mark the free vectors */
@@ -769,7 +758,7 @@ void __setup_vector_irq(int cpu)
                irq = per_cpu(vector_irq, cpu)[vector];
                if (irq < 0)
                        continue;
-               if (!cpu_isset(cpu, irq_domain[irq]))
+               if (!cpu_isset(cpu, irq_cfg[irq].domain))
                        per_cpu(vector_irq, cpu)[vector] = -1;
        }
 }
@@ -790,22 +779,24 @@ static void ioapic_register_intr(int irq, unsigned long trigger)
 static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
                              int trigger, int polarity)
 {
+       struct irq_cfg *cfg = irq_cfg + irq;
        struct IO_APIC_route_entry entry;
        cpumask_t mask;
-       int vector;
        unsigned long flags;
 
        if (!IO_APIC_IRQ(irq))
                return;
 
-       vector = assign_irq_vector(irq, TARGET_CPUS, &mask);
-       if (vector < 0)
+       mask = TARGET_CPUS;
+       if (assign_irq_vector(irq, mask))
                return;
 
+       cpus_and(mask, cfg->domain, mask);
+
        apic_printk(APIC_VERBOSE,KERN_DEBUG
                    "IOAPIC[%d]: Set routing entry (%d-%d -> 0x%x -> "
                    "IRQ %d Mode:%i Active:%i)\n",
-                   apic, mp_ioapics[apic].mpc_apicid, pin, vector,
+                   apic, mp_ioapics[apic].mpc_apicid, pin, cfg->vector,
                    irq, trigger, polarity);
 
        /*
@@ -819,7 +810,7 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
        entry.mask = 0;                         /* enable IRQ */
        entry.trigger = trigger;
        entry.polarity = polarity;
-       entry.vector = vector;
+       entry.vector = cfg->vector;
 
        /* Mask level triggered irqs.
         * Use IRQ_DELAYED_DISABLE for edge triggered irqs.
@@ -1346,16 +1337,15 @@ static unsigned int startup_ioapic_irq(unsigned int irq)
 
 static int ioapic_retrigger_irq(unsigned int irq)
 {
+       struct irq_cfg *cfg = &irq_cfg[irq];
        cpumask_t mask;
-       unsigned vector;
        unsigned long flags;
 
        spin_lock_irqsave(&vector_lock, flags);
-       vector = irq_vector[irq];
        cpus_clear(mask);
-       cpu_set(first_cpu(irq_domain[irq]), mask);
+       cpu_set(first_cpu(cfg->domain), mask);
 
-       send_IPI_mask(mask, vector);
+       send_IPI_mask(mask, cfg->vector);
        spin_unlock_irqrestore(&vector_lock, flags);
 
        return 1;
@@ -1430,7 +1420,7 @@ static inline void init_IO_APIC_traps(void)
         */
        for (irq = 0; irq < NR_IRQS ; irq++) {
                int tmp = irq;
-               if (IO_APIC_IRQ(tmp) && !irq_vector[tmp]) {
+               if (IO_APIC_IRQ(tmp) && !irq_cfg[tmp].vector) {
                        /*
                         * Hmm.. We don't have an entry for this,
                         * so default to an old-fashioned 8259
@@ -1569,15 +1559,14 @@ static inline void unlock_ExtINT_logic(void)
  */
 static inline void check_timer(void)
 {
+       struct irq_cfg *cfg = irq_cfg + 0;
        int apic1, pin1, apic2, pin2;
-       int vector;
-       cpumask_t mask;
 
        /*
         * get/set the timer IRQ vector:
         */
        disable_8259A_irq(0);
-       vector = assign_irq_vector(0, TARGET_CPUS, &mask);
+       assign_irq_vector(0, TARGET_CPUS);
 
        /*
         * Subtle, code in do_timer_interrupt() expects an AEOI
@@ -1597,7 +1586,7 @@ static inline void check_timer(void)
        apic2 = ioapic_i8259.apic;
 
        apic_printk(APIC_VERBOSE,KERN_INFO "..TIMER: vector=0x%02X apic1=%d pin1=%d apic2=%d pin2=%d\n",
-               vector, apic1, pin1, apic2, pin2);
+               cfg->vector, apic1, pin1, apic2, pin2);
 
        if (pin1 != -1) {
                /*
@@ -1628,7 +1617,7 @@ static inline void check_timer(void)
                /*
                 * legacy devices should be connected to IO APIC #0
                 */
-               setup_ExtINT_IRQ0_pin(apic2, pin2, vector);
+               setup_ExtINT_IRQ0_pin(apic2, pin2, cfg->vector);
                if (timer_irq_works()) {
                        apic_printk(APIC_VERBOSE," works.\n");
                        nmi_watchdog_default();
@@ -1653,14 +1642,14 @@ static inline void check_timer(void)
 
        disable_8259A_irq(0);
        irq_desc[0].chip = &lapic_irq_type;
-       apic_write(APIC_LVT0, APIC_DM_FIXED | vector);  /* Fixed mode */
+       apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector);     /* Fixed mode */
        enable_8259A_irq(0);
 
        if (timer_irq_works()) {
                apic_printk(APIC_VERBOSE," works.\n");
                return;
        }
-       apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | vector);
+       apic_write(APIC_LVT0, APIC_LVT_MASKED | APIC_DM_FIXED | cfg->vector);
        apic_printk(APIC_VERBOSE," failed.\n");
 
        apic_printk(APIC_VERBOSE, KERN_INFO "...trying to set up timer as ExtINT IRQ...");
@@ -1807,19 +1796,16 @@ int create_irq(void)
        /* Allocate an unused irq */
        int irq;
        int new;
-       int vector = 0;
        unsigned long flags;
-       cpumask_t mask;
 
        irq = -ENOSPC;
        spin_lock_irqsave(&vector_lock, flags);
        for (new = (NR_IRQS - 1); new >= 0; new--) {
                if (platform_legacy_irq(new))
                        continue;
-               if (irq_vector[new] != 0)
+               if (irq_cfg[new].vector != 0)
                        continue;
-               vector = __assign_irq_vector(new, TARGET_CPUS, &mask);
-               if (likely(vector > 0))
+               if (__assign_irq_vector(new, TARGET_CPUS) == 0)
                        irq = new;
                break;
        }
@@ -1848,12 +1834,15 @@ void destroy_irq(unsigned int irq)
 #ifdef CONFIG_PCI_MSI
 static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_msg *msg)
 {
-       int vector;
+       struct irq_cfg *cfg = irq_cfg + irq;
+       int err;
        unsigned dest;
        cpumask_t tmp;
 
-       vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
-       if (vector >= 0) {
+       tmp = TARGET_CPUS;
+       err = assign_irq_vector(irq, tmp);
+       if (!err) {
+               cpus_and(tmp, cfg->domain, tmp);
                dest = cpu_mask_to_apicid(tmp);
 
                msg->address_hi = MSI_ADDR_BASE_HI;
@@ -1873,33 +1862,33 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms
                        ((INT_DELIVERY_MODE != dest_LowestPrio) ?
                                MSI_DATA_DELIVERY_FIXED:
                                MSI_DATA_DELIVERY_LOWPRI) |
-                       MSI_DATA_VECTOR(vector);
+                       MSI_DATA_VECTOR(cfg->vector);
        }
-       return vector;
+       return err;
 }
 
 #ifdef CONFIG_SMP
 static void set_msi_irq_affinity(unsigned int irq, cpumask_t mask)
 {
+       struct irq_cfg *cfg = irq_cfg + irq;
        struct msi_msg msg;
        unsigned int dest;
        cpumask_t tmp;
-       int vector;
 
        cpus_and(tmp, mask, cpu_online_map);
        if (cpus_empty(tmp))
                return;
 
-       vector = assign_irq_vector(irq, mask, &tmp);
-       if (vector < 0)
+       if (assign_irq_vector(irq, mask))
                return;
 
+       cpus_and(tmp, cfg->domain, mask);
        dest = cpu_mask_to_apicid(tmp);
 
        read_msi_msg(irq, &msg);
 
        msg.data &= ~MSI_DATA_VECTOR_MASK;
-       msg.data |= MSI_DATA_VECTOR(vector);
+       msg.data |= MSI_DATA_VECTOR(cfg->vector);
        msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
        msg.address_lo |= MSI_ADDR_DEST_ID(dest);
 
@@ -1975,21 +1964,21 @@ static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
 
 static void set_ht_irq_affinity(unsigned int irq, cpumask_t mask)
 {
+       struct irq_cfg *cfg = irq_cfg + irq;
        unsigned int dest;
        cpumask_t tmp;
-       int vector;
 
        cpus_and(tmp, mask, cpu_online_map);
        if (cpus_empty(tmp))
                return;
 
-       vector = assign_irq_vector(irq, mask, &tmp);
-       if (vector < 0)
+       if (assign_irq_vector(irq, mask))
                return;
 
+       cpus_and(tmp, cfg->domain, mask);
        dest = cpu_mask_to_apicid(tmp);
 
-       target_ht_irq(irq, dest, vector);
+       target_ht_irq(irq, dest, cfg->vector);
        irq_desc[irq].affinity = mask;
 }
 #endif
@@ -2007,14 +1996,17 @@ static struct irq_chip ht_irq_chip = {
 
 int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
 {
-       int vector;
+       struct irq_cfg *cfg = irq_cfg + irq;
+       int err;
        cpumask_t tmp;
 
-       vector = assign_irq_vector(irq, TARGET_CPUS, &tmp);
-       if (vector >= 0) {
+       tmp = TARGET_CPUS;
+       err = assign_irq_vector(irq, tmp);
+       if (!err) {
                struct ht_irq_msg msg;
                unsigned dest;
 
+               cpus_and(tmp, cfg->domain, tmp);
                dest = cpu_mask_to_apicid(tmp);
 
                msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest);
@@ -2022,7 +2014,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
                msg.address_lo =
                        HT_IRQ_LOW_BASE |
                        HT_IRQ_LOW_DEST_ID(dest) |
-                       HT_IRQ_LOW_VECTOR(vector) |
+                       HT_IRQ_LOW_VECTOR(cfg->vector) |
                        ((INT_DEST_MODE == 0) ?
                                HT_IRQ_LOW_DM_PHYSICAL :
                                HT_IRQ_LOW_DM_LOGICAL) |
@@ -2037,7 +2029,7 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
                set_irq_chip_and_handler_name(irq, &ht_irq_chip,
                                              handle_edge_irq, "edge");
        }
-       return vector;
+       return err;
 }
 #endif /* CONFIG_HT_IRQ */
 
@@ -2108,7 +2100,7 @@ void __init setup_ioapic_dest(void)
                         * when you have too many devices, because at that time only boot
                         * cpu is online.
                         */
-                       if(!irq_vector[irq])
+                       if (!irq_cfg[irq].vector)
                                setup_IO_APIC_irq(ioapic, pin, irq,
                                                  irq_trigger(irq_entry),
                                                  irq_polarity(irq_entry));