Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 253227
b: refs/heads/master
c: 3a43e05
h: refs/heads/master
i:
  253225: 0a0f704
  253223: 001d7db
v: v3
  • Loading branch information
Sebastian Andrzej Siewior authored and Thomas Gleixner committed Jun 3, 2011
1 parent 6bf5738 commit eeccf52
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 20 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ef26f20cd117eb3c185038ed7cbf7b235575751d
refs/heads/master: 3a43e05f4d0600e906fa09f4a65d749288c44592
6 changes: 3 additions & 3 deletions trunk/include/linux/irqreturn.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@
* @IRQ_WAKE_THREAD handler requests to wake the handler thread
*/
enum irqreturn {
IRQ_NONE,
IRQ_HANDLED,
IRQ_WAKE_THREAD,
IRQ_NONE = (0 << 0),
IRQ_HANDLED = (1 << 0),
IRQ_WAKE_THREAD = (1 << 1),
};

typedef enum irqreturn irqreturn_t;
Expand Down
6 changes: 0 additions & 6 deletions trunk/kernel/irq/handle.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,12 +132,6 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)

switch (res) {
case IRQ_WAKE_THREAD:
/*
* Set result to handled so the spurious check
* does not trigger.
*/
res = IRQ_HANDLED;

/*
* Catch drivers which return WAKE_THREAD but
* did not set up a thread function
Expand Down
24 changes: 18 additions & 6 deletions trunk/kernel/irq/manage.c
Original file line number Diff line number Diff line change
Expand Up @@ -723,24 +723,31 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { }
* context. So we need to disable bh here to avoid deadlocks and other
* side effects.
*/
static void
static irqreturn_t
irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action)
{
irqreturn_t ret;

local_bh_disable();
action->thread_fn(action->irq, action->dev_id);
ret = action->thread_fn(action->irq, action->dev_id);
irq_finalize_oneshot(desc, action, false);
local_bh_enable();
return ret;
}

/*
* Interrupts explicitely requested as threaded interupts want to be
* preemtible - many of them need to sleep and wait for slow busses to
* complete.
*/
static void irq_thread_fn(struct irq_desc *desc, struct irqaction *action)
static irqreturn_t irq_thread_fn(struct irq_desc *desc,
struct irqaction *action)
{
action->thread_fn(action->irq, action->dev_id);
irqreturn_t ret;

ret = action->thread_fn(action->irq, action->dev_id);
irq_finalize_oneshot(desc, action, false);
return ret;
}

/*
Expand All @@ -753,7 +760,8 @@ static int irq_thread(void *data)
};
struct irqaction *action = data;
struct irq_desc *desc = irq_to_desc(action->irq);
void (*handler_fn)(struct irq_desc *desc, struct irqaction *action);
irqreturn_t (*handler_fn)(struct irq_desc *desc,
struct irqaction *action);
int wake;

if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD,
Expand Down Expand Up @@ -783,8 +791,12 @@ static int irq_thread(void *data)
desc->istate |= IRQS_PENDING;
raw_spin_unlock_irq(&desc->lock);
} else {
irqreturn_t action_ret;

raw_spin_unlock_irq(&desc->lock);
handler_fn(desc, action);
action_ret = handler_fn(desc, action);
if (!noirqdebug)
note_interrupt(action->irq, desc, action_ret);
}

wake = atomic_dec_and_test(&desc->threads_active);
Expand Down
22 changes: 18 additions & 4 deletions trunk/kernel/irq/spurious.c
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,13 @@ static void poll_spurious_irqs(unsigned long dummy)
jiffies + POLL_SPURIOUS_IRQ_INTERVAL);
}

static inline int bad_action_ret(irqreturn_t action_ret)
{
if (likely(action_ret <= (IRQ_HANDLED | IRQ_WAKE_THREAD)))
return 0;
return 1;
}

/*
* If 99,900 of the previous 100,000 interrupts have not been handled
* then assume that the IRQ is stuck in some manner. Drop a diagnostic
Expand All @@ -182,7 +189,7 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc,
struct irqaction *action;
unsigned long flags;

if (action_ret != IRQ_HANDLED && action_ret != IRQ_NONE) {
if (bad_action_ret(action_ret)) {
printk(KERN_ERR "irq event %d: bogus return value %x\n",
irq, action_ret);
} else {
Expand Down Expand Up @@ -263,7 +270,16 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
if (desc->istate & IRQS_POLL_INPROGRESS)
return;

if (unlikely(action_ret != IRQ_HANDLED)) {
/* we get here again via the threaded handler */
if (action_ret == IRQ_WAKE_THREAD)
return;

if (bad_action_ret(action_ret)) {
report_bad_irq(irq, desc, action_ret);
return;
}

if (unlikely(action_ret == IRQ_NONE)) {
/*
* If we are seeing only the odd spurious IRQ caused by
* bus asynchronicity then don't eventually trigger an error,
Expand All @@ -275,8 +291,6 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
else
desc->irqs_unhandled++;
desc->last_unhandled = jiffies;
if (unlikely(action_ret != IRQ_NONE))
report_bad_irq(irq, desc, action_ret);
}

if (unlikely(try_misrouted_irq(irq, desc, action_ret))) {
Expand Down

0 comments on commit eeccf52

Please sign in to comment.