lkml.org 
[lkml]   [2010]   [Dec]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v3 3/4] genirq: Add support for IRQF_COND_ONESHOT
    Date
    From: Jan Kiszka <jan.kiszka@siemens.com>

    Provide an adaptive version of IRQF_ONESHOT: If the line is exclusively used,
    IRQF_COND_ONESHOT provides the same semantics as IRQF_ONESHOT. If it is
    shared, the line will be unmasked directly after the hardirq handler, just as
    if IRQF_COND_ONESHOT was not provided.

    Signed-off-by: Jan Kiszka <jan.kiszka@siemens.com>
    ---
    include/linux/interrupt.h | 3 +++
    kernel/irq/manage.c | 19 ++++++++++++++++---
    2 files changed, 19 insertions(+), 3 deletions(-)

    diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
    index 12e5fc0..bbb16f4 100644
    --- a/include/linux/interrupt.h
    +++ b/include/linux/interrupt.h
    @@ -56,6 +56,8 @@
    * irq line disabled until the threaded handler has been run.
    * IRQF_NO_SUSPEND - Do not disable this IRQ during suspend
    * IRQF_ADAPTIVE - Request notification about upcoming interrupt line sharing
    + * IRQF_COND_ONESHOT - If line is not shared, keep interrupt disabled after
    + * hardirq handler finshed.
    *
    */
    #define IRQF_DISABLED 0x00000020
    @@ -69,6 +71,7 @@
    #define IRQF_ONESHOT 0x00002000
    #define IRQF_NO_SUSPEND 0x00004000
    #define IRQF_ADAPTIVE 0x00008000
    +#define IRQF_COND_ONESHOT 0x00010000

    #define IRQF_TIMER (__IRQF_TIMER | IRQF_NO_SUSPEND)

    diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
    index 2dd4eef..9a73633 100644
    --- a/kernel/irq/manage.c
    +++ b/kernel/irq/manage.c
    @@ -583,7 +583,7 @@ static int irq_thread(void *data)
    struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO/2, };
    struct irqaction *action = data;
    struct irq_desc *desc = irq_to_desc(action->irq);
    - int wake, oneshot = desc->status & IRQ_ONESHOT;
    + int wake, oneshot;

    sched_setscheduler(current, SCHED_FIFO, &param);
    current->irqaction = action;
    @@ -606,6 +606,7 @@ static int irq_thread(void *data)
    desc->status |= IRQ_PENDING;
    raw_spin_unlock_irq(&desc->lock);
    } else {
    + oneshot = desc->status & IRQ_ONESHOT;
    raw_spin_unlock_irq(&desc->lock);

    action->thread_fn(action->irq, action->dev_id);
    @@ -759,6 +760,15 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
    shared = 1;

    desc->irq_data.drv_status |= IRQS_SHARED;
    + desc->status &= ~IRQ_ONESHOT;
    +
    + /* Unmask if the interrupt was masked due to oneshot mode. */
    + if ((desc->status &
    + (IRQ_INPROGRESS | IRQ_DISABLED | IRQ_MASKED)) ==
    + IRQ_MASKED) {
    + desc->irq_data.chip->irq_unmask(&desc->irq_data);
    + desc->status &= ~IRQ_MASKED;
    + }
    }

    if (!shared) {
    @@ -783,7 +793,7 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
    desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | IRQ_ONESHOT |
    IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);

    - if (new->flags & IRQF_ONESHOT)
    + if (new->flags & (IRQF_ONESHOT | IRQF_COND_ONESHOT))
    desc->status |= IRQ_ONESHOT;

    if (!(desc->status & IRQ_NOAUTOEN)) {
    @@ -934,8 +944,11 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
    desc->irq_data.chip->irq_shutdown(&desc->irq_data);
    else
    desc->irq_data.chip->irq_disable(&desc->irq_data);
    - } else if (!desc->action->next)
    + } else if (!desc->action->next) {
    single_handler = true;
    + if (desc->action->flags & IRQF_COND_ONESHOT)
    + desc->status |= IRQ_ONESHOT;
    + }

    #ifdef CONFIG_SMP
    /* make sure affinity_hint is cleaned up */
    --
    1.7.1


    \
     
     \ /
      Last update: 2010-12-14 00:03    [W:4.140 / U:0.304 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site