From: Ingo Molnar This patch converts all the i386 PIC controllers (except VisWS and Voyager, which I could not test - but which should still work as old-style IRQ layers) to the new and simpler irq-chip interrupt handling layer. Signed-off-by: Ingo Molnar Signed-off-by: Thomas Gleixner Signed-off-by: Andrew Morton --- arch/i386/kernel/i8259.c | 45 ++------- arch/i386/kernel/io_apic.c | 165 ++++++++++------------------------- arch/i386/kernel/irq.c | 19 ++-- include/asm-i386/hw_irq.h | 2 4 files changed, 76 insertions(+), 155 deletions(-) diff -puN arch/i386/kernel/i8259.c~genirq-convert-the-i386-architecture-to-irq-chips arch/i386/kernel/i8259.c --- a/arch/i386/kernel/i8259.c~genirq-convert-the-i386-architecture-to-irq-chips +++ a/arch/i386/kernel/i8259.c @@ -34,39 +34,21 @@ * moves to arch independent land */ -DEFINE_SPINLOCK(i8259A_lock); - -static void end_8259A_irq (unsigned int irq) -{ - if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS)) && - irq_desc[irq].action) - enable_8259A_irq(irq); -} - -#define shutdown_8259A_irq disable_8259A_irq - static void mask_and_ack_8259A(unsigned int); -unsigned int startup_8259A_irq(unsigned int irq) -{ - enable_8259A_irq(irq); - return 0; /* never anything pending */ -} - -static struct hw_interrupt_type i8259A_irq_type = { - .typename = "XT-PIC", - .startup = startup_8259A_irq, - .shutdown = shutdown_8259A_irq, - .enable = enable_8259A_irq, - .disable = disable_8259A_irq, - .ack = mask_and_ack_8259A, - .end = end_8259A_irq, +static struct irq_chip i8259A_chip = { + .name = "XT-PIC", + .mask = disable_8259A_irq, + .unmask = enable_8259A_irq, + .mask_ack = mask_and_ack_8259A, }; /* * 8259A PIC functions to handle ISA devices: */ +DEFINE_SPINLOCK(i8259A_lock); + /* * This contains the irq mask for both 8259A irq controllers, */ @@ -131,7 +113,7 @@ void make_8259A_irq(unsigned int irq) { disable_irq_nosync(irq); io_apic_irqs &= ~(1<> 1)); @@ -2014,35 +1990,19 @@ static void end_level_ioapic_irq (unsign } } -#ifdef CONFIG_PCI_MSI -static unsigned int startup_edge_ioapic_vector(unsigned int vector) -{ - int irq = vector_to_irq(vector); - - return startup_edge_ioapic_irq(irq); -} - -static void ack_edge_ioapic_vector(unsigned int vector) -{ - int irq = vector_to_irq(vector); - - move_native_irq(vector); - ack_edge_ioapic_irq(irq); -} - -static unsigned int startup_level_ioapic_vector (unsigned int vector) +static unsigned int startup_ioapic_vector(unsigned int vector) { int irq = vector_to_irq(vector); - return startup_level_ioapic_irq (irq); + return startup_ioapic_irq(irq); } -static void end_level_ioapic_vector (unsigned int vector) +static void ack_ioapic_quirk_vector(unsigned int vector) { int irq = vector_to_irq(vector); move_native_irq(vector); - end_level_ioapic_irq(irq); + ack_ioapic_quirk_irq(irq); } static void mask_IO_APIC_vector (unsigned int vector) @@ -2069,50 +2029,28 @@ static void set_ioapic_affinity_vector ( set_ioapic_affinity_irq(irq, cpu_mask); } #endif -#endif -static int ioapic_retrigger(unsigned int irq) +static int ioapic_retrigger_vector(unsigned int vector) { + int irq = vector_to_irq(vector); + send_IPI_self(IO_APIC_VECTOR(irq)); return 1; } -/* - * Level and edge triggered IO-APIC interrupts need different handling, - * so we use two separate IRQ descriptors. Edge triggered IRQs can be - * handled with the level-triggered descriptor, but that one has slightly - * more overhead. Level-triggered interrupts cannot be handled with the - * edge-triggered handler, without risking IRQ storms and other ugly - * races. - */ -static struct hw_interrupt_type ioapic_edge_type __read_mostly = { - .typename = "IO-APIC-edge", - .startup = startup_edge_ioapic, - .shutdown = shutdown_edge_ioapic, - .enable = enable_edge_ioapic, - .disable = disable_edge_ioapic, - .ack = ack_edge_ioapic, - .end = end_edge_ioapic, +static struct irq_chip ioapic_chip __read_mostly = { + .name = "IO-APIC", + .startup = startup_ioapic_vector, + .mask = mask_IO_APIC_vector, + .unmask = unmask_IO_APIC_vector, + .ack = ack_ioapic_quirk_vector, #ifdef CONFIG_SMP .set_affinity = set_ioapic_affinity, #endif - .retrigger = ioapic_retrigger, + .retrigger = ioapic_retrigger_vector, }; -static struct hw_interrupt_type ioapic_level_type __read_mostly = { - .typename = "IO-APIC-level", - .startup = startup_level_ioapic, - .shutdown = shutdown_level_ioapic, - .enable = enable_level_ioapic, - .disable = disable_level_ioapic, - .ack = mask_and_ack_level_ioapic, - .end = end_level_ioapic, -#ifdef CONFIG_SMP - .set_affinity = set_ioapic_affinity, -#endif - .retrigger = ioapic_retrigger, -}; static inline void init_IO_APIC_traps(void) { @@ -2146,20 +2084,21 @@ static inline void init_IO_APIC_traps(vo make_8259A_irq(irq); else /* Strange. Oh, well.. */ - irq_desc[irq].chip = &no_irq_type; + irq_desc[irq].chip = &no_irq_chip; } } } -static void enable_lapic_irq (unsigned int irq) -{ - unsigned long v; +/* + * The local APIC irq-chip implementation: + */ - v = apic_read(APIC_LVT0); - apic_write_around(APIC_LVT0, v & ~APIC_LVT_MASKED); +static void ack_apic(unsigned int irq) +{ + ack_APIC_irq(); } -static void disable_lapic_irq (unsigned int irq) +static void mask_lapic_irq (unsigned int irq) { unsigned long v; @@ -2167,21 +2106,19 @@ static void disable_lapic_irq (unsigned apic_write_around(APIC_LVT0, v | APIC_LVT_MASKED); } -static void ack_lapic_irq (unsigned int irq) +static void unmask_lapic_irq (unsigned int irq) { - ack_APIC_irq(); -} + unsigned long v; -static void end_lapic_irq (unsigned int i) { /* nothing */ } + v = apic_read(APIC_LVT0); + apic_write_around(APIC_LVT0, v & ~APIC_LVT_MASKED); +} -static struct hw_interrupt_type lapic_irq_type __read_mostly = { - .typename = "local-APIC-edge", - .startup = NULL, /* startup_irq() not used for IRQ0 */ - .shutdown = NULL, /* shutdown_irq() not used for IRQ0 */ - .enable = enable_lapic_irq, - .disable = disable_lapic_irq, - .ack = ack_lapic_irq, - .end = end_lapic_irq +static struct irq_chip lapic_chip __read_mostly = { + .name = "local-APIC-edge", + .mask = mask_lapic_irq, + .unmask = unmask_lapic_irq, + .ack = ack_apic, }; static void setup_nmi (void) @@ -2362,7 +2299,7 @@ static inline void check_timer(void) printk(KERN_INFO "...trying to set up timer as Virtual Wire IRQ..."); disable_8259A_irq(0); - irq_desc[0].chip = &lapic_irq_type; + set_irq_chip_and_handler(0, &lapic_chip, handle_fastack_irq); apic_write_around(APIC_LVT0, APIC_DM_FIXED | vector); /* Fixed mode */ enable_8259A_irq(0); diff -puN arch/i386/kernel/irq.c~genirq-convert-the-i386-architecture-to-irq-chips arch/i386/kernel/irq.c --- a/arch/i386/kernel/irq.c~genirq-convert-the-i386-architecture-to-irq-chips +++ a/arch/i386/kernel/irq.c @@ -55,6 +55,7 @@ fastcall unsigned int do_IRQ(struct pt_r { /* high bit used in ret_from_ code */ int irq = ~regs->orig_eax; + struct irq_desc *desc = irq_desc + irq; #ifdef CONFIG_4KSTACKS union irq_ctx *curctx, *irqctx; u32 *isp; @@ -98,7 +99,7 @@ fastcall unsigned int do_IRQ(struct pt_r * current stack (which is the irq stack already after all) */ if (curctx != irqctx) { - int arg1, arg2, ebx; + int arg1, arg2, arg3, ebx; /* build the stack frame on the IRQ stack */ isp = (u32*) ((char*)irqctx + sizeof(*irqctx)); @@ -114,16 +115,17 @@ fastcall unsigned int do_IRQ(struct pt_r (curctx->tinfo.preempt_count & SOFTIRQ_MASK); asm volatile( - " xchgl %%ebx,%%esp \n" - " call __do_IRQ \n" + " xchgl %%ebx,%%esp \n" + " call *%%edi \n" " movl %%ebx,%%esp \n" - : "=a" (arg1), "=d" (arg2), "=b" (ebx) - : "0" (irq), "1" (regs), "2" (isp) - : "memory", "cc", "ecx" + : "=a" (arg1), "=d" (arg2), "=c" (arg3), "=b" (ebx) + : "0" (irq), "1" (desc), "2" (regs), "3" (isp), + "D" (desc->handle_irq) + : "memory", "cc" ); } else #endif - __do_IRQ(irq, regs); + desc->handle_irq(irq, desc, regs); out_exit: irq_exit(); @@ -258,7 +260,8 @@ int show_interrupts(struct seq_file *p, for_each_online_cpu(j) seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]); #endif - seq_printf(p, " %14s", irq_desc[i].chip->typename); + seq_printf(p, " %8s", irq_desc[i].chip->name); + seq_printf(p, "-%s", handle_irq_name(irq_desc[i].handle_irq)); seq_printf(p, " %s", action->name); for (action=action->next; action; action = action->next) diff -puN include/asm-i386/hw_irq.h~genirq-convert-the-i386-architecture-to-irq-chips include/asm-i386/hw_irq.h --- a/include/asm-i386/hw_irq.h~genirq-convert-the-i386-architecture-to-irq-chips +++ a/include/asm-i386/hw_irq.h @@ -17,8 +17,6 @@ #include #include -struct hw_interrupt_type; - #define NMI_VECTOR 0x02 /* _