handle_prio_irq is almost identical with handle_fasteoi_irq. The subtle differences are 1) The handler checks for IRQ_DISABLED after the device handler has been called. In case it's set it masks the interrupt. 2) When the handler sees IRQ_DISABLED on entry it masks the interupt in the same way as handle_fastoei_irq, but does not set the IRQ_PENDING flag. 3) Instead of gracefully handling a recursive interrupt it crashes the kernel. #1 is just relevant when a device handler calls disable_irq_nosync() and it does not matter whether we mask the interrupt right away or not. We handle lazy masking for disable_irq anyway, so there is no real reason to have this extra mask in place. #2 will prevent the resend of a pending interrupt, which can result in lost interrupts for edge type interrupts. For level type interrupts the resend is a noop in the generic code. According to the datasheet all interrupts are level type, so marking them as such will result in the exact same behaviour as the private handle_prio_irq implementation. #3 is just stupid. Crashing the kernel instead of handling a problem gracefully is just wrong. With the current semantics- all handlers run with interrupts disabled - this is even more wrong. Rename ack to eoi, remove the unused mask_ack, switch to handle_fasteoi_irq and remove the private function. Signed-off-by: Thomas Gleixner Cc: Peter Zijlstra Acked-by: Uwe Kleine-Koenig Cc: linux-arm-kernel@lists.infradead.org LKML-Reference: <20110202212552.299898447@linutronix.de> --- arch/arm/mach-ns9xxx/irq.c | 58 +++------------------------------------------ 1 file changed, 4 insertions(+), 54 deletions(-) Index: linux-2.6-tip/arch/arm/mach-ns9xxx/irq.c =================================================================== --- linux-2.6-tip.orig/arch/arm/mach-ns9xxx/irq.c +++ linux-2.6-tip/arch/arm/mach-ns9xxx/irq.c @@ -31,17 +31,11 @@ static void ns9xxx_mask_irq(struct irq_d __raw_writel(ic, SYS_IC(prio / 4)); } -static void ns9xxx_ack_irq(struct irq_data *d) +static void ns9xxx_eoi_irq(struct irq_data *d) { __raw_writel(0, SYS_ISRADDR); } -static void ns9xxx_maskack_irq(struct irq_data *d) -{ - ns9xxx_mask_irq(d); - ns9xxx_ack_irq(d); -} - static void ns9xxx_unmask_irq(struct irq_data *d) { /* XXX: better use cpp symbols */ @@ -52,56 +46,11 @@ static void ns9xxx_unmask_irq(struct irq } static struct irq_chip ns9xxx_chip = { - .irq_ack = ns9xxx_ack_irq, + .irq_eoi = ns9xxx_eoi_irq, .irq_mask = ns9xxx_mask_irq, - .irq_mask_ack = ns9xxx_maskack_irq, .irq_unmask = ns9xxx_unmask_irq, }; -#if 0 -#define handle_irq handle_level_irq -#else -static void handle_prio_irq(unsigned int irq, struct irq_desc *desc) -{ - struct irqaction *action; - irqreturn_t action_ret; - - raw_spin_lock(&desc->lock); - - BUG_ON(desc->status & IRQ_INPROGRESS); - - desc->status &= ~(IRQ_REPLAY | IRQ_WAITING); - kstat_incr_irqs_this_cpu(irq, desc); - - action = desc->action; - if (unlikely(!action || (desc->status & IRQ_DISABLED))) - goto out_mask; - - desc->status |= IRQ_INPROGRESS; - raw_spin_unlock(&desc->lock); - - action_ret = handle_IRQ_event(irq, action); - - /* XXX: There is no direct way to access noirqdebug, so check - * unconditionally for spurious irqs... - * Maybe this function should go to kernel/irq/chip.c? */ - note_interrupt(irq, desc, action_ret); - - raw_spin_lock(&desc->lock); - desc->status &= ~IRQ_INPROGRESS; - - if (desc->status & IRQ_DISABLED) -out_mask: - desc->irq_data.chip->irq_mask(&desc->irq_data); - - /* ack unconditionally to unmask lower prio irqs */ - desc->irq_data.chip->irq_ack(&desc->irq_data); - - raw_spin_unlock(&desc->lock); -} -#define handle_irq handle_prio_irq -#endif - void __init ns9xxx_init_irq(void) { int i; @@ -119,7 +68,8 @@ void __init ns9xxx_init_irq(void) for (i = 0; i <= 31; ++i) { set_irq_chip(i, &ns9xxx_chip); - set_irq_handler(i, handle_irq); + set_irq_handler(i, handle_fasteoi_irq); set_irq_flags(i, IRQF_VALID); + irq_set_status_flags(i, IRQ_LEVEL); } }