lkml.org 
[lkml]   [2012]   [Feb]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    Date
    From
    Subject[ 58/72] genirq: Handle pending irqs in irq_startup()
    3.2-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Thomas Gleixner <tglx@linutronix.de>

    commit b4bc724e82e80478cba5fe9825b62e71ddf78757 upstream.

    An interrupt might be pending when irq_startup() is called, but the
    startup code does not invoke the resend logic. In some cases this
    prevents the device from issuing another interrupt which renders the
    device non functional.

    Call the resend function in irq_startup() to keep things going.

    Reported-and-tested-by: Russell King <rmk+kernel@arm.linux.org.uk>
    Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    kernel/irq/autoprobe.c | 4 ++--
    kernel/irq/chip.c | 17 ++++++++++-------
    kernel/irq/internals.h | 2 +-
    kernel/irq/manage.c | 2 +-
    4 files changed, 14 insertions(+), 11 deletions(-)

    --- a/kernel/irq/autoprobe.c
    +++ b/kernel/irq/autoprobe.c
    @@ -53,7 +53,7 @@ unsigned long probe_irq_on(void)
    if (desc->irq_data.chip->irq_set_type)
    desc->irq_data.chip->irq_set_type(&desc->irq_data,
    IRQ_TYPE_PROBE);
    - irq_startup(desc);
    + irq_startup(desc, false);
    }
    raw_spin_unlock_irq(&desc->lock);
    }
    @@ -70,7 +70,7 @@ unsigned long probe_irq_on(void)
    raw_spin_lock_irq(&desc->lock);
    if (!desc->action && irq_settings_can_probe(desc)) {
    desc->istate |= IRQS_AUTODETECT | IRQS_WAITING;
    - if (irq_startup(desc))
    + if (irq_startup(desc, false))
    desc->istate |= IRQS_PENDING;
    }
    raw_spin_unlock_irq(&desc->lock);
    --- a/kernel/irq/chip.c
    +++ b/kernel/irq/chip.c
    @@ -157,19 +157,22 @@ static void irq_state_set_masked(struct
    irqd_set(&desc->irq_data, IRQD_IRQ_MASKED);
    }

    -int irq_startup(struct irq_desc *desc)
    +int irq_startup(struct irq_desc *desc, bool resend)
    {
    + int ret = 0;
    +
    irq_state_clr_disabled(desc);
    desc->depth = 0;

    if (desc->irq_data.chip->irq_startup) {
    - int ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
    + ret = desc->irq_data.chip->irq_startup(&desc->irq_data);
    irq_state_clr_masked(desc);
    - return ret;
    + } else {
    + irq_enable(desc);
    }
    -
    - irq_enable(desc);
    - return 0;
    + if (resend)
    + check_irq_resend(desc, desc->irq_data.irq);
    + return ret;
    }

    void irq_shutdown(struct irq_desc *desc)
    @@ -646,7 +649,7 @@ __irq_set_handler(unsigned int irq, irq_
    irq_settings_set_noprobe(desc);
    irq_settings_set_norequest(desc);
    irq_settings_set_nothread(desc);
    - irq_startup(desc);
    + irq_startup(desc, true);
    }
    out:
    irq_put_desc_busunlock(desc, flags);
    --- a/kernel/irq/internals.h
    +++ b/kernel/irq/internals.h
    @@ -67,7 +67,7 @@ extern int __irq_set_trigger(struct irq_
    extern void __disable_irq(struct irq_desc *desc, unsigned int irq, bool susp);
    extern void __enable_irq(struct irq_desc *desc, unsigned int irq, bool resume);

    -extern int irq_startup(struct irq_desc *desc);
    +extern int irq_startup(struct irq_desc *desc, bool resend);
    extern void irq_shutdown(struct irq_desc *desc);
    extern void irq_enable(struct irq_desc *desc);
    extern void irq_disable(struct irq_desc *desc);
    --- a/kernel/irq/manage.c
    +++ b/kernel/irq/manage.c
    @@ -1027,7 +1027,7 @@ __setup_irq(unsigned int irq, struct irq
    desc->istate |= IRQS_ONESHOT;

    if (irq_settings_can_autoenable(desc))
    - irq_startup(desc);
    + irq_startup(desc, true);
    else
    /* Undo nested disables: */
    desc->depth = 1;



    \
     
     \ /
      Last update: 2012-02-28 02:15    [W:4.110 / U:0.068 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site