diff options
-rw-r--r-- | include/linux/interrupt.h | 2 | ||||
-rw-r--r-- | kernel/irq/handle.c | 29 | ||||
-rw-r--r-- | kernel/irq/manage.c | 17 |
3 files changed, 33 insertions, 15 deletions
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h index dbf6a6fd116c..266a5f5f57cc 100644 --- a/include/linux/interrupt.h +++ b/include/linux/interrupt.h | |||
@@ -63,10 +63,12 @@ | |||
63 | * Bits used by threaded handlers: | 63 | * Bits used by threaded handlers: |
64 | * IRQTF_RUNTHREAD - signals that the interrupt handler thread should run | 64 | * IRQTF_RUNTHREAD - signals that the interrupt handler thread should run |
65 | * IRQTF_DIED - handler thread died | 65 | * IRQTF_DIED - handler thread died |
66 | * IRQTF_WARNED - warning "IRQ_WAKE_THREAD w/o thread_fn" has been printed | ||
66 | */ | 67 | */ |
67 | enum { | 68 | enum { |
68 | IRQTF_RUNTHREAD, | 69 | IRQTF_RUNTHREAD, |
69 | IRQTF_DIED, | 70 | IRQTF_DIED, |
71 | IRQTF_WARNED, | ||
70 | }; | 72 | }; |
71 | 73 | ||
72 | typedef irqreturn_t (*irq_handler_t)(int, void *); | 74 | typedef irqreturn_t (*irq_handler_t)(int, void *); |
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c index fe8f45374e86..38b49a9e508a 100644 --- a/kernel/irq/handle.c +++ b/kernel/irq/handle.c | |||
@@ -338,6 +338,15 @@ irqreturn_t no_action(int cpl, void *dev_id) | |||
338 | return IRQ_NONE; | 338 | return IRQ_NONE; |
339 | } | 339 | } |
340 | 340 | ||
341 | static void warn_no_thread(unsigned int irq, struct irqaction *action) | ||
342 | { | ||
343 | if (test_and_set_bit(IRQTF_WARNED, &action->thread_flags)) | ||
344 | return; | ||
345 | |||
346 | printk(KERN_WARNING "IRQ %d device %s returned IRQ_WAKE_THREAD " | ||
347 | "but no thread function available.", irq, action->name); | ||
348 | } | ||
349 | |||
341 | /** | 350 | /** |
342 | * handle_IRQ_event - irq action chain handler | 351 | * handle_IRQ_event - irq action chain handler |
343 | * @irq: the interrupt number | 352 | * @irq: the interrupt number |
@@ -361,6 +370,21 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) | |||
361 | switch (ret) { | 370 | switch (ret) { |
362 | case IRQ_WAKE_THREAD: | 371 | case IRQ_WAKE_THREAD: |
363 | /* | 372 | /* |
373 | * Set result to handled so the spurious check | ||
374 | * does not trigger. | ||
375 | */ | ||
376 | ret = IRQ_HANDLED; | ||
377 | |||
378 | /* | ||
379 | * Catch drivers which return WAKE_THREAD but | ||
380 | * did not set up a thread function | ||
381 | */ | ||
382 | if (unlikely(!action->thread_fn)) { | ||
383 | warn_no_thread(irq, action); | ||
384 | break; | ||
385 | } | ||
386 | |||
387 | /* | ||
364 | * Wake up the handler thread for this | 388 | * Wake up the handler thread for this |
365 | * action. In case the thread crashed and was | 389 | * action. In case the thread crashed and was |
366 | * killed we just pretend that we handled the | 390 | * killed we just pretend that we handled the |
@@ -374,11 +398,6 @@ irqreturn_t handle_IRQ_event(unsigned int irq, struct irqaction *action) | |||
374 | wake_up_process(action->thread); | 398 | wake_up_process(action->thread); |
375 | } | 399 | } |
376 | 400 | ||
377 | /* | ||
378 | * Set it to handled so the spurious check | ||
379 | * does not trigger. | ||
380 | */ | ||
381 | ret = IRQ_HANDLED; | ||
382 | /* Fall through to add to randomness */ | 401 | /* Fall through to add to randomness */ |
383 | case IRQ_HANDLED: | 402 | case IRQ_HANDLED: |
384 | status |= action->flags; | 403 | status |= action->flags; |
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index a4c1ab86cd25..a3eb7baf1e46 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
@@ -407,20 +407,17 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq, | |||
407 | return ret; | 407 | return ret; |
408 | } | 408 | } |
409 | 409 | ||
410 | static inline int irq_thread_should_run(struct irqaction *action) | ||
411 | { | ||
412 | return test_and_clear_bit(IRQTF_RUNTHREAD, &action->thread_flags); | ||
413 | } | ||
414 | |||
415 | static int irq_wait_for_interrupt(struct irqaction *action) | 410 | static int irq_wait_for_interrupt(struct irqaction *action) |
416 | { | 411 | { |
417 | while (!kthread_should_stop()) { | 412 | while (!kthread_should_stop()) { |
418 | set_current_state(TASK_INTERRUPTIBLE); | 413 | set_current_state(TASK_INTERRUPTIBLE); |
419 | if (irq_thread_should_run(action)) { | 414 | |
415 | if (test_and_clear_bit(IRQTF_RUNTHREAD, | ||
416 | &action->thread_flags)) { | ||
420 | __set_current_state(TASK_RUNNING); | 417 | __set_current_state(TASK_RUNNING); |
421 | return 0; | 418 | return 0; |
422 | } else | 419 | } |
423 | schedule(); | 420 | schedule(); |
424 | } | 421 | } |
425 | return -1; | 422 | return -1; |
426 | } | 423 | } |
@@ -820,8 +817,8 @@ EXPORT_SYMBOL(free_irq); | |||
820 | * @irq: Interrupt line to allocate | 817 | * @irq: Interrupt line to allocate |
821 | * @handler: Function to be called when the IRQ occurs. | 818 | * @handler: Function to be called when the IRQ occurs. |
822 | * Primary handler for threaded interrupts | 819 | * Primary handler for threaded interrupts |
823 | * @thread_fn: Function called from the irq handler thread | 820 | * @thread_fn: Function called from the irq handler thread |
824 | * If NULL, no irq thread is created | 821 | * If NULL, no irq thread is created |
825 | * @irqflags: Interrupt type flags | 822 | * @irqflags: Interrupt type flags |
826 | * @devname: An ascii name for the claiming device | 823 | * @devname: An ascii name for the claiming device |
827 | * @dev_id: A cookie passed back to the handler function | 824 | * @dev_id: A cookie passed back to the handler function |