Commit cb0a02ec authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'irq-urgent-for-linus' of...

Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip

* 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
  genirq: Ensure we locate the passed IRQ in irq_alloc_descs()
  genirq: Fix descriptor init on non-sparse IRQs
  irq: Handle spurios irq detection for threaded irqs
  genirq: Print threaded handler in spurious debug output
parents d681f120 c5182b88
...@@ -8,9 +8,9 @@ ...@@ -8,9 +8,9 @@
* @IRQ_WAKE_THREAD handler requests to wake the handler thread * @IRQ_WAKE_THREAD handler requests to wake the handler thread
*/ */
enum irqreturn { enum irqreturn {
IRQ_NONE, IRQ_NONE = (0 << 0),
IRQ_HANDLED, IRQ_HANDLED = (1 << 0),
IRQ_WAKE_THREAD, IRQ_WAKE_THREAD = (1 << 1),
}; };
typedef enum irqreturn irqreturn_t; typedef enum irqreturn irqreturn_t;
......
...@@ -132,12 +132,6 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action) ...@@ -132,12 +132,6 @@ handle_irq_event_percpu(struct irq_desc *desc, struct irqaction *action)
switch (res) { switch (res) {
case IRQ_WAKE_THREAD: 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 * Catch drivers which return WAKE_THREAD but
* did not set up a thread function * did not set up a thread function
......
...@@ -257,13 +257,11 @@ int __init early_irq_init(void) ...@@ -257,13 +257,11 @@ int __init early_irq_init(void)
count = ARRAY_SIZE(irq_desc); count = ARRAY_SIZE(irq_desc);
for (i = 0; i < count; i++) { for (i = 0; i < count; i++) {
desc[i].irq_data.irq = i;
desc[i].irq_data.chip = &no_irq_chip;
desc[i].kstat_irqs = alloc_percpu(unsigned int); desc[i].kstat_irqs = alloc_percpu(unsigned int);
irq_settings_clr_and_set(desc, ~0, _IRQ_DEFAULT_INIT_FLAGS); alloc_masks(&desc[i], GFP_KERNEL, node);
alloc_masks(desc + i, GFP_KERNEL, node); raw_spin_lock_init(&desc[i].lock);
desc_smp_init(desc + i, node);
lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
desc_set_defaults(i, &desc[i], node);
} }
return arch_early_irq_init(); return arch_early_irq_init();
} }
...@@ -346,6 +344,12 @@ irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node) ...@@ -346,6 +344,12 @@ irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node)
if (!cnt) if (!cnt)
return -EINVAL; return -EINVAL;
if (irq >= 0) {
if (from > irq)
return -EINVAL;
from = irq;
}
mutex_lock(&sparse_irq_lock); mutex_lock(&sparse_irq_lock);
start = bitmap_find_next_zero_area(allocated_irqs, IRQ_BITMAP_BITS, start = bitmap_find_next_zero_area(allocated_irqs, IRQ_BITMAP_BITS,
......
...@@ -723,13 +723,16 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { } ...@@ -723,13 +723,16 @@ irq_thread_check_affinity(struct irq_desc *desc, struct irqaction *action) { }
* context. So we need to disable bh here to avoid deadlocks and other * context. So we need to disable bh here to avoid deadlocks and other
* side effects. * side effects.
*/ */
static void static irqreturn_t
irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action) irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action)
{ {
irqreturn_t ret;
local_bh_disable(); 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); irq_finalize_oneshot(desc, action, false);
local_bh_enable(); local_bh_enable();
return ret;
} }
/* /*
...@@ -737,10 +740,14 @@ irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action) ...@@ -737,10 +740,14 @@ irq_forced_thread_fn(struct irq_desc *desc, struct irqaction *action)
* preemtible - many of them need to sleep and wait for slow busses to * preemtible - many of them need to sleep and wait for slow busses to
* complete. * 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); irq_finalize_oneshot(desc, action, false);
return ret;
} }
/* /*
...@@ -753,7 +760,8 @@ static int irq_thread(void *data) ...@@ -753,7 +760,8 @@ static int irq_thread(void *data)
}; };
struct irqaction *action = data; struct irqaction *action = data;
struct irq_desc *desc = irq_to_desc(action->irq); 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; int wake;
if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD, if (force_irqthreads & test_bit(IRQTF_FORCED_THREAD,
...@@ -783,8 +791,12 @@ static int irq_thread(void *data) ...@@ -783,8 +791,12 @@ static int irq_thread(void *data)
desc->istate |= IRQS_PENDING; desc->istate |= IRQS_PENDING;
raw_spin_unlock_irq(&desc->lock); raw_spin_unlock_irq(&desc->lock);
} else { } else {
irqreturn_t action_ret;
raw_spin_unlock_irq(&desc->lock); 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); wake = atomic_dec_and_test(&desc->threads_active);
......
...@@ -167,6 +167,13 @@ static void poll_spurious_irqs(unsigned long dummy) ...@@ -167,6 +167,13 @@ static void poll_spurious_irqs(unsigned long dummy)
jiffies + POLL_SPURIOUS_IRQ_INTERVAL); 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 * 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 * then assume that the IRQ is stuck in some manner. Drop a diagnostic
...@@ -182,7 +189,7 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc, ...@@ -182,7 +189,7 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc,
struct irqaction *action; struct irqaction *action;
unsigned long flags; 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", printk(KERN_ERR "irq event %d: bogus return value %x\n",
irq, action_ret); irq, action_ret);
} else { } else {
...@@ -201,10 +208,11 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc, ...@@ -201,10 +208,11 @@ __report_bad_irq(unsigned int irq, struct irq_desc *desc,
raw_spin_lock_irqsave(&desc->lock, flags); raw_spin_lock_irqsave(&desc->lock, flags);
action = desc->action; action = desc->action;
while (action) { while (action) {
printk(KERN_ERR "[<%p>]", action->handler); printk(KERN_ERR "[<%p>] %pf", action->handler, action->handler);
print_symbol(" (%s)", if (action->thread_fn)
(unsigned long)action->handler); printk(KERN_CONT " threaded [<%p>] %pf",
printk("\n"); action->thread_fn, action->thread_fn);
printk(KERN_CONT "\n");
action = action->next; action = action->next;
} }
raw_spin_unlock_irqrestore(&desc->lock, flags); raw_spin_unlock_irqrestore(&desc->lock, flags);
...@@ -262,7 +270,16 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, ...@@ -262,7 +270,16 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
if (desc->istate & IRQS_POLL_INPROGRESS) if (desc->istate & IRQS_POLL_INPROGRESS)
return; 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 * If we are seeing only the odd spurious IRQ caused by
* bus asynchronicity then don't eventually trigger an error, * bus asynchronicity then don't eventually trigger an error,
...@@ -274,8 +291,6 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc, ...@@ -274,8 +291,6 @@ void note_interrupt(unsigned int irq, struct irq_desc *desc,
else else
desc->irqs_unhandled++; desc->irqs_unhandled++;
desc->last_unhandled = jiffies; 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))) { if (unlikely(try_misrouted_irq(irq, desc, action_ret))) {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment