diff options
author | David Brownell <dbrownell@users.sourceforge.net> | 2008-10-08 18:30:11 -0400 |
---|---|---|
committer | Samuel Ortiz <samuel@sortiz.org> | 2008-10-19 16:54:11 -0400 |
commit | 9297a0e7e033b7f2776610197fcbb9ff563efe32 (patch) | |
tree | 669dea049a24ac9fc89d5506745fb386d620590f /drivers/mfd | |
parent | 26b8f5e1e2d1229c186d8e61d26513c43a058c5e (diff) |
mfd: twl4030-core irq simplification
Simplify twl4030 IRQ handling by removing a needless custom flow
handler. The top level IRQs, from the PIH, are well suited for
handle_simple_irq() ... they can't be acked or masked.
Switching resolves some issues with how IRQs were dispatched.
Notably, abuse of desc->status, IRQ accounting, and handling
of various faults.
In short, use standard genirq code.
Drivers that request_irq() to the PIH will need to pay more
attention to things like setting IRQF_DISABLED (since it's
no longer ignored), and making I2C calls from handlers (you'll
need a lockdep workaround).
Signed-off-by: David Brownell <dbrownell@users.sourceforge.net>
Signed-off-by: Tony Lindgren <tony@atomide.com>
Signed-off-by: Samuel Ortiz <sameo@openedhand.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/twl4030-core.c | 68 |
1 files changed, 2 insertions, 66 deletions
diff --git a/drivers/mfd/twl4030-core.c b/drivers/mfd/twl4030-core.c index 4af1624987c5..fd9a0160202c 100644 --- a/drivers/mfd/twl4030-core.c +++ b/drivers/mfd/twl4030-core.c | |||
@@ -535,68 +535,6 @@ EXPORT_SYMBOL(twl4030_i2c_read_u8); | |||
535 | 535 | ||
536 | /*----------------------------------------------------------------------*/ | 536 | /*----------------------------------------------------------------------*/ |
537 | 537 | ||
538 | /* | ||
539 | * do_twl4030_module_irq() is the desc->handle method for each of the twl4030 | ||
540 | * module interrupts that doesn't chain to another irq_chip (GPIO, power, etc). | ||
541 | * It executes in kernel thread context. On entry, cpu interrupts are disabled. | ||
542 | */ | ||
543 | static void do_twl4030_module_irq(unsigned int irq, irq_desc_t *desc) | ||
544 | { | ||
545 | struct irqaction *action; | ||
546 | const unsigned int cpu = smp_processor_id(); | ||
547 | |||
548 | /* | ||
549 | * Earlier this was desc->triggered = 1; | ||
550 | */ | ||
551 | desc->status |= IRQ_LEVEL; | ||
552 | |||
553 | /* | ||
554 | * The desc->handle method would normally call the desc->chip->ack | ||
555 | * method here, but we won't bother since our ack method is NULL. | ||
556 | */ | ||
557 | |||
558 | if (!desc->depth) { | ||
559 | kstat_cpu(cpu).irqs[irq]++; | ||
560 | |||
561 | action = desc->action; | ||
562 | if (action) { | ||
563 | int ret; | ||
564 | int status = 0; | ||
565 | int retval = 0; | ||
566 | |||
567 | local_irq_enable(); | ||
568 | |||
569 | do { | ||
570 | /* Call the ISR with cpu interrupts enabled */ | ||
571 | ret = action->handler(irq, action->dev_id); | ||
572 | if (ret == IRQ_HANDLED) | ||
573 | status |= action->flags; | ||
574 | retval |= ret; | ||
575 | action = action->next; | ||
576 | } while (action); | ||
577 | |||
578 | if (status & IRQF_SAMPLE_RANDOM) | ||
579 | add_interrupt_randomness(irq); | ||
580 | |||
581 | local_irq_disable(); | ||
582 | |||
583 | if (retval != IRQ_HANDLED) | ||
584 | printk(KERN_ERR "ISR for TWL4030 module" | ||
585 | " irq %d can't handle interrupt\n", | ||
586 | irq); | ||
587 | |||
588 | /* | ||
589 | * Here is where we should call the unmask method, but | ||
590 | * again we won't bother since it is NULL. | ||
591 | */ | ||
592 | } else | ||
593 | printk(KERN_CRIT "TWL4030 module irq %d has no ISR" | ||
594 | " but can't be masked!\n", irq); | ||
595 | } else | ||
596 | printk(KERN_CRIT "TWL4030 module irq %d is disabled but can't" | ||
597 | " be masked!\n", irq); | ||
598 | } | ||
599 | |||
600 | static unsigned twl4030_irq_base; | 538 | static unsigned twl4030_irq_base; |
601 | 539 | ||
602 | static struct completion irq_event; | 540 | static struct completion irq_event; |
@@ -611,7 +549,6 @@ static int twl4030_irq_thread(void *data) | |||
611 | static unsigned i2c_errors; | 549 | static unsigned i2c_errors; |
612 | const static unsigned max_i2c_errors = 100; | 550 | const static unsigned max_i2c_errors = 100; |
613 | 551 | ||
614 | daemonize("twl4030-irq"); | ||
615 | current->flags |= PF_NOFREEZE; | 552 | current->flags |= PF_NOFREEZE; |
616 | 553 | ||
617 | while (!kthread_should_stop()) { | 554 | while (!kthread_should_stop()) { |
@@ -691,8 +628,7 @@ static struct task_struct * __init start_twl4030_irq_thread(long irq) | |||
691 | struct task_struct *thread; | 628 | struct task_struct *thread; |
692 | 629 | ||
693 | init_completion(&irq_event); | 630 | init_completion(&irq_event); |
694 | thread = kthread_run(twl4030_irq_thread, (void *)irq, | 631 | thread = kthread_run(twl4030_irq_thread, (void *)irq, "twl4030-irq"); |
695 | "twl4030 irq %ld", irq); | ||
696 | if (!thread) | 632 | if (!thread) |
697 | pr_err("%s: could not create twl4030 irq %ld thread!\n", | 633 | pr_err("%s: could not create twl4030 irq %ld thread!\n", |
698 | DRIVER_NAME, irq); | 634 | DRIVER_NAME, irq); |
@@ -1126,7 +1062,7 @@ static void twl_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
1126 | /* install an irq handler for each of the PIH modules */ | 1062 | /* install an irq handler for each of the PIH modules */ |
1127 | for (i = irq_base; i < irq_end; i++) { | 1063 | for (i = irq_base; i < irq_end; i++) { |
1128 | set_irq_chip_and_handler(i, &twl4030_irq_chip, | 1064 | set_irq_chip_and_handler(i, &twl4030_irq_chip, |
1129 | do_twl4030_module_irq); | 1065 | handle_simple_irq); |
1130 | activate_irq(i); | 1066 | activate_irq(i); |
1131 | } | 1067 | } |
1132 | 1068 | ||