aboutsummaryrefslogtreecommitdiffstats
path: root/kernel/irq/manage.c
diff options
context:
space:
mode:
Diffstat (limited to 'kernel/irq/manage.c')
-rw-r--r--kernel/irq/manage.c49
1 files changed, 45 insertions, 4 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c
index d222515a5a06..d7f7b5fd2476 100644
--- a/kernel/irq/manage.c
+++ b/kernel/irq/manage.c
@@ -436,6 +436,16 @@ int __irq_set_trigger(struct irq_desc *desc, unsigned int irq,
436 return ret; 436 return ret;
437} 437}
438 438
439/*
440 * Default primary interrupt handler for threaded interrupts. Is
441 * assigned as primary handler when request_threaded_irq is called
442 * with handler == NULL. Useful for oneshot interrupts.
443 */
444static irqreturn_t irq_default_primary_handler(int irq, void *dev_id)
445{
446 return IRQ_WAKE_THREAD;
447}
448
439static int irq_wait_for_interrupt(struct irqaction *action) 449static int irq_wait_for_interrupt(struct irqaction *action)
440{ 450{
441 while (!kthread_should_stop()) { 451 while (!kthread_should_stop()) {
@@ -451,6 +461,21 @@ static int irq_wait_for_interrupt(struct irqaction *action)
451 return -1; 461 return -1;
452} 462}
453 463
464/*
465 * Oneshot interrupts keep the irq line masked until the threaded
466 * handler finished. unmask if the interrupt has not been disabled and
467 * is marked MASKED.
468 */
469static void irq_finalize_oneshot(unsigned int irq, struct irq_desc *desc)
470{
471 spin_lock_irq(&desc->lock);
472 if (!(desc->status & IRQ_DISABLED) && (desc->status & IRQ_MASKED)) {
473 desc->status &= ~IRQ_MASKED;
474 desc->chip->unmask(irq);
475 }
476 spin_unlock_irq(&desc->lock);
477}
478
454#ifdef CONFIG_SMP 479#ifdef CONFIG_SMP
455/* 480/*
456 * Check whether we need to change the affinity of the interrupt thread. 481 * Check whether we need to change the affinity of the interrupt thread.
@@ -492,7 +517,7 @@ static int irq_thread(void *data)
492 struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO/2, }; 517 struct sched_param param = { .sched_priority = MAX_USER_RT_PRIO/2, };
493 struct irqaction *action = data; 518 struct irqaction *action = data;
494 struct irq_desc *desc = irq_to_desc(action->irq); 519 struct irq_desc *desc = irq_to_desc(action->irq);
495 int wake; 520 int wake, oneshot = desc->status & IRQ_ONESHOT;
496 521
497 sched_setscheduler(current, SCHED_FIFO, &param); 522 sched_setscheduler(current, SCHED_FIFO, &param);
498 current->irqaction = action; 523 current->irqaction = action;
@@ -518,6 +543,9 @@ static int irq_thread(void *data)
518 spin_unlock_irq(&desc->lock); 543 spin_unlock_irq(&desc->lock);
519 544
520 action->thread_fn(action->irq, action->dev_id); 545 action->thread_fn(action->irq, action->dev_id);
546
547 if (oneshot)
548 irq_finalize_oneshot(action->irq, desc);
521 } 549 }
522 550
523 wake = atomic_dec_and_test(&desc->threads_active); 551 wake = atomic_dec_and_test(&desc->threads_active);
@@ -590,6 +618,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
590 rand_initialize_irq(irq); 618 rand_initialize_irq(irq);
591 } 619 }
592 620
621 /* Oneshot interrupts are not allowed with shared */
622 if ((new->flags & IRQF_ONESHOT) && (new->flags & IRQF_SHARED))
623 return -EINVAL;
624
593 /* 625 /*
594 * Threaded handler ? 626 * Threaded handler ?
595 */ 627 */
@@ -663,9 +695,12 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
663 desc->status |= IRQ_PER_CPU; 695 desc->status |= IRQ_PER_CPU;
664#endif 696#endif
665 697
666 desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | 698 desc->status &= ~(IRQ_AUTODETECT | IRQ_WAITING | IRQ_ONESHOT |
667 IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED); 699 IRQ_INPROGRESS | IRQ_SPURIOUS_DISABLED);
668 700
701 if (new->flags & IRQF_ONESHOT)
702 desc->status |= IRQ_ONESHOT;
703
669 if (!(desc->status & IRQ_NOAUTOEN)) { 704 if (!(desc->status & IRQ_NOAUTOEN)) {
670 desc->depth = 0; 705 desc->depth = 0;
671 desc->status &= ~IRQ_DISABLED; 706 desc->status &= ~IRQ_DISABLED;
@@ -878,6 +913,8 @@ EXPORT_SYMBOL(free_irq);
878 * @irq: Interrupt line to allocate 913 * @irq: Interrupt line to allocate
879 * @handler: Function to be called when the IRQ occurs. 914 * @handler: Function to be called when the IRQ occurs.
880 * Primary handler for threaded interrupts 915 * Primary handler for threaded interrupts
916 * If NULL and thread_fn != NULL the default
917 * primary handler is installed
881 * @thread_fn: Function called from the irq handler thread 918 * @thread_fn: Function called from the irq handler thread
882 * If NULL, no irq thread is created 919 * If NULL, no irq thread is created
883 * @irqflags: Interrupt type flags 920 * @irqflags: Interrupt type flags
@@ -957,8 +994,12 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler,
957 994
958 if (desc->status & IRQ_NOREQUEST) 995 if (desc->status & IRQ_NOREQUEST)
959 return -EINVAL; 996 return -EINVAL;
960 if (!handler) 997
961 return -EINVAL; 998 if (!handler) {
999 if (!thread_fn)
1000 return -EINVAL;
1001 handler = irq_default_primary_handler;
1002 }
962 1003
963 action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); 1004 action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
964 if (!action) 1005 if (!action)