[PATCH] pass irq handling status down to low-level code

From: Jan Beulich (JBeulich_at_novell.com)
Date: 09/08/05

  • Next message: Richard Purdie: "Re: [-mm patch 5/5] SharpSL: Add new ARM PXA machines Spitz and Borzoi with partial Akita Support"
    Date:	Thu, 08 Sep 2005 16:49:08 +0200
    To: <linux-kernel@vger.kernel.org>
    
    
    

    (Note: Patch also attached because the inline version is certain to get
    line wrapped.)

    In order for low-level code to know whether/how a hardware interrupt
    was
    serviced, make sure this information gets passed down correctly.

    At once, use the proper type (irqreturn_t) for returning this
    information,
    which in turn required breaking up a header into two to resolve
    recursive
    inclusion problems resulting otherwise.

    Architecture dependent code needs to change for this to fully work,
    but
    no change should be necessary if the described functionality isn't
    consumed on a given architecture. Thus respective adjustments in this
    patch
    are only to those architectures I have further depend code for (i386,
    x86_64, ia64).

    (Kernel debuggers may want to convert a hardware interrupt, say from a
    hot key press, into a pseudo-exception, requiring that they should
    have
    a way to get this information communicated from the respective
    interrupt
    handler. For this to fully work, additional adjustments are necessary,
    so this is meant ot only be the first step.)

    Signed-off-by: Jan Beulich <jbeulich@novell.com>

    diff -Npru 2.6.13/arch/i386/kernel/irq.c
    2.6.13-irqreturn/arch/i386/kernel/irq.c
    --- 2.6.13/arch/i386/kernel/irq.c 2005-08-29 01:41:01.000000000
    +0200
    +++ 2.6.13-irqreturn/arch/i386/kernel/irq.c 2005-09-01
    11:32:11.000000000 +0200
    @@ -51,7 +51,7 @@ static union irq_ctx *softirq_ctx[NR_CPU
      * SMP cross-CPU interrupts have their own specific
      * handlers).
      */
    -fastcall unsigned int do_IRQ(struct pt_regs *regs)
    +fastcall irqreturn_t do_IRQ(struct pt_regs *regs)
     {
             /* high bits used in ret_from_ code */
             int irq = regs->orig_eax & 0xff;
    @@ -59,6 +59,7 @@ fastcall unsigned int do_IRQ(struct pt_r
             union irq_ctx *curctx, *irqctx;
             u32 *isp;
     #endif
    + irqreturn_t ret;
     
             irq_enter();
     #ifdef CONFIG_DEBUG_STACKOVERFLOW
    @@ -88,7 +89,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 edx, ebx;
     
                     /* build the stack frame on the IRQ stack */
                     isp = (u32*) ((char*)irqctx + sizeof(*irqctx));
    @@ -99,17 +100,17 @@ fastcall unsigned int do_IRQ(struct pt_r
                             " xchgl %%ebx,%%esp \n"
                             " call __do_IRQ \n"
                             " movl %%ebx,%%esp \n"
    - : "=a" (arg1), "=d" (arg2), "=b" (ebx)
    - : "0" (irq), "1" (regs), "2" (isp)
    + : "=a" (ret), "=d" (edx), "=b" (ebx)
    + : "0" (irq), "1" (regs), "2" (isp)
                             : "memory", "cc", "ecx"
                     );
             } else
     #endif
    - __do_IRQ(irq, regs);
    + ret = __do_IRQ(irq, regs);
     
             irq_exit();
     
    - return 1;
    + return ret;
     }
     
     #ifdef CONFIG_4KSTACKS
    diff -Npru 2.6.13/arch/i386/mach-visws/visws_apic.c
    2.6.13-irqreturn/arch/i386/mach-visws/visws_apic.c
    --- 2.6.13/arch/i386/mach-visws/visws_apic.c 2005-08-29
    01:41:01.000000000 +0200
    +++ 2.6.13-irqreturn/arch/i386/mach-visws/visws_apic.c 2005-03-16
    12:24:41.000000000 +0100
    @@ -198,6 +198,7 @@ static irqreturn_t piix4_master_intr(int
             int realirq;
             irq_desc_t *desc;
             unsigned long flags;
    + irqreturn_t ret;
     
             spin_lock_irqsave(&i8259A_lock, flags);
     
    @@ -246,12 +247,14 @@ static irqreturn_t piix4_master_intr(int
             kstat_cpu(smp_processor_id()).irqs[realirq]++;
     
             if (likely(desc->action != NULL))
    - handle_IRQ_event(realirq, regs, desc->action);
    + ret = handle_IRQ_event(realirq, regs, desc->action);
    + else
    + ret = IRQ_NONE;
     
             if (!(desc->status & IRQ_DISABLED))
                     enable_8259A_irq(realirq);
     
    - return IRQ_HANDLED;
    + return ret;
     
     out_unlock:
             spin_unlock_irqrestore(&i8259A_lock, flags);
    diff -Npru 2.6.13/arch/ia64/kernel/irq_ia64.c
    2.6.13-irqreturn/arch/ia64/kernel/irq_ia64.c
    --- 2.6.13/arch/ia64/kernel/irq_ia64.c 2005-08-29 01:41:01.000000000
    +0200
    +++ 2.6.13-irqreturn/arch/ia64/kernel/irq_ia64.c 2005-09-01
    14:08:15.000000000 +0200
    @@ -99,10 +99,11 @@ free_irq_vector (int vector)
      * interrupt. This branches to the correct hardware IRQ handler via
      * function ptr.
      */
    -void
    +irqreturn_t
     ia64_handle_irq (ia64_vector vector, struct pt_regs *regs)
     {
             unsigned long saved_tpr;
    + irqreturn_t ret;
     
     #if IRQ_DEBUG
             {
    @@ -142,12 +143,13 @@ ia64_handle_irq (ia64_vector vector, str
             irq_enter();
             saved_tpr = ia64_getreg(_IA64_REG_CR_TPR);
             ia64_srlz_d();
    + ret = IRQ_NONE;
             while (vector != IA64_SPURIOUS_INT_VECTOR) {
                     if (!IS_RESCHEDULE(vector)) {
                             ia64_setreg(_IA64_REG_CR_TPR, vector);
                             ia64_srlz_d();
     
    - __do_IRQ(local_vector_to_irq(vector), regs);
    + ret |= __do_IRQ(local_vector_to_irq(vector),
    regs);
     
                             /*
                              * Disable interrupts and send EOI:
    @@ -164,6 +166,7 @@ ia64_handle_irq (ia64_vector vector, str
              * come through until ia64_eoi() has been done.
              */
             irq_exit();
    + return ret;
     }
     
     #ifdef CONFIG_HOTPLUG_CPU
    diff -Npru 2.6.13/arch/x86_64/kernel/irq.c
    2.6.13-irqreturn/arch/x86_64/kernel/irq.c
    --- 2.6.13/arch/x86_64/kernel/irq.c 2005-08-29 01:41:01.000000000
    +0200
    +++ 2.6.13-irqreturn/arch/x86_64/kernel/irq.c 2005-09-01
    11:32:11.000000000 +0200
    @@ -93,18 +93,19 @@ skip:
      * SMP cross-CPU interrupts have their own specific
      * handlers).
      */
    -asmlinkage unsigned int do_IRQ(struct pt_regs *regs)
    +asmlinkage irqreturn_t do_IRQ(struct pt_regs *regs)
     {
             /* high bits used in ret_from_ code */
             unsigned irq = regs->orig_rax & 0xff;
    + irqreturn_t ret = IRQ_NONE;
     
             irq_enter();
    - BUG_ON(irq > 256);
     
    - __do_IRQ(irq, regs);
    + ret = __do_IRQ(irq, regs);
    +
             irq_exit();
     
    - return 1;
    + return ret;
     }
     
     #ifdef CONFIG_HOTPLUG_CPU
    diff -Npru 2.6.13/include/linux/interrupt.h
    2.6.13-irqreturn/include/linux/interrupt.h
    --- 2.6.13/include/linux/interrupt.h 2005-08-29 01:41:01.000000000
    +0200
    +++ 2.6.13-irqreturn/include/linux/interrupt.h 2005-03-21
    14:20:20.000000000 +0100
    @@ -8,31 +8,12 @@
     #include <linux/bitops.h>
     #include <linux/preempt.h>
     #include <linux/cpumask.h>
    +#include <linux/irqreturn.h>
     #include <linux/hardirq.h>
     #include <asm/atomic.h>
     #include <asm/ptrace.h>
     #include <asm/system.h>
     
    -/*
    - * For 2.4.x compatibility, 2.4.x can use
    - *
    - * typedef void irqreturn_t;
    - * #define IRQ_NONE
    - * #define IRQ_HANDLED
    - * #define IRQ_RETVAL(x)
    - *
    - * To mix old-style and new-style irq handler returns.
    - *
    - * IRQ_NONE means we didn't handle it.
    - * IRQ_HANDLED means that we did have a valid interrupt and handled
    it.
    - * IRQ_RETVAL(x) selects on the two depending on x being non-zero (for
    handled)
    - */
    -typedef int irqreturn_t;
    -
    -#define IRQ_NONE (0)
    -#define IRQ_HANDLED (1)
    -#define IRQ_RETVAL(x) ((x) != 0)
    -
     struct irqaction {
             irqreturn_t (*handler)(int, void *, struct pt_regs *);
             unsigned long flags;
    diff -Npru 2.6.13/include/linux/irq.h
    2.6.13-irqreturn/include/linux/irq.h
    --- 2.6.13/include/linux/irq.h 2005-08-29 01:41:01.000000000 +0200
    +++ 2.6.13-irqreturn/include/linux/irq.h 2005-09-01
    17:43:05.000000000 +0200
    @@ -17,6 +17,7 @@
     #include <linux/cache.h>
     #include <linux/spinlock.h>
     #include <linux/cpumask.h>
    +#include <linux/irqreturn.h>
     
     #include <asm/irq.h>
     #include <asm/ptrace.h>
    @@ -86,7 +87,7 @@ extern int noirqdebug_setup(char *str);
     
     extern fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs
    *regs,
                                             struct irqaction *action);
    -extern fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs
    *regs);
    +extern fastcall irqreturn_t __do_IRQ(unsigned int irq, struct pt_regs
    *regs);
     extern void note_interrupt(unsigned int irq, irq_desc_t *desc,
                                             int action_ret, struct pt_regs
    *regs);
     extern int can_request_irq(unsigned int irq, unsigned long irqflags);
    diff -Npru 2.6.13/include/linux/irqreturn.h
    2.6.13-irqreturn/include/linux/irqreturn.h
    --- 2.6.13/include/linux/irqreturn.h 1970-01-01 01:00:00.000000000
    +0100
    +++ 2.6.13-irqreturn/include/linux/irqreturn.h 2005-03-21
    14:21:06.000000000 +0100
    @@ -0,0 +1,27 @@
    +/* irqreturn.h */
    +#ifndef _LINUX_IRQRETURN_H
    +#define _LINUX_IRQRETURN_H
    +
    +#include <linux/config.h>
    +
    +/*
    + * For 2.4.x compatibility, 2.4.x can use
    + *
    + * typedef void irqreturn_t;
    + * #define IRQ_NONE
    + * #define IRQ_HANDLED
    + * #define IRQ_RETVAL(x)
    + *
    + * To mix old-style and new-style irq handler returns.
    + *
    + * IRQ_NONE means we didn't handle it.
    + * IRQ_HANDLED means that we did have a valid interrupt and handled
    it.
    + * IRQ_RETVAL(x) selects on the two depending on x being non-zero (for
    handled)
    + */
    +typedef int irqreturn_t;
    +
    +#define IRQ_NONE (0)
    +#define IRQ_HANDLED (1)
    +#define IRQ_RETVAL(x) ((x) != 0)
    +
    +#endif
    diff -Npru 2.6.13/kernel/irq/handle.c
    2.6.13-irqreturn/kernel/irq/handle.c
    --- 2.6.13/kernel/irq/handle.c 2005-08-29 01:41:01.000000000 +0200
    +++ 2.6.13-irqreturn/kernel/irq/handle.c 2005-09-01
    17:54:23.000000000 +0200
    @@ -76,16 +76,18 @@ irqreturn_t no_action(int cpl, void *dev
     /*
      * Have got an event to handle:
      */
    -fastcall int handle_IRQ_event(unsigned int irq, struct pt_regs *regs,
    +fastcall irqreturn_t handle_IRQ_event(unsigned int irq, struct pt_regs
    *regs,
                                     struct irqaction *action)
     {
    - int ret, retval = 0, status = 0;
    + int status = 0;
    + irqreturn_t retval = IRQ_NONE;
     
             if (!(action->flags & SA_INTERRUPT))
                     local_irq_enable();
     
             do {
    - ret = action->handler(irq, action->dev_id, regs);
    + irqreturn_t ret = action->handler(irq, action->dev_id,
    regs);
    +
                     if (ret == IRQ_HANDLED)
                             status |= action->flags;
                     retval |= ret;
    @@ -104,15 +106,16 @@ fastcall int handle_IRQ_event(unsigned i
      * SMP cross-CPU interrupts have their own specific
      * handlers).
      */
    -fastcall unsigned int __do_IRQ(unsigned int irq, struct pt_regs
    *regs)
    +fastcall irqreturn_t __do_IRQ(unsigned int irq, struct pt_regs *regs)
     {
             irq_desc_t *desc = irq_desc + irq;
             struct irqaction * action;
             unsigned int status;
    + irqreturn_t ret = IRQ_NONE;
     
             kstat_this_cpu.irqs[irq]++;
             if (desc->status & IRQ_PER_CPU) {
    - irqreturn_t action_ret;
    + irqreturn_t action_ret = IRQ_NONE;
     
                     /*
                      * No locking required for CPU-local interrupts:
    @@ -120,7 +123,7 @@ fastcall unsigned int __do_IRQ(unsigned
                     desc->handler->ack(irq);
                     action_ret = handle_IRQ_event(irq, regs, desc->action);
                     desc->handler->end(irq);
    - return 1;
    + return action_ret;
             }
     
             spin_lock(&desc->lock);
    @@ -173,6 +176,7 @@ fastcall unsigned int __do_IRQ(unsigned
                     spin_lock(&desc->lock);
                     if (!noirqdebug)
                             note_interrupt(irq, desc, action_ret, regs);
    + ret |= action_ret;
                     if (likely(!(desc->status & IRQ_PENDING)))
                             break;
                     desc->status &= ~IRQ_PENDING;
    @@ -187,6 +191,6 @@ out:
             desc->handler->end(irq);
             spin_unlock(&desc->lock);
     
    - return 1;
    + return ret;
     }
     

    
    

    -
    To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
    the body of a message to majordomo@vger.kernel.org
    More majordomo info at http://vger.kernel.org/majordomo-info.html
    Please read the FAQ at http://www.tux.org/lkml/



  • Next message: Richard Purdie: "Re: [-mm patch 5/5] SharpSL: Add new ARM PXA machines Spitz and Borzoi with partial Akita Support"

    Relevant Pages