Depending on the configuration and hardware, the kernel may allocate
device IRQs in the range above our static FIRST_SYSTEM_VECTOR. This
happens quickly with a non-trivial number of MSI-X capable devices.

Fix this and also optimize the critical vector->IRQ translation by
filling the kernel's per-CPU vector_irq table also with I-pipe
translations.

Signed-off-by: Jan Kiszka <[email protected]>
---
 arch/x86/include/asm/ipipe_base.h |    6 ++++++
 arch/x86/kernel/apic/io_apic.c    |    1 +
 arch/x86/kernel/ipipe.c           |   30 +++++++++++++++++-------------
 arch/x86/kernel/irqinit.c         |    1 +
 arch/x86/platform/uv/tlb_uv.c     |    5 +++++
 5 files changed, 30 insertions(+), 13 deletions(-)

diff --git a/arch/x86/include/asm/ipipe_base.h 
b/arch/x86/include/asm/ipipe_base.h
index 44c8c73..f28ca74 100644
--- a/arch/x86/include/asm/ipipe_base.h
+++ b/arch/x86/include/asm/ipipe_base.h
@@ -211,6 +211,12 @@ void __ipipe_halt_root(void);
 
 void __ipipe_serial_debug(const char *fmt, ...);
 
+#ifdef CONFIG_IPIPE
+void ipipe_init_vector_irq(int cpu);
+#else
+static inline void ipipe_init_vector_irq(int cpu) { }
+#endif
+
 #endif /* !__ASSEMBLY__ */
 
 #endif /* !__X86_IPIPE_BASE_H */
diff --git a/arch/x86/kernel/apic/io_apic.c b/arch/x86/kernel/apic/io_apic.c
index fa599db..8eaaadc 100644
--- a/arch/x86/kernel/apic/io_apic.c
+++ b/arch/x86/kernel/apic/io_apic.c
@@ -1205,6 +1205,7 @@ void __setup_vector_irq(int cpu)
                if (!cpumask_test_cpu(cpu, cfg->domain))
                        per_cpu(vector_irq, cpu)[vector] = -1;
        }
+       ipipe_init_vector_irq(cpu);
        raw_spin_unlock(&vector_lock);
 }
 
diff --git a/arch/x86/kernel/ipipe.c b/arch/x86/kernel/ipipe.c
index d1d4544..4e180db 100644
--- a/arch/x86/kernel/ipipe.c
+++ b/arch/x86/kernel/ipipe.c
@@ -141,6 +141,19 @@ static void __ipipe_null_handler(unsigned irq, void 
*cookie)
 /* __ipipe_enable_pipeline() -- We are running on the boot CPU, hw
    interrupts are off, and secondary CPUs are still lost in space. */
 
+void ipipe_init_vector_irq(int cpu)
+{
+       unsigned int vector;
+
+       per_cpu(vector_irq, cpu)[IRQ_MOVE_CLEANUP_VECTOR] =
+               IRQ_MOVE_CLEANUP_VECTOR;
+
+       for (vector = first_system_vector; vector < NR_VECTORS; vector++)
+               if (per_cpu(vector_irq, cpu)[vector] == -1)
+                       per_cpu(vector_irq, cpu)[vector] =
+                               ipipe_apic_vector_irq(vector);
+}
+
 void __init __ipipe_enable_pipeline(void)
 {
        unsigned int vector, irq;
@@ -685,23 +698,14 @@ int __ipipe_syscall_root(struct pt_regs *regs)
 int __ipipe_handle_irq(struct pt_regs *regs)
 {
        struct ipipe_domain *this_domain, *next_domain;
-       unsigned int vector = regs->orig_ax, irq;
+       int irq, vector = regs->orig_ax;
        struct list_head *head, *pos;
        struct pt_regs *tick_regs;
        int m_ack;
 
-       if ((long)regs->orig_ax < 0) {
-               vector = ~vector;
-#ifdef CONFIG_X86_LOCAL_APIC
-               if (vector >= FIRST_SYSTEM_VECTOR)
-                       irq = ipipe_apic_vector_irq(vector);
-#ifdef CONFIG_SMP
-               else if (vector == IRQ_MOVE_CLEANUP_VECTOR)
-                       irq = vector;
-#endif /* CONFIG_SMP */
-               else
-#endif /* CONFIG_X86_LOCAL_APIC */
-                       irq = __get_cpu_var(vector_irq)[vector];
+       if (vector < 0) {
+               irq = __get_cpu_var(vector_irq)[~vector];
+               BUG_ON(irq < 0);
                m_ack = 0;
        } else { /* This is a self-triggered one. */
                irq = vector;
diff --git a/arch/x86/kernel/irqinit.c b/arch/x86/kernel/irqinit.c
index 699fb0e..8aff110 100644
--- a/arch/x86/kernel/irqinit.c
+++ b/arch/x86/kernel/irqinit.c
@@ -232,6 +232,7 @@ static void __init apic_intr_init(void)
        alloc_intr_gate(IPIPE_SERVICE_VECTOR2, ipipe_ipi2);
        alloc_intr_gate(IPIPE_SERVICE_VECTOR3, ipipe_ipi3);
 #endif
+       ipipe_init_vector_irq(0);
 #endif
 }
 
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index ba9caa8..99cef66 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -1640,6 +1640,11 @@ static int __init uv_bau_init(void)
 
        uv_enable_timeouts();
        alloc_intr_gate(vector, uv_bau_message_intr1);
+#ifdef CONFIG_IPIPE
+       for_each_possible_cpu(cur_cpu)
+               per_cpu(vector_irq, cur_cpu)[vector] =
+                       ipipe_apic_vector_irq(vector);
+#endif
 
        for_each_possible_blade(uvhub) {
                if (uv_blade_nr_possible_cpus(uvhub)) {
-- 
1.7.1

_______________________________________________
Adeos-main mailing list
[email protected]
https://mail.gna.org/listinfo/adeos-main

Reply via email to