|
@@ -108,8 +108,33 @@ static int __init parse_noapic(char *str)
|
|
|
early_param("noapic", parse_noapic);
|
|
|
|
|
|
struct irq_pin_list;
|
|
|
+
|
|
|
+/*
|
|
|
+ * This is performance-critical, we want to do it O(1)
|
|
|
+ *
|
|
|
+ * the indexing order of this array favors 1:1 mappings
|
|
|
+ * between pins and IRQs.
|
|
|
+ */
|
|
|
+
|
|
|
+struct irq_pin_list {
|
|
|
+ int apic, pin;
|
|
|
+ struct irq_pin_list *next;
|
|
|
+};
|
|
|
+
|
|
|
+static struct irq_pin_list *get_one_free_irq_2_pin(int cpu)
|
|
|
+{
|
|
|
+ struct irq_pin_list *pin;
|
|
|
+ int node;
|
|
|
+
|
|
|
+ node = cpu_to_node(cpu);
|
|
|
+
|
|
|
+ pin = kzalloc_node(sizeof(*pin), GFP_ATOMIC, node);
|
|
|
+ printk(KERN_DEBUG " alloc irq_2_pin on cpu %d node %d\n", cpu, node);
|
|
|
+
|
|
|
+ return pin;
|
|
|
+}
|
|
|
+
|
|
|
struct irq_cfg {
|
|
|
- unsigned int irq;
|
|
|
struct irq_pin_list *irq_2_pin;
|
|
|
cpumask_t domain;
|
|
|
cpumask_t old_domain;
|
|
@@ -119,81 +144,95 @@ struct irq_cfg {
|
|
|
};
|
|
|
|
|
|
/* irq_cfg is indexed by the sum of all RTEs in all I/O APICs. */
|
|
|
+#ifdef CONFIG_SPARSE_IRQ
|
|
|
+static struct irq_cfg irq_cfgx[] = {
|
|
|
+#else
|
|
|
static struct irq_cfg irq_cfgx[NR_IRQS] = {
|
|
|
- [0] = { .irq = 0, .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, },
|
|
|
- [1] = { .irq = 1, .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, },
|
|
|
- [2] = { .irq = 2, .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, },
|
|
|
- [3] = { .irq = 3, .domain = CPU_MASK_ALL, .vector = IRQ3_VECTOR, },
|
|
|
- [4] = { .irq = 4, .domain = CPU_MASK_ALL, .vector = IRQ4_VECTOR, },
|
|
|
- [5] = { .irq = 5, .domain = CPU_MASK_ALL, .vector = IRQ5_VECTOR, },
|
|
|
- [6] = { .irq = 6, .domain = CPU_MASK_ALL, .vector = IRQ6_VECTOR, },
|
|
|
- [7] = { .irq = 7, .domain = CPU_MASK_ALL, .vector = IRQ7_VECTOR, },
|
|
|
- [8] = { .irq = 8, .domain = CPU_MASK_ALL, .vector = IRQ8_VECTOR, },
|
|
|
- [9] = { .irq = 9, .domain = CPU_MASK_ALL, .vector = IRQ9_VECTOR, },
|
|
|
- [10] = { .irq = 10, .domain = CPU_MASK_ALL, .vector = IRQ10_VECTOR, },
|
|
|
- [11] = { .irq = 11, .domain = CPU_MASK_ALL, .vector = IRQ11_VECTOR, },
|
|
|
- [12] = { .irq = 12, .domain = CPU_MASK_ALL, .vector = IRQ12_VECTOR, },
|
|
|
- [13] = { .irq = 13, .domain = CPU_MASK_ALL, .vector = IRQ13_VECTOR, },
|
|
|
- [14] = { .irq = 14, .domain = CPU_MASK_ALL, .vector = IRQ14_VECTOR, },
|
|
|
- [15] = { .irq = 15, .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, },
|
|
|
+#endif
|
|
|
+ [0] = { .domain = CPU_MASK_ALL, .vector = IRQ0_VECTOR, },
|
|
|
+ [1] = { .domain = CPU_MASK_ALL, .vector = IRQ1_VECTOR, },
|
|
|
+ [2] = { .domain = CPU_MASK_ALL, .vector = IRQ2_VECTOR, },
|
|
|
+ [3] = { .domain = CPU_MASK_ALL, .vector = IRQ3_VECTOR, },
|
|
|
+ [4] = { .domain = CPU_MASK_ALL, .vector = IRQ4_VECTOR, },
|
|
|
+ [5] = { .domain = CPU_MASK_ALL, .vector = IRQ5_VECTOR, },
|
|
|
+ [6] = { .domain = CPU_MASK_ALL, .vector = IRQ6_VECTOR, },
|
|
|
+ [7] = { .domain = CPU_MASK_ALL, .vector = IRQ7_VECTOR, },
|
|
|
+ [8] = { .domain = CPU_MASK_ALL, .vector = IRQ8_VECTOR, },
|
|
|
+ [9] = { .domain = CPU_MASK_ALL, .vector = IRQ9_VECTOR, },
|
|
|
+ [10] = { .domain = CPU_MASK_ALL, .vector = IRQ10_VECTOR, },
|
|
|
+ [11] = { .domain = CPU_MASK_ALL, .vector = IRQ11_VECTOR, },
|
|
|
+ [12] = { .domain = CPU_MASK_ALL, .vector = IRQ12_VECTOR, },
|
|
|
+ [13] = { .domain = CPU_MASK_ALL, .vector = IRQ13_VECTOR, },
|
|
|
+ [14] = { .domain = CPU_MASK_ALL, .vector = IRQ14_VECTOR, },
|
|
|
+ [15] = { .domain = CPU_MASK_ALL, .vector = IRQ15_VECTOR, },
|
|
|
};
|
|
|
|
|
|
-#define for_each_irq_cfg(irq, cfg) \
|
|
|
- for (irq = 0, cfg = irq_cfgx; irq < nr_irqs; irq++, cfg++)
|
|
|
-
|
|
|
-static struct irq_cfg *irq_cfg(unsigned int irq)
|
|
|
+void __init arch_early_irq_init(void)
|
|
|
{
|
|
|
- return irq < nr_irqs ? irq_cfgx + irq : NULL;
|
|
|
+ struct irq_cfg *cfg;
|
|
|
+ struct irq_desc *desc;
|
|
|
+ int count;
|
|
|
+ int i;
|
|
|
+
|
|
|
+ cfg = irq_cfgx;
|
|
|
+ count = ARRAY_SIZE(irq_cfgx);
|
|
|
+
|
|
|
+ for (i = 0; i < count; i++) {
|
|
|
+ desc = irq_to_desc(i);
|
|
|
+ desc->chip_data = &cfg[i];
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-static struct irq_cfg *irq_cfg_alloc(unsigned int irq)
|
|
|
+#ifdef CONFIG_SPARSE_IRQ
|
|
|
+static struct irq_cfg *irq_cfg(unsigned int irq)
|
|
|
{
|
|
|
- return irq_cfg(irq);
|
|
|
+ struct irq_cfg *cfg = NULL;
|
|
|
+ struct irq_desc *desc;
|
|
|
+
|
|
|
+ desc = irq_to_desc(irq);
|
|
|
+ if (desc)
|
|
|
+ cfg = desc->chip_data;
|
|
|
+
|
|
|
+ return cfg;
|
|
|
}
|
|
|
|
|
|
-/*
|
|
|
- * Rough estimation of how many shared IRQs there are, can be changed
|
|
|
- * anytime.
|
|
|
- */
|
|
|
-#define MAX_PLUS_SHARED_IRQS NR_IRQS
|
|
|
-#define PIN_MAP_SIZE (MAX_PLUS_SHARED_IRQS + NR_IRQS)
|
|
|
+static struct irq_cfg *get_one_free_irq_cfg(int cpu)
|
|
|
+{
|
|
|
+ struct irq_cfg *cfg;
|
|
|
+ int node;
|
|
|
|
|
|
-/*
|
|
|
- * This is performance-critical, we want to do it O(1)
|
|
|
- *
|
|
|
- * the indexing order of this array favors 1:1 mappings
|
|
|
- * between pins and IRQs.
|
|
|
- */
|
|
|
+ node = cpu_to_node(cpu);
|
|
|
|
|
|
-struct irq_pin_list {
|
|
|
- int apic, pin;
|
|
|
- struct irq_pin_list *next;
|
|
|
-};
|
|
|
+ cfg = kzalloc_node(sizeof(*cfg), GFP_ATOMIC, node);
|
|
|
+ printk(KERN_DEBUG " alloc irq_cfg on cpu %d node %d\n", cpu, node);
|
|
|
|
|
|
-static struct irq_pin_list irq_2_pin_head[PIN_MAP_SIZE];
|
|
|
-static struct irq_pin_list *irq_2_pin_ptr;
|
|
|
+ return cfg;
|
|
|
+}
|
|
|
|
|
|
-static void __init irq_2_pin_init(void)
|
|
|
+void arch_init_chip_data(struct irq_desc *desc, int cpu)
|
|
|
{
|
|
|
- struct irq_pin_list *pin = irq_2_pin_head;
|
|
|
- int i;
|
|
|
-
|
|
|
- for (i = 1; i < PIN_MAP_SIZE; i++)
|
|
|
- pin[i-1].next = &pin[i];
|
|
|
+ struct irq_cfg *cfg;
|
|
|
|
|
|
- irq_2_pin_ptr = &pin[0];
|
|
|
+ cfg = desc->chip_data;
|
|
|
+ if (!cfg) {
|
|
|
+ desc->chip_data = get_one_free_irq_cfg(cpu);
|
|
|
+ if (!desc->chip_data) {
|
|
|
+ printk(KERN_ERR "can not alloc irq_cfg\n");
|
|
|
+ BUG_ON(1);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
-static struct irq_pin_list *get_one_free_irq_2_pin(void)
|
|
|
+#else
|
|
|
+static struct irq_cfg *irq_cfg(unsigned int irq)
|
|
|
{
|
|
|
- struct irq_pin_list *pin = irq_2_pin_ptr;
|
|
|
+ return irq < nr_irqs ? irq_cfgx + irq : NULL;
|
|
|
+}
|
|
|
|
|
|
- if (!pin)
|
|
|
- panic("can not get more irq_2_pin\n");
|
|
|
+#endif
|
|
|
|
|
|
- irq_2_pin_ptr = pin->next;
|
|
|
- pin->next = NULL;
|
|
|
- return pin;
|
|
|
+static inline void set_extra_move_desc(struct irq_desc *desc, cpumask_t mask)
|
|
|
+{
|
|
|
}
|
|
|
|
|
|
struct io_apic {
|
|
@@ -237,11 +276,10 @@ static inline void io_apic_modify(unsigned int apic, unsigned int reg, unsigned
|
|
|
writel(value, &io_apic->data);
|
|
|
}
|
|
|
|
|
|
-static bool io_apic_level_ack_pending(unsigned int irq)
|
|
|
+static bool io_apic_level_ack_pending(struct irq_cfg *cfg)
|
|
|
{
|
|
|
struct irq_pin_list *entry;
|
|
|
unsigned long flags;
|
|
|
- struct irq_cfg *cfg = irq_cfg(irq);
|
|
|
|
|
|
spin_lock_irqsave(&ioapic_lock, flags);
|
|
|
entry = cfg->irq_2_pin;
|
|
@@ -323,13 +361,12 @@ static void ioapic_mask_entry(int apic, int pin)
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_SMP
|
|
|
-static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
|
|
|
+static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, struct irq_cfg *cfg)
|
|
|
{
|
|
|
int apic, pin;
|
|
|
- struct irq_cfg *cfg;
|
|
|
struct irq_pin_list *entry;
|
|
|
+ u8 vector = cfg->vector;
|
|
|
|
|
|
- cfg = irq_cfg(irq);
|
|
|
entry = cfg->irq_2_pin;
|
|
|
for (;;) {
|
|
|
unsigned int reg;
|
|
@@ -359,24 +396,27 @@ static void __target_IO_APIC_irq(unsigned int irq, unsigned int dest, u8 vector)
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static int assign_irq_vector(int irq, cpumask_t mask);
|
|
|
+static int assign_irq_vector(int irq, struct irq_cfg *cfg, cpumask_t mask);
|
|
|
|
|
|
-static void set_ioapic_affinity_irq(unsigned int irq,
|
|
|
- const struct cpumask *mask)
|
|
|
+static void set_ioapic_affinity_irq_desc(struct irq_desc *desc,
|
|
|
+ const struct cpumask *mask)
|
|
|
{
|
|
|
struct irq_cfg *cfg;
|
|
|
unsigned long flags;
|
|
|
unsigned int dest;
|
|
|
cpumask_t tmp;
|
|
|
- struct irq_desc *desc;
|
|
|
+ unsigned int irq;
|
|
|
|
|
|
if (!cpumask_intersects(mask, cpu_online_mask))
|
|
|
return;
|
|
|
|
|
|
- cfg = irq_cfg(irq);
|
|
|
- if (assign_irq_vector(irq, *mask))
|
|
|
+ irq = desc->irq;
|
|
|
+ cfg = desc->chip_data;
|
|
|
+ if (assign_irq_vector(irq, cfg, *mask))
|
|
|
return;
|
|
|
|
|
|
+ set_extra_move_desc(desc, *mask);
|
|
|
+
|
|
|
cpumask_and(&tmp, &cfg->domain, mask);
|
|
|
dest = cpu_mask_to_apicid(tmp);
|
|
|
/*
|
|
@@ -384,12 +424,21 @@ static void set_ioapic_affinity_irq(unsigned int irq,
|
|
|
*/
|
|
|
dest = SET_APIC_LOGICAL_ID(dest);
|
|
|
|
|
|
- desc = irq_to_desc(irq);
|
|
|
spin_lock_irqsave(&ioapic_lock, flags);
|
|
|
- __target_IO_APIC_irq(irq, dest, cfg->vector);
|
|
|
+ __target_IO_APIC_irq(irq, dest, cfg);
|
|
|
cpumask_copy(&desc->affinity, mask);
|
|
|
spin_unlock_irqrestore(&ioapic_lock, flags);
|
|
|
}
|
|
|
+
|
|
|
+static void set_ioapic_affinity_irq(unsigned int irq,
|
|
|
+ const struct cpumask *mask)
|
|
|
+{
|
|
|
+ struct irq_desc *desc;
|
|
|
+
|
|
|
+ desc = irq_to_desc(irq);
|
|
|
+
|
|
|
+ set_ioapic_affinity_irq_desc(desc, mask);
|
|
|
+}
|
|
|
#endif /* CONFIG_SMP */
|
|
|
|
|
|
/*
|
|
@@ -397,16 +446,18 @@ static void set_ioapic_affinity_irq(unsigned int irq,
|
|
|
* shared ISA-space IRQs, so we have to support them. We are super
|
|
|
* fast in the common case, and fast for shared ISA-space IRQs.
|
|
|
*/
|
|
|
-static void add_pin_to_irq(unsigned int irq, int apic, int pin)
|
|
|
+static void add_pin_to_irq_cpu(struct irq_cfg *cfg, int cpu, int apic, int pin)
|
|
|
{
|
|
|
- struct irq_cfg *cfg;
|
|
|
struct irq_pin_list *entry;
|
|
|
|
|
|
- /* first time to refer irq_cfg, so with new */
|
|
|
- cfg = irq_cfg_alloc(irq);
|
|
|
entry = cfg->irq_2_pin;
|
|
|
if (!entry) {
|
|
|
- entry = get_one_free_irq_2_pin();
|
|
|
+ entry = get_one_free_irq_2_pin(cpu);
|
|
|
+ if (!entry) {
|
|
|
+ printk(KERN_ERR "can not alloc irq_2_pin to add %d - %d\n",
|
|
|
+ apic, pin);
|
|
|
+ return;
|
|
|
+ }
|
|
|
cfg->irq_2_pin = entry;
|
|
|
entry->apic = apic;
|
|
|
entry->pin = pin;
|
|
@@ -421,7 +472,7 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin)
|
|
|
entry = entry->next;
|
|
|
}
|
|
|
|
|
|
- entry->next = get_one_free_irq_2_pin();
|
|
|
+ entry->next = get_one_free_irq_2_pin(cpu);
|
|
|
entry = entry->next;
|
|
|
entry->apic = apic;
|
|
|
entry->pin = pin;
|
|
@@ -430,11 +481,10 @@ static void add_pin_to_irq(unsigned int irq, int apic, int pin)
|
|
|
/*
|
|
|
* Reroute an IRQ to a different pin.
|
|
|
*/
|
|
|
-static void __init replace_pin_at_irq(unsigned int irq,
|
|
|
+static void __init replace_pin_at_irq_cpu(struct irq_cfg *cfg, int cpu,
|
|
|
int oldapic, int oldpin,
|
|
|
int newapic, int newpin)
|
|
|
{
|
|
|
- struct irq_cfg *cfg = irq_cfg(irq);
|
|
|
struct irq_pin_list *entry = cfg->irq_2_pin;
|
|
|
int replaced = 0;
|
|
|
|
|
@@ -451,18 +501,16 @@ static void __init replace_pin_at_irq(unsigned int irq,
|
|
|
|
|
|
/* why? call replace before add? */
|
|
|
if (!replaced)
|
|
|
- add_pin_to_irq(irq, newapic, newpin);
|
|
|
+ add_pin_to_irq_cpu(cfg, cpu, newapic, newpin);
|
|
|
}
|
|
|
|
|
|
-static inline void io_apic_modify_irq(unsigned int irq,
|
|
|
+static inline void io_apic_modify_irq(struct irq_cfg *cfg,
|
|
|
int mask_and, int mask_or,
|
|
|
void (*final)(struct irq_pin_list *entry))
|
|
|
{
|
|
|
int pin;
|
|
|
- struct irq_cfg *cfg;
|
|
|
struct irq_pin_list *entry;
|
|
|
|
|
|
- cfg = irq_cfg(irq);
|
|
|
for (entry = cfg->irq_2_pin; entry != NULL; entry = entry->next) {
|
|
|
unsigned int reg;
|
|
|
pin = entry->pin;
|
|
@@ -475,9 +523,9 @@ static inline void io_apic_modify_irq(unsigned int irq,
|
|
|
}
|
|
|
}
|
|
|
|
|
|
-static void __unmask_IO_APIC_irq(unsigned int irq)
|
|
|
+static void __unmask_IO_APIC_irq(struct irq_cfg *cfg)
|
|
|
{
|
|
|
- io_apic_modify_irq(irq, ~IO_APIC_REDIR_MASKED, 0, NULL);
|
|
|
+ io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED, 0, NULL);
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_X86_64
|
|
@@ -492,47 +540,64 @@ void io_apic_sync(struct irq_pin_list *entry)
|
|
|
readl(&io_apic->data);
|
|
|
}
|
|
|
|
|
|
-static void __mask_IO_APIC_irq(unsigned int irq)
|
|
|
+static void __mask_IO_APIC_irq(struct irq_cfg *cfg)
|
|
|
{
|
|
|
- io_apic_modify_irq(irq, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync);
|
|
|
+ io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, &io_apic_sync);
|
|
|
}
|
|
|
#else /* CONFIG_X86_32 */
|
|
|
-static void __mask_IO_APIC_irq(unsigned int irq)
|
|
|
+static void __mask_IO_APIC_irq(struct irq_cfg *cfg)
|
|
|
{
|
|
|
- io_apic_modify_irq(irq, ~0, IO_APIC_REDIR_MASKED, NULL);
|
|
|
+ io_apic_modify_irq(cfg, ~0, IO_APIC_REDIR_MASKED, NULL);
|
|
|
}
|
|
|
|
|
|
-static void __mask_and_edge_IO_APIC_irq(unsigned int irq)
|
|
|
+static void __mask_and_edge_IO_APIC_irq(struct irq_cfg *cfg)
|
|
|
{
|
|
|
- io_apic_modify_irq(irq, ~IO_APIC_REDIR_LEVEL_TRIGGER,
|
|
|
+ io_apic_modify_irq(cfg, ~IO_APIC_REDIR_LEVEL_TRIGGER,
|
|
|
IO_APIC_REDIR_MASKED, NULL);
|
|
|
}
|
|
|
|
|
|
-static void __unmask_and_level_IO_APIC_irq(unsigned int irq)
|
|
|
+static void __unmask_and_level_IO_APIC_irq(struct irq_cfg *cfg)
|
|
|
{
|
|
|
- io_apic_modify_irq(irq, ~IO_APIC_REDIR_MASKED,
|
|
|
+ io_apic_modify_irq(cfg, ~IO_APIC_REDIR_MASKED,
|
|
|
IO_APIC_REDIR_LEVEL_TRIGGER, NULL);
|
|
|
}
|
|
|
#endif /* CONFIG_X86_32 */
|
|
|
|
|
|
-static void mask_IO_APIC_irq (unsigned int irq)
|
|
|
+static void mask_IO_APIC_irq_desc(struct irq_desc *desc)
|
|
|
{
|
|
|
+ struct irq_cfg *cfg = desc->chip_data;
|
|
|
unsigned long flags;
|
|
|
|
|
|
+ BUG_ON(!cfg);
|
|
|
+
|
|
|
spin_lock_irqsave(&ioapic_lock, flags);
|
|
|
- __mask_IO_APIC_irq(irq);
|
|
|
+ __mask_IO_APIC_irq(cfg);
|
|
|
spin_unlock_irqrestore(&ioapic_lock, flags);
|
|
|
}
|
|
|
|
|
|
-static void unmask_IO_APIC_irq (unsigned int irq)
|
|
|
+static void unmask_IO_APIC_irq_desc(struct irq_desc *desc)
|
|
|
{
|
|
|
+ struct irq_cfg *cfg = desc->chip_data;
|
|
|
unsigned long flags;
|
|
|
|
|
|
spin_lock_irqsave(&ioapic_lock, flags);
|
|
|
- __unmask_IO_APIC_irq(irq);
|
|
|
+ __unmask_IO_APIC_irq(cfg);
|
|
|
spin_unlock_irqrestore(&ioapic_lock, flags);
|
|
|
}
|
|
|
|
|
|
+static void mask_IO_APIC_irq(unsigned int irq)
|
|
|
+{
|
|
|
+ struct irq_desc *desc = irq_to_desc(irq);
|
|
|
+
|
|
|
+ mask_IO_APIC_irq_desc(desc);
|
|
|
+}
|
|
|
+static void unmask_IO_APIC_irq(unsigned int irq)
|
|
|
+{
|
|
|
+ struct irq_desc *desc = irq_to_desc(irq);
|
|
|
+
|
|
|
+ unmask_IO_APIC_irq_desc(desc);
|
|
|
+}
|
|
|
+
|
|
|
static void clear_IO_APIC_pin(unsigned int apic, unsigned int pin)
|
|
|
{
|
|
|
struct IO_APIC_route_entry entry;
|
|
@@ -809,7 +874,7 @@ EXPORT_SYMBOL(IO_APIC_get_PCI_irq_vector);
|
|
|
*/
|
|
|
static int EISA_ELCR(unsigned int irq)
|
|
|
{
|
|
|
- if (irq < 16) {
|
|
|
+ if (irq < NR_IRQS_LEGACY) {
|
|
|
unsigned int port = 0x4d0 + (irq >> 3);
|
|
|
return (inb(port) >> (irq & 7)) & 1;
|
|
|
}
|
|
@@ -1034,7 +1099,7 @@ void unlock_vector_lock(void)
|
|
|
spin_unlock(&vector_lock);
|
|
|
}
|
|
|
|
|
|
-static int __assign_irq_vector(int irq, cpumask_t mask)
|
|
|
+static int __assign_irq_vector(int irq, struct irq_cfg *cfg, cpumask_t mask)
|
|
|
{
|
|
|
/*
|
|
|
* NOTE! The local APIC isn't very good at handling
|
|
@@ -1050,16 +1115,13 @@ static int __assign_irq_vector(int irq, cpumask_t mask)
|
|
|
static int current_vector = FIRST_DEVICE_VECTOR, current_offset = 0;
|
|
|
unsigned int old_vector;
|
|
|
int cpu;
|
|
|
- struct irq_cfg *cfg;
|
|
|
|
|
|
- cfg = irq_cfg(irq);
|
|
|
+ if ((cfg->move_in_progress) || cfg->move_cleanup_count)
|
|
|
+ return -EBUSY;
|
|
|
|
|
|
/* Only try and allocate irqs on cpus that are present */
|
|
|
cpus_and(mask, mask, cpu_online_map);
|
|
|
|
|
|
- if ((cfg->move_in_progress) || cfg->move_cleanup_count)
|
|
|
- return -EBUSY;
|
|
|
-
|
|
|
old_vector = cfg->vector;
|
|
|
if (old_vector) {
|
|
|
cpumask_t tmp;
|
|
@@ -1113,24 +1175,22 @@ next:
|
|
|
return -ENOSPC;
|
|
|
}
|
|
|
|
|
|
-static int assign_irq_vector(int irq, cpumask_t mask)
|
|
|
+static int assign_irq_vector(int irq, struct irq_cfg *cfg, cpumask_t mask)
|
|
|
{
|
|
|
int err;
|
|
|
unsigned long flags;
|
|
|
|
|
|
spin_lock_irqsave(&vector_lock, flags);
|
|
|
- err = __assign_irq_vector(irq, mask);
|
|
|
+ err = __assign_irq_vector(irq, cfg, mask);
|
|
|
spin_unlock_irqrestore(&vector_lock, flags);
|
|
|
return err;
|
|
|
}
|
|
|
|
|
|
-static void __clear_irq_vector(int irq)
|
|
|
+static void __clear_irq_vector(int irq, struct irq_cfg *cfg)
|
|
|
{
|
|
|
- struct irq_cfg *cfg;
|
|
|
cpumask_t mask;
|
|
|
int cpu, vector;
|
|
|
|
|
|
- cfg = irq_cfg(irq);
|
|
|
BUG_ON(!cfg->vector);
|
|
|
|
|
|
vector = cfg->vector;
|
|
@@ -1162,9 +1222,13 @@ void __setup_vector_irq(int cpu)
|
|
|
/* This function must be called with vector_lock held */
|
|
|
int irq, vector;
|
|
|
struct irq_cfg *cfg;
|
|
|
+ struct irq_desc *desc;
|
|
|
|
|
|
/* Mark the inuse vectors */
|
|
|
- for_each_irq_cfg(irq, cfg) {
|
|
|
+ for_each_irq_desc(irq, desc) {
|
|
|
+ if (!desc)
|
|
|
+ continue;
|
|
|
+ cfg = desc->chip_data;
|
|
|
if (!cpu_isset(cpu, cfg->domain))
|
|
|
continue;
|
|
|
vector = cfg->vector;
|
|
@@ -1215,11 +1279,8 @@ static inline int IO_APIC_irq_trigger(int irq)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-static void ioapic_register_intr(int irq, unsigned long trigger)
|
|
|
+static void ioapic_register_intr(int irq, struct irq_desc *desc, unsigned long trigger)
|
|
|
{
|
|
|
- struct irq_desc *desc;
|
|
|
-
|
|
|
- desc = irq_to_desc(irq);
|
|
|
|
|
|
if ((trigger == IOAPIC_AUTO && IO_APIC_irq_trigger(irq)) ||
|
|
|
trigger == IOAPIC_LEVEL)
|
|
@@ -1311,7 +1372,7 @@ static int setup_ioapic_entry(int apic, int irq,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
|
|
|
+static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq, struct irq_desc *desc,
|
|
|
int trigger, int polarity)
|
|
|
{
|
|
|
struct irq_cfg *cfg;
|
|
@@ -1321,10 +1382,10 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
|
|
|
if (!IO_APIC_IRQ(irq))
|
|
|
return;
|
|
|
|
|
|
- cfg = irq_cfg(irq);
|
|
|
+ cfg = desc->chip_data;
|
|
|
|
|
|
mask = TARGET_CPUS;
|
|
|
- if (assign_irq_vector(irq, mask))
|
|
|
+ if (assign_irq_vector(irq, cfg, mask))
|
|
|
return;
|
|
|
|
|
|
cpus_and(mask, cfg->domain, mask);
|
|
@@ -1341,12 +1402,12 @@ static void setup_IO_APIC_irq(int apic, int pin, unsigned int irq,
|
|
|
cfg->vector)) {
|
|
|
printk("Failed to setup ioapic entry for ioapic %d, pin %d\n",
|
|
|
mp_ioapics[apic].mp_apicid, pin);
|
|
|
- __clear_irq_vector(irq);
|
|
|
+ __clear_irq_vector(irq, cfg);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- ioapic_register_intr(irq, trigger);
|
|
|
- if (irq < 16)
|
|
|
+ ioapic_register_intr(irq, desc, trigger);
|
|
|
+ if (irq < NR_IRQS_LEGACY)
|
|
|
disable_8259A_irq(irq);
|
|
|
|
|
|
ioapic_write_entry(apic, pin, entry);
|
|
@@ -1356,6 +1417,9 @@ static void __init setup_IO_APIC_irqs(void)
|
|
|
{
|
|
|
int apic, pin, idx, irq;
|
|
|
int notcon = 0;
|
|
|
+ struct irq_desc *desc;
|
|
|
+ struct irq_cfg *cfg;
|
|
|
+ int cpu = boot_cpu_id;
|
|
|
|
|
|
apic_printk(APIC_VERBOSE, KERN_DEBUG "init IO_APIC IRQs\n");
|
|
|
|
|
@@ -1387,9 +1451,15 @@ static void __init setup_IO_APIC_irqs(void)
|
|
|
if (multi_timer_check(apic, irq))
|
|
|
continue;
|
|
|
#endif
|
|
|
- add_pin_to_irq(irq, apic, pin);
|
|
|
+ desc = irq_to_desc_alloc_cpu(irq, cpu);
|
|
|
+ if (!desc) {
|
|
|
+ printk(KERN_INFO "can not get irq_desc for %d\n", irq);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ cfg = desc->chip_data;
|
|
|
+ add_pin_to_irq_cpu(cfg, cpu, apic, pin);
|
|
|
|
|
|
- setup_IO_APIC_irq(apic, pin, irq,
|
|
|
+ setup_IO_APIC_irq(apic, pin, irq, desc,
|
|
|
irq_trigger(idx), irq_polarity(idx));
|
|
|
}
|
|
|
}
|
|
@@ -1448,6 +1518,7 @@ __apicdebuginit(void) print_IO_APIC(void)
|
|
|
union IO_APIC_reg_03 reg_03;
|
|
|
unsigned long flags;
|
|
|
struct irq_cfg *cfg;
|
|
|
+ struct irq_desc *desc;
|
|
|
unsigned int irq;
|
|
|
|
|
|
if (apic_verbosity == APIC_QUIET)
|
|
@@ -1537,8 +1608,13 @@ __apicdebuginit(void) print_IO_APIC(void)
|
|
|
}
|
|
|
}
|
|
|
printk(KERN_DEBUG "IRQ to pin mappings:\n");
|
|
|
- for_each_irq_cfg(irq, cfg) {
|
|
|
- struct irq_pin_list *entry = cfg->irq_2_pin;
|
|
|
+ for_each_irq_desc(irq, desc) {
|
|
|
+ struct irq_pin_list *entry;
|
|
|
+
|
|
|
+ if (!desc)
|
|
|
+ continue;
|
|
|
+ cfg = desc->chip_data;
|
|
|
+ entry = cfg->irq_2_pin;
|
|
|
if (!entry)
|
|
|
continue;
|
|
|
printk(KERN_DEBUG "IRQ%d ", irq);
|
|
@@ -2022,14 +2098,16 @@ static unsigned int startup_ioapic_irq(unsigned int irq)
|
|
|
{
|
|
|
int was_pending = 0;
|
|
|
unsigned long flags;
|
|
|
+ struct irq_cfg *cfg;
|
|
|
|
|
|
spin_lock_irqsave(&ioapic_lock, flags);
|
|
|
- if (irq < 16) {
|
|
|
+ if (irq < NR_IRQS_LEGACY) {
|
|
|
disable_8259A_irq(irq);
|
|
|
if (i8259A_irq_pending(irq))
|
|
|
was_pending = 1;
|
|
|
}
|
|
|
- __unmask_IO_APIC_irq(irq);
|
|
|
+ cfg = irq_cfg(irq);
|
|
|
+ __unmask_IO_APIC_irq(cfg);
|
|
|
spin_unlock_irqrestore(&ioapic_lock, flags);
|
|
|
|
|
|
return was_pending;
|
|
@@ -2092,35 +2170,37 @@ static DECLARE_DELAYED_WORK(ir_migration_work, ir_irq_migration);
|
|
|
* as simple as edge triggered migration and we can do the irq migration
|
|
|
* with a simple atomic update to IO-APIC RTE.
|
|
|
*/
|
|
|
-static void migrate_ioapic_irq(int irq, cpumask_t mask)
|
|
|
+static void migrate_ioapic_irq_desc(struct irq_desc *desc, cpumask_t mask)
|
|
|
{
|
|
|
struct irq_cfg *cfg;
|
|
|
- struct irq_desc *desc;
|
|
|
cpumask_t tmp, cleanup_mask;
|
|
|
struct irte irte;
|
|
|
int modify_ioapic_rte;
|
|
|
unsigned int dest;
|
|
|
unsigned long flags;
|
|
|
+ unsigned int irq;
|
|
|
|
|
|
cpus_and(tmp, mask, cpu_online_map);
|
|
|
if (cpus_empty(tmp))
|
|
|
return;
|
|
|
|
|
|
+ irq = desc->irq;
|
|
|
if (get_irte(irq, &irte))
|
|
|
return;
|
|
|
|
|
|
- if (assign_irq_vector(irq, mask))
|
|
|
+ cfg = desc->chip_data;
|
|
|
+ if (assign_irq_vector(irq, cfg, mask))
|
|
|
return;
|
|
|
|
|
|
- cfg = irq_cfg(irq);
|
|
|
+ set_extra_move_desc(desc, mask);
|
|
|
+
|
|
|
cpus_and(tmp, cfg->domain, mask);
|
|
|
dest = cpu_mask_to_apicid(tmp);
|
|
|
|
|
|
- desc = irq_to_desc(irq);
|
|
|
modify_ioapic_rte = desc->status & IRQ_LEVEL;
|
|
|
if (modify_ioapic_rte) {
|
|
|
spin_lock_irqsave(&ioapic_lock, flags);
|
|
|
- __target_IO_APIC_irq(irq, dest, cfg->vector);
|
|
|
+ __target_IO_APIC_irq(irq, dest, cfg);
|
|
|
spin_unlock_irqrestore(&ioapic_lock, flags);
|
|
|
}
|
|
|
|
|
@@ -2142,14 +2222,14 @@ static void migrate_ioapic_irq(int irq, cpumask_t mask)
|
|
|
desc->affinity = mask;
|
|
|
}
|
|
|
|
|
|
-static int migrate_irq_remapped_level(int irq)
|
|
|
+static int migrate_irq_remapped_level_desc(struct irq_desc *desc)
|
|
|
{
|
|
|
int ret = -1;
|
|
|
- struct irq_desc *desc = irq_to_desc(irq);
|
|
|
+ struct irq_cfg *cfg = desc->chip_data;
|
|
|
|
|
|
- mask_IO_APIC_irq(irq);
|
|
|
+ mask_IO_APIC_irq_desc(desc);
|
|
|
|
|
|
- if (io_apic_level_ack_pending(irq)) {
|
|
|
+ if (io_apic_level_ack_pending(cfg)) {
|
|
|
/*
|
|
|
* Interrupt in progress. Migrating irq now will change the
|
|
|
* vector information in the IO-APIC RTE and that will confuse
|
|
@@ -2161,14 +2241,15 @@ static int migrate_irq_remapped_level(int irq)
|
|
|
}
|
|
|
|
|
|
/* everthing is clear. we have right of way */
|
|
|
- migrate_ioapic_irq(irq, desc->pending_mask);
|
|
|
+ migrate_ioapic_irq_desc(desc, desc->pending_mask);
|
|
|
|
|
|
ret = 0;
|
|
|
desc->status &= ~IRQ_MOVE_PENDING;
|
|
|
cpus_clear(desc->pending_mask);
|
|
|
|
|
|
unmask:
|
|
|
- unmask_IO_APIC_irq(irq);
|
|
|
+ unmask_IO_APIC_irq_desc(desc);
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -2178,6 +2259,9 @@ static void ir_irq_migration(struct work_struct *work)
|
|
|
struct irq_desc *desc;
|
|
|
|
|
|
for_each_irq_desc(irq, desc) {
|
|
|
+ if (!desc)
|
|
|
+ continue;
|
|
|
+
|
|
|
if (desc->status & IRQ_MOVE_PENDING) {
|
|
|
unsigned long flags;
|
|
|
|
|
@@ -2198,19 +2282,24 @@ static void ir_irq_migration(struct work_struct *work)
|
|
|
/*
|
|
|
* Migrates the IRQ destination in the process context.
|
|
|
*/
|
|
|
-static void set_ir_ioapic_affinity_irq(unsigned int irq,
|
|
|
- const struct cpumask *mask)
|
|
|
+static void set_ir_ioapic_affinity_irq_desc(struct irq_desc *desc,
|
|
|
+ const struct cpumask *mask)
|
|
|
{
|
|
|
- struct irq_desc *desc = irq_to_desc(irq);
|
|
|
-
|
|
|
if (desc->status & IRQ_LEVEL) {
|
|
|
desc->status |= IRQ_MOVE_PENDING;
|
|
|
cpumask_copy(&desc->pending_mask, mask);
|
|
|
- migrate_irq_remapped_level(irq);
|
|
|
+ migrate_irq_remapped_level_desc(desc);
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- migrate_ioapic_irq(irq, *mask);
|
|
|
+ migrate_ioapic_irq_desc(desc, mask);
|
|
|
+}
|
|
|
+static void set_ir_ioapic_affinity_irq(unsigned int irq,
|
|
|
+ const struct cpumask *mask)
|
|
|
+{
|
|
|
+ struct irq_desc *desc = irq_to_desc(irq);
|
|
|
+
|
|
|
+ set_ir_ioapic_affinity_irq_desc(desc, mask);
|
|
|
}
|
|
|
#endif
|
|
|
|
|
@@ -2230,6 +2319,9 @@ asmlinkage void smp_irq_move_cleanup_interrupt(void)
|
|
|
struct irq_cfg *cfg;
|
|
|
irq = __get_cpu_var(vector_irq)[vector];
|
|
|
|
|
|
+ if (irq == -1)
|
|
|
+ continue;
|
|
|
+
|
|
|
desc = irq_to_desc(irq);
|
|
|
if (!desc)
|
|
|
continue;
|
|
@@ -2251,9 +2343,10 @@ unlock:
|
|
|
irq_exit();
|
|
|
}
|
|
|
|
|
|
-static void irq_complete_move(unsigned int irq)
|
|
|
+static void irq_complete_move(struct irq_desc **descp)
|
|
|
{
|
|
|
- struct irq_cfg *cfg = irq_cfg(irq);
|
|
|
+ struct irq_desc *desc = *descp;
|
|
|
+ struct irq_cfg *cfg = desc->chip_data;
|
|
|
unsigned vector, me;
|
|
|
|
|
|
if (likely(!cfg->move_in_progress))
|
|
@@ -2271,8 +2364,9 @@ static void irq_complete_move(unsigned int irq)
|
|
|
}
|
|
|
}
|
|
|
#else
|
|
|
-static inline void irq_complete_move(unsigned int irq) {}
|
|
|
+static inline void irq_complete_move(struct irq_desc **descp) {}
|
|
|
#endif
|
|
|
+
|
|
|
#ifdef CONFIG_INTR_REMAP
|
|
|
static void ack_x2apic_level(unsigned int irq)
|
|
|
{
|
|
@@ -2283,11 +2377,14 @@ static void ack_x2apic_edge(unsigned int irq)
|
|
|
{
|
|
|
ack_x2APIC_irq();
|
|
|
}
|
|
|
+
|
|
|
#endif
|
|
|
|
|
|
static void ack_apic_edge(unsigned int irq)
|
|
|
{
|
|
|
- irq_complete_move(irq);
|
|
|
+ struct irq_desc *desc = irq_to_desc(irq);
|
|
|
+
|
|
|
+ irq_complete_move(&desc);
|
|
|
move_native_irq(irq);
|
|
|
ack_APIC_irq();
|
|
|
}
|
|
@@ -2296,18 +2393,21 @@ atomic_t irq_mis_count;
|
|
|
|
|
|
static void ack_apic_level(unsigned int irq)
|
|
|
{
|
|
|
+ struct irq_desc *desc = irq_to_desc(irq);
|
|
|
+
|
|
|
#ifdef CONFIG_X86_32
|
|
|
unsigned long v;
|
|
|
int i;
|
|
|
#endif
|
|
|
+ struct irq_cfg *cfg;
|
|
|
int do_unmask_irq = 0;
|
|
|
|
|
|
- irq_complete_move(irq);
|
|
|
+ irq_complete_move(&desc);
|
|
|
#ifdef CONFIG_GENERIC_PENDING_IRQ
|
|
|
/* If we are moving the irq we need to mask it */
|
|
|
- if (unlikely(irq_to_desc(irq)->status & IRQ_MOVE_PENDING)) {
|
|
|
+ if (unlikely(desc->status & IRQ_MOVE_PENDING)) {
|
|
|
do_unmask_irq = 1;
|
|
|
- mask_IO_APIC_irq(irq);
|
|
|
+ mask_IO_APIC_irq_desc(desc);
|
|
|
}
|
|
|
#endif
|
|
|
|
|
@@ -2331,7 +2431,8 @@ static void ack_apic_level(unsigned int irq)
|
|
|
* operation to prevent an edge-triggered interrupt escaping meanwhile.
|
|
|
* The idea is from Manfred Spraul. --macro
|
|
|
*/
|
|
|
- i = irq_cfg(irq)->vector;
|
|
|
+ cfg = desc->chip_data;
|
|
|
+ i = cfg->vector;
|
|
|
|
|
|
v = apic_read(APIC_TMR + ((i & ~0x1f) >> 1));
|
|
|
#endif
|
|
@@ -2370,17 +2471,18 @@ static void ack_apic_level(unsigned int irq)
|
|
|
* accurate and is causing problems then it is a hardware bug
|
|
|
* and you can go talk to the chipset vendor about it.
|
|
|
*/
|
|
|
- if (!io_apic_level_ack_pending(irq))
|
|
|
+ cfg = desc->chip_data;
|
|
|
+ if (!io_apic_level_ack_pending(cfg))
|
|
|
move_masked_irq(irq);
|
|
|
- unmask_IO_APIC_irq(irq);
|
|
|
+ unmask_IO_APIC_irq_desc(desc);
|
|
|
}
|
|
|
|
|
|
#ifdef CONFIG_X86_32
|
|
|
if (!(v & (1 << (i & 0x1f)))) {
|
|
|
atomic_inc(&irq_mis_count);
|
|
|
spin_lock(&ioapic_lock);
|
|
|
- __mask_and_edge_IO_APIC_irq(irq);
|
|
|
- __unmask_and_level_IO_APIC_irq(irq);
|
|
|
+ __mask_and_edge_IO_APIC_irq(cfg);
|
|
|
+ __unmask_and_level_IO_APIC_irq(cfg);
|
|
|
spin_unlock(&ioapic_lock);
|
|
|
}
|
|
|
#endif
|
|
@@ -2431,20 +2533,22 @@ static inline void init_IO_APIC_traps(void)
|
|
|
* Also, we've got to be careful not to trash gate
|
|
|
* 0x80, because int 0x80 is hm, kind of importantish. ;)
|
|
|
*/
|
|
|
- for_each_irq_cfg(irq, cfg) {
|
|
|
- if (IO_APIC_IRQ(irq) && !cfg->vector) {
|
|
|
+ for_each_irq_desc(irq, desc) {
|
|
|
+ if (!desc)
|
|
|
+ continue;
|
|
|
+
|
|
|
+ cfg = desc->chip_data;
|
|
|
+ if (IO_APIC_IRQ(irq) && cfg && !cfg->vector) {
|
|
|
/*
|
|
|
* Hmm.. We don't have an entry for this,
|
|
|
* so default to an old-fashioned 8259
|
|
|
* interrupt if we can..
|
|
|
*/
|
|
|
- if (irq < 16)
|
|
|
+ if (irq < NR_IRQS_LEGACY)
|
|
|
make_8259A_irq(irq);
|
|
|
- else {
|
|
|
- desc = irq_to_desc(irq);
|
|
|
+ else
|
|
|
/* Strange. Oh, well.. */
|
|
|
desc->chip = &no_irq_chip;
|
|
|
- }
|
|
|
}
|
|
|
}
|
|
|
}
|
|
@@ -2469,7 +2573,7 @@ static void unmask_lapic_irq(unsigned int irq)
|
|
|
apic_write(APIC_LVT0, v & ~APIC_LVT_MASKED);
|
|
|
}
|
|
|
|
|
|
-static void ack_lapic_irq (unsigned int irq)
|
|
|
+static void ack_lapic_irq(unsigned int irq)
|
|
|
{
|
|
|
ack_APIC_irq();
|
|
|
}
|
|
@@ -2481,11 +2585,8 @@ static struct irq_chip lapic_chip __read_mostly = {
|
|
|
.ack = ack_lapic_irq,
|
|
|
};
|
|
|
|
|
|
-static void lapic_register_intr(int irq)
|
|
|
+static void lapic_register_intr(int irq, struct irq_desc *desc)
|
|
|
{
|
|
|
- struct irq_desc *desc;
|
|
|
-
|
|
|
- desc = irq_to_desc(irq);
|
|
|
desc->status &= ~IRQ_LEVEL;
|
|
|
set_irq_chip_and_handler_name(irq, &lapic_chip, handle_edge_irq,
|
|
|
"edge");
|
|
@@ -2589,7 +2690,9 @@ int timer_through_8259 __initdata;
|
|
|
*/
|
|
|
static inline void __init check_timer(void)
|
|
|
{
|
|
|
- struct irq_cfg *cfg = irq_cfg(0);
|
|
|
+ struct irq_desc *desc = irq_to_desc(0);
|
|
|
+ struct irq_cfg *cfg = desc->chip_data;
|
|
|
+ int cpu = boot_cpu_id;
|
|
|
int apic1, pin1, apic2, pin2;
|
|
|
unsigned long flags;
|
|
|
unsigned int ver;
|
|
@@ -2604,7 +2707,7 @@ static inline void __init check_timer(void)
|
|
|
* get/set the timer IRQ vector:
|
|
|
*/
|
|
|
disable_8259A_irq(0);
|
|
|
- assign_irq_vector(0, TARGET_CPUS);
|
|
|
+ assign_irq_vector(0, cfg, TARGET_CPUS);
|
|
|
|
|
|
/*
|
|
|
* As IRQ0 is to be enabled in the 8259A, the virtual
|
|
@@ -2655,10 +2758,10 @@ static inline void __init check_timer(void)
|
|
|
* Ok, does IRQ0 through the IOAPIC work?
|
|
|
*/
|
|
|
if (no_pin1) {
|
|
|
- add_pin_to_irq(0, apic1, pin1);
|
|
|
+ add_pin_to_irq_cpu(cfg, cpu, apic1, pin1);
|
|
|
setup_timer_IRQ0_pin(apic1, pin1, cfg->vector);
|
|
|
}
|
|
|
- unmask_IO_APIC_irq(0);
|
|
|
+ unmask_IO_APIC_irq_desc(desc);
|
|
|
if (timer_irq_works()) {
|
|
|
if (nmi_watchdog == NMI_IO_APIC) {
|
|
|
setup_nmi();
|
|
@@ -2684,9 +2787,9 @@ static inline void __init check_timer(void)
|
|
|
/*
|
|
|
* legacy devices should be connected to IO APIC #0
|
|
|
*/
|
|
|
- replace_pin_at_irq(0, apic1, pin1, apic2, pin2);
|
|
|
+ replace_pin_at_irq_cpu(cfg, cpu, apic1, pin1, apic2, pin2);
|
|
|
setup_timer_IRQ0_pin(apic2, pin2, cfg->vector);
|
|
|
- unmask_IO_APIC_irq(0);
|
|
|
+ unmask_IO_APIC_irq_desc(desc);
|
|
|
enable_8259A_irq(0);
|
|
|
if (timer_irq_works()) {
|
|
|
apic_printk(APIC_QUIET, KERN_INFO "....... works.\n");
|
|
@@ -2718,7 +2821,7 @@ static inline void __init check_timer(void)
|
|
|
apic_printk(APIC_QUIET, KERN_INFO
|
|
|
"...trying to set up timer as Virtual Wire IRQ...\n");
|
|
|
|
|
|
- lapic_register_intr(0);
|
|
|
+ lapic_register_intr(0, desc);
|
|
|
apic_write(APIC_LVT0, APIC_DM_FIXED | cfg->vector); /* Fixed mode */
|
|
|
enable_8259A_irq(0);
|
|
|
|
|
@@ -2903,22 +3006,26 @@ unsigned int create_irq_nr(unsigned int irq_want)
|
|
|
unsigned int irq;
|
|
|
unsigned int new;
|
|
|
unsigned long flags;
|
|
|
- struct irq_cfg *cfg_new;
|
|
|
-
|
|
|
- irq_want = nr_irqs - 1;
|
|
|
+ struct irq_cfg *cfg_new = NULL;
|
|
|
+ int cpu = boot_cpu_id;
|
|
|
+ struct irq_desc *desc_new = NULL;
|
|
|
|
|
|
irq = 0;
|
|
|
spin_lock_irqsave(&vector_lock, flags);
|
|
|
- for (new = irq_want; new > 0; new--) {
|
|
|
+ for (new = irq_want; new < NR_IRQS; new++) {
|
|
|
if (platform_legacy_irq(new))
|
|
|
continue;
|
|
|
- cfg_new = irq_cfg(new);
|
|
|
- if (cfg_new && cfg_new->vector != 0)
|
|
|
+
|
|
|
+ desc_new = irq_to_desc_alloc_cpu(new, cpu);
|
|
|
+ if (!desc_new) {
|
|
|
+ printk(KERN_INFO "can not get irq_desc for %d\n", new);
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ cfg_new = desc_new->chip_data;
|
|
|
+
|
|
|
+ if (cfg_new->vector != 0)
|
|
|
continue;
|
|
|
- /* check if need to create one */
|
|
|
- if (!cfg_new)
|
|
|
- cfg_new = irq_cfg_alloc(new);
|
|
|
- if (__assign_irq_vector(new, TARGET_CPUS) == 0)
|
|
|
+ if (__assign_irq_vector(new, cfg_new, TARGET_CPUS) == 0)
|
|
|
irq = new;
|
|
|
break;
|
|
|
}
|
|
@@ -2926,15 +3033,21 @@ unsigned int create_irq_nr(unsigned int irq_want)
|
|
|
|
|
|
if (irq > 0) {
|
|
|
dynamic_irq_init(irq);
|
|
|
+ /* restore it, in case dynamic_irq_init clear it */
|
|
|
+ if (desc_new)
|
|
|
+ desc_new->chip_data = cfg_new;
|
|
|
}
|
|
|
return irq;
|
|
|
}
|
|
|
|
|
|
+static int nr_irqs_gsi = NR_IRQS_LEGACY;
|
|
|
int create_irq(void)
|
|
|
{
|
|
|
+ unsigned int irq_want;
|
|
|
int irq;
|
|
|
|
|
|
- irq = create_irq_nr(nr_irqs - 1);
|
|
|
+ irq_want = nr_irqs_gsi;
|
|
|
+ irq = create_irq_nr(irq_want);
|
|
|
|
|
|
if (irq == 0)
|
|
|
irq = -1;
|
|
@@ -2945,14 +3058,22 @@ int create_irq(void)
|
|
|
void destroy_irq(unsigned int irq)
|
|
|
{
|
|
|
unsigned long flags;
|
|
|
+ struct irq_cfg *cfg;
|
|
|
+ struct irq_desc *desc;
|
|
|
|
|
|
+ /* store it, in case dynamic_irq_cleanup clear it */
|
|
|
+ desc = irq_to_desc(irq);
|
|
|
+ cfg = desc->chip_data;
|
|
|
dynamic_irq_cleanup(irq);
|
|
|
+ /* connect back irq_cfg */
|
|
|
+ if (desc)
|
|
|
+ desc->chip_data = cfg;
|
|
|
|
|
|
#ifdef CONFIG_INTR_REMAP
|
|
|
free_irte(irq);
|
|
|
#endif
|
|
|
spin_lock_irqsave(&vector_lock, flags);
|
|
|
- __clear_irq_vector(irq);
|
|
|
+ __clear_irq_vector(irq, cfg);
|
|
|
spin_unlock_irqrestore(&vector_lock, flags);
|
|
|
}
|
|
|
|
|
@@ -2967,12 +3088,12 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms
|
|
|
unsigned dest;
|
|
|
cpumask_t tmp;
|
|
|
|
|
|
+ cfg = irq_cfg(irq);
|
|
|
tmp = TARGET_CPUS;
|
|
|
- err = assign_irq_vector(irq, tmp);
|
|
|
+ err = assign_irq_vector(irq, cfg, tmp);
|
|
|
if (err)
|
|
|
return err;
|
|
|
|
|
|
- cfg = irq_cfg(irq);
|
|
|
cpus_and(tmp, cfg->domain, tmp);
|
|
|
dest = cpu_mask_to_apicid(tmp);
|
|
|
|
|
@@ -3030,34 +3151,34 @@ static int msi_compose_msg(struct pci_dev *pdev, unsigned int irq, struct msi_ms
|
|
|
#ifdef CONFIG_SMP
|
|
|
static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
|
|
|
{
|
|
|
+ struct irq_desc *desc = irq_to_desc(irq);
|
|
|
struct irq_cfg *cfg;
|
|
|
struct msi_msg msg;
|
|
|
unsigned int dest;
|
|
|
cpumask_t tmp;
|
|
|
- struct irq_desc *desc;
|
|
|
|
|
|
if (!cpumask_intersects(mask, cpu_online_mask))
|
|
|
return;
|
|
|
|
|
|
- if (assign_irq_vector(irq, *mask))
|
|
|
+ cfg = desc->chip_data;
|
|
|
+ if (assign_irq_vector(irq, cfg, *mask))
|
|
|
return;
|
|
|
|
|
|
- cfg = irq_cfg(irq);
|
|
|
+ set_extra_move_desc(desc, *mask);
|
|
|
+
|
|
|
cpumask_and(&tmp, &cfg->domain, mask);
|
|
|
dest = cpu_mask_to_apicid(tmp);
|
|
|
|
|
|
- read_msi_msg(irq, &msg);
|
|
|
+ read_msi_msg_desc(desc, &msg);
|
|
|
|
|
|
msg.data &= ~MSI_DATA_VECTOR_MASK;
|
|
|
msg.data |= MSI_DATA_VECTOR(cfg->vector);
|
|
|
msg.address_lo &= ~MSI_ADDR_DEST_ID_MASK;
|
|
|
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
|
|
|
|
|
|
- write_msi_msg(irq, &msg);
|
|
|
- desc = irq_to_desc(irq);
|
|
|
+ write_msi_msg_desc(desc, &msg);
|
|
|
cpumask_copy(&desc->affinity, mask);
|
|
|
}
|
|
|
-
|
|
|
#ifdef CONFIG_INTR_REMAP
|
|
|
/*
|
|
|
* Migrate the MSI irq to another cpumask. This migration is
|
|
@@ -3066,11 +3187,11 @@ static void set_msi_irq_affinity(unsigned int irq, const struct cpumask *mask)
|
|
|
static void ir_set_msi_irq_affinity(unsigned int irq,
|
|
|
const struct cpumask *mask)
|
|
|
{
|
|
|
+ struct irq_desc *desc = irq_to_desc(irq);
|
|
|
struct irq_cfg *cfg;
|
|
|
unsigned int dest;
|
|
|
cpumask_t tmp, cleanup_mask;
|
|
|
struct irte irte;
|
|
|
- struct irq_desc *desc;
|
|
|
|
|
|
if (!cpumask_intersects(mask, cpu_online_mask))
|
|
|
return;
|
|
@@ -3078,10 +3199,12 @@ static void ir_set_msi_irq_affinity(unsigned int irq,
|
|
|
if (get_irte(irq, &irte))
|
|
|
return;
|
|
|
|
|
|
- if (assign_irq_vector(irq, *mask))
|
|
|
+ cfg = desc->chip_data;
|
|
|
+ if (assign_irq_vector(irq, cfg, *mask))
|
|
|
return;
|
|
|
|
|
|
- cfg = irq_cfg(irq);
|
|
|
+ set_extra_move_desc(desc, mask);
|
|
|
+
|
|
|
cpumask_and(&tmp, &cfg->domain, mask);
|
|
|
dest = cpu_mask_to_apicid(tmp);
|
|
|
|
|
@@ -3105,9 +3228,9 @@ static void ir_set_msi_irq_affinity(unsigned int irq,
|
|
|
cfg->move_in_progress = 0;
|
|
|
}
|
|
|
|
|
|
- desc = irq_to_desc(irq);
|
|
|
cpumask_copy(&desc->affinity, mask);
|
|
|
}
|
|
|
+
|
|
|
#endif
|
|
|
#endif /* CONFIG_SMP */
|
|
|
|
|
@@ -3166,7 +3289,7 @@ static int msi_alloc_irte(struct pci_dev *dev, int irq, int nvec)
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq)
|
|
|
+static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc, int irq)
|
|
|
{
|
|
|
int ret;
|
|
|
struct msi_msg msg;
|
|
@@ -3175,7 +3298,7 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq)
|
|
|
if (ret < 0)
|
|
|
return ret;
|
|
|
|
|
|
- set_irq_msi(irq, desc);
|
|
|
+ set_irq_msi(irq, msidesc);
|
|
|
write_msi_msg(irq, &msg);
|
|
|
|
|
|
#ifdef CONFIG_INTR_REMAP
|
|
@@ -3195,26 +3318,13 @@ static int setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc, int irq)
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
-static unsigned int build_irq_for_pci_dev(struct pci_dev *dev)
|
|
|
-{
|
|
|
- unsigned int irq;
|
|
|
-
|
|
|
- irq = dev->bus->number;
|
|
|
- irq <<= 8;
|
|
|
- irq |= dev->devfn;
|
|
|
- irq <<= 12;
|
|
|
-
|
|
|
- return irq;
|
|
|
-}
|
|
|
-
|
|
|
-int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
|
|
|
+int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *msidesc)
|
|
|
{
|
|
|
unsigned int irq;
|
|
|
int ret;
|
|
|
unsigned int irq_want;
|
|
|
|
|
|
- irq_want = build_irq_for_pci_dev(dev) + 0x100;
|
|
|
-
|
|
|
+ irq_want = nr_irqs_gsi;
|
|
|
irq = create_irq_nr(irq_want);
|
|
|
if (irq == 0)
|
|
|
return -1;
|
|
@@ -3228,7 +3338,7 @@ int arch_setup_msi_irq(struct pci_dev *dev, struct msi_desc *desc)
|
|
|
goto error;
|
|
|
no_ir:
|
|
|
#endif
|
|
|
- ret = setup_msi_irq(dev, desc, irq);
|
|
|
+ ret = setup_msi_irq(dev, msidesc, irq);
|
|
|
if (ret < 0) {
|
|
|
destroy_irq(irq);
|
|
|
return ret;
|
|
@@ -3246,7 +3356,7 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
|
|
{
|
|
|
unsigned int irq;
|
|
|
int ret, sub_handle;
|
|
|
- struct msi_desc *desc;
|
|
|
+ struct msi_desc *msidesc;
|
|
|
unsigned int irq_want;
|
|
|
|
|
|
#ifdef CONFIG_INTR_REMAP
|
|
@@ -3254,10 +3364,11 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
|
|
int index = 0;
|
|
|
#endif
|
|
|
|
|
|
- irq_want = build_irq_for_pci_dev(dev) + 0x100;
|
|
|
+ irq_want = nr_irqs_gsi;
|
|
|
sub_handle = 0;
|
|
|
- list_for_each_entry(desc, &dev->msi_list, list) {
|
|
|
- irq = create_irq_nr(irq_want--);
|
|
|
+ list_for_each_entry(msidesc, &dev->msi_list, list) {
|
|
|
+ irq = create_irq_nr(irq_want);
|
|
|
+ irq_want++;
|
|
|
if (irq == 0)
|
|
|
return -1;
|
|
|
#ifdef CONFIG_INTR_REMAP
|
|
@@ -3289,7 +3400,7 @@ int arch_setup_msi_irqs(struct pci_dev *dev, int nvec, int type)
|
|
|
}
|
|
|
no_ir:
|
|
|
#endif
|
|
|
- ret = setup_msi_irq(dev, desc, irq);
|
|
|
+ ret = setup_msi_irq(dev, msidesc, irq);
|
|
|
if (ret < 0)
|
|
|
goto error;
|
|
|
sub_handle++;
|
|
@@ -3310,19 +3421,21 @@ void arch_teardown_msi_irq(unsigned int irq)
|
|
|
#ifdef CONFIG_SMP
|
|
|
static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
|
|
|
{
|
|
|
+ struct irq_desc *desc = irq_to_desc(irq);
|
|
|
struct irq_cfg *cfg;
|
|
|
struct msi_msg msg;
|
|
|
unsigned int dest;
|
|
|
cpumask_t tmp;
|
|
|
- struct irq_desc *desc;
|
|
|
|
|
|
if (!cpumask_intersects(mask, cpu_online_mask))
|
|
|
return;
|
|
|
|
|
|
- if (assign_irq_vector(irq, *mask))
|
|
|
+ cfg = desc->chip_data;
|
|
|
+ if (assign_irq_vector(irq, cfg, *mask))
|
|
|
return;
|
|
|
|
|
|
- cfg = irq_cfg(irq);
|
|
|
+ set_extra_move_desc(desc, *mask);
|
|
|
+
|
|
|
cpumask_and(&tmp, &cfg->domain, mask);
|
|
|
dest = cpu_mask_to_apicid(tmp);
|
|
|
|
|
@@ -3334,9 +3447,9 @@ static void dmar_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
|
|
|
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
|
|
|
|
|
|
dmar_msi_write(irq, &msg);
|
|
|
- desc = irq_to_desc(irq);
|
|
|
cpumask_copy(&desc->affinity, mask);
|
|
|
}
|
|
|
+
|
|
|
#endif /* CONFIG_SMP */
|
|
|
|
|
|
struct irq_chip dmar_msi_type = {
|
|
@@ -3370,8 +3483,8 @@ int arch_setup_dmar_msi(unsigned int irq)
|
|
|
#ifdef CONFIG_SMP
|
|
|
static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
|
|
|
{
|
|
|
+ struct irq_desc *desc = irq_to_desc(irq);
|
|
|
struct irq_cfg *cfg;
|
|
|
- struct irq_desc *desc;
|
|
|
struct msi_msg msg;
|
|
|
unsigned int dest;
|
|
|
cpumask_t tmp;
|
|
@@ -3379,10 +3492,12 @@ static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
|
|
|
if (!cpumask_intersects(mask, cpu_online_mask))
|
|
|
return;
|
|
|
|
|
|
- if (assign_irq_vector(irq, *mask))
|
|
|
+ cfg = desc->chip_data;
|
|
|
+ if (assign_irq_vector(irq, cfg, *mask))
|
|
|
return;
|
|
|
|
|
|
- cfg = irq_cfg(irq);
|
|
|
+ set_extra_move_desc(desc, *mask);
|
|
|
+
|
|
|
cpumask_and(&tmp, &cfg->domain, mask);
|
|
|
dest = cpu_mask_to_apicid(tmp);
|
|
|
|
|
@@ -3394,9 +3509,9 @@ static void hpet_msi_set_affinity(unsigned int irq, const struct cpumask *mask)
|
|
|
msg.address_lo |= MSI_ADDR_DEST_ID(dest);
|
|
|
|
|
|
hpet_msi_write(irq, &msg);
|
|
|
- desc = irq_to_desc(irq);
|
|
|
cpumask_copy(&desc->affinity, mask);
|
|
|
}
|
|
|
+
|
|
|
#endif /* CONFIG_SMP */
|
|
|
|
|
|
struct irq_chip hpet_msi_type = {
|
|
@@ -3451,25 +3566,27 @@ static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector)
|
|
|
|
|
|
static void set_ht_irq_affinity(unsigned int irq, const struct cpumask *mask)
|
|
|
{
|
|
|
+ struct irq_desc *desc = irq_to_desc(irq);
|
|
|
struct irq_cfg *cfg;
|
|
|
unsigned int dest;
|
|
|
cpumask_t tmp;
|
|
|
- struct irq_desc *desc;
|
|
|
|
|
|
if (!cpumask_intersects(mask, cpu_online_mask))
|
|
|
return;
|
|
|
|
|
|
- if (assign_irq_vector(irq, *mask))
|
|
|
+ cfg = desc->chip_data;
|
|
|
+ if (assign_irq_vector(irq, cfg, *mask))
|
|
|
return;
|
|
|
|
|
|
- cfg = irq_cfg(irq);
|
|
|
+ set_extra_move_desc(desc, *mask);
|
|
|
+
|
|
|
cpumask_and(&tmp, &cfg->domain, mask);
|
|
|
dest = cpu_mask_to_apicid(tmp);
|
|
|
|
|
|
target_ht_irq(irq, dest, cfg->vector);
|
|
|
- desc = irq_to_desc(irq);
|
|
|
cpumask_copy(&desc->affinity, mask);
|
|
|
}
|
|
|
+
|
|
|
#endif
|
|
|
|
|
|
static struct irq_chip ht_irq_chip = {
|
|
@@ -3489,13 +3606,13 @@ int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev)
|
|
|
int err;
|
|
|
cpumask_t tmp;
|
|
|
|
|
|
+ cfg = irq_cfg(irq);
|
|
|
tmp = TARGET_CPUS;
|
|
|
- err = assign_irq_vector(irq, tmp);
|
|
|
+ err = assign_irq_vector(irq, cfg, tmp);
|
|
|
if (!err) {
|
|
|
struct ht_irq_msg msg;
|
|
|
unsigned dest;
|
|
|
|
|
|
- cfg = irq_cfg(irq);
|
|
|
cpus_and(tmp, cfg->domain, tmp);
|
|
|
dest = cpu_mask_to_apicid(tmp);
|
|
|
|
|
@@ -3541,7 +3658,9 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
|
|
|
unsigned long flags;
|
|
|
int err;
|
|
|
|
|
|
- err = assign_irq_vector(irq, *eligible_cpu);
|
|
|
+ cfg = irq_cfg(irq);
|
|
|
+
|
|
|
+ err = assign_irq_vector(irq, cfg, *eligible_cpu);
|
|
|
if (err != 0)
|
|
|
return err;
|
|
|
|
|
@@ -3550,8 +3669,6 @@ int arch_enable_uv_irq(char *irq_name, unsigned int irq, int cpu, int mmr_blade,
|
|
|
irq_name);
|
|
|
spin_unlock_irqrestore(&vector_lock, flags);
|
|
|
|
|
|
- cfg = irq_cfg(irq);
|
|
|
-
|
|
|
mmr_value = 0;
|
|
|
entry = (struct uv_IO_APIC_route_entry *)&mmr_value;
|
|
|
BUG_ON(sizeof(struct uv_IO_APIC_route_entry) != sizeof(unsigned long));
|
|
@@ -3603,9 +3720,16 @@ int __init io_apic_get_redir_entries (int ioapic)
|
|
|
return reg_01.bits.entries;
|
|
|
}
|
|
|
|
|
|
-int __init probe_nr_irqs(void)
|
|
|
+void __init probe_nr_irqs_gsi(void)
|
|
|
{
|
|
|
- return NR_IRQS;
|
|
|
+ int idx;
|
|
|
+ int nr = 0;
|
|
|
+
|
|
|
+ for (idx = 0; idx < nr_ioapics; idx++)
|
|
|
+ nr += io_apic_get_redir_entries(idx) + 1;
|
|
|
+
|
|
|
+ if (nr > nr_irqs_gsi)
|
|
|
+ nr_irqs_gsi = nr;
|
|
|
}
|
|
|
|
|
|
/* --------------------------------------------------------------------------
|
|
@@ -3704,19 +3828,31 @@ int __init io_apic_get_version(int ioapic)
|
|
|
|
|
|
int io_apic_set_pci_routing (int ioapic, int pin, int irq, int triggering, int polarity)
|
|
|
{
|
|
|
+ struct irq_desc *desc;
|
|
|
+ struct irq_cfg *cfg;
|
|
|
+ int cpu = boot_cpu_id;
|
|
|
+
|
|
|
if (!IO_APIC_IRQ(irq)) {
|
|
|
apic_printk(APIC_QUIET,KERN_ERR "IOAPIC[%d]: Invalid reference to IRQ 0\n",
|
|
|
ioapic);
|
|
|
return -EINVAL;
|
|
|
}
|
|
|
|
|
|
+ desc = irq_to_desc_alloc_cpu(irq, cpu);
|
|
|
+ if (!desc) {
|
|
|
+ printk(KERN_INFO "can not get irq_desc %d\n", irq);
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
/*
|
|
|
* IRQs < 16 are already in the irq_2_pin[] map
|
|
|
*/
|
|
|
- if (irq >= 16)
|
|
|
- add_pin_to_irq(irq, ioapic, pin);
|
|
|
+ if (irq >= NR_IRQS_LEGACY) {
|
|
|
+ cfg = desc->chip_data;
|
|
|
+ add_pin_to_irq_cpu(cfg, cpu, ioapic, pin);
|
|
|
+ }
|
|
|
|
|
|
- setup_IO_APIC_irq(ioapic, pin, irq, triggering, polarity);
|
|
|
+ setup_IO_APIC_irq(ioapic, pin, irq, desc, triggering, polarity);
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -3770,9 +3906,10 @@ void __init setup_ioapic_dest(void)
|
|
|
* when you have too many devices, because at that time only boot
|
|
|
* cpu is online.
|
|
|
*/
|
|
|
- cfg = irq_cfg(irq);
|
|
|
+ desc = irq_to_desc(irq);
|
|
|
+ cfg = desc->chip_data;
|
|
|
if (!cfg->vector) {
|
|
|
- setup_IO_APIC_irq(ioapic, pin, irq,
|
|
|
+ setup_IO_APIC_irq(ioapic, pin, irq, desc,
|
|
|
irq_trigger(irq_entry),
|
|
|
irq_polarity(irq_entry));
|
|
|
continue;
|
|
@@ -3782,7 +3919,6 @@ void __init setup_ioapic_dest(void)
|
|
|
/*
|
|
|
* Honour affinities which have been set in early boot
|
|
|
*/
|
|
|
- desc = irq_to_desc(irq);
|
|
|
if (desc->status &
|
|
|
(IRQ_NO_BALANCING | IRQ_AFFINITY_SET))
|
|
|
mask = desc->affinity;
|
|
@@ -3791,10 +3927,10 @@ void __init setup_ioapic_dest(void)
|
|
|
|
|
|
#ifdef CONFIG_INTR_REMAP
|
|
|
if (intr_remapping_enabled)
|
|
|
- set_ir_ioapic_affinity_irq(irq, &mask);
|
|
|
+ set_ir_ioapic_affinity_irq_desc(desc, &mask);
|
|
|
else
|
|
|
#endif
|
|
|
- set_ioapic_affinity_irq(irq, &mask);
|
|
|
+ set_ioapic_affinity_irq_desc(desc, &mask);
|
|
|
}
|
|
|
|
|
|
}
|
|
@@ -3843,7 +3979,6 @@ void __init ioapic_init_mappings(void)
|
|
|
struct resource *ioapic_res;
|
|
|
int i;
|
|
|
|
|
|
- irq_2_pin_init();
|
|
|
ioapic_res = ioapic_setup_resources();
|
|
|
for (i = 0; i < nr_ioapics; i++) {
|
|
|
if (smp_found_config) {
|