Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

David Brownell and committed by
Samuel Ortiz
9297a0e7 26b8f5e1

+2 -66
+2 -66
drivers/mfd/twl4030-core.c
··· 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 538 static unsigned twl4030_irq_base; 601 539 602 540 static struct completion irq_event; ··· 549 611 static unsigned i2c_errors; 550 612 const static unsigned max_i2c_errors = 100; 551 613 552 - daemonize("twl4030-irq"); 553 614 current->flags |= PF_NOFREEZE; 554 615 555 616 while (!kthread_should_stop()) { ··· 628 691 struct task_struct *thread; 629 692 630 693 init_completion(&irq_event); 631 - thread = kthread_run(twl4030_irq_thread, (void *)irq, 632 - "twl4030 irq %ld", irq); 694 + thread = kthread_run(twl4030_irq_thread, (void *)irq, "twl4030-irq"); 633 695 if (!thread) 634 696 pr_err("%s: could not create twl4030 irq %ld thread!\n", 635 697 DRIVER_NAME, irq); ··· 1062 1126 /* install an irq handler for each of the PIH modules */ 1063 1127 for (i = irq_base; i < irq_end; i++) { 1064 1128 set_irq_chip_and_handler(i, &twl4030_irq_chip, 1065 - do_twl4030_module_irq); 1129 + handle_simple_irq); 1066 1130 activate_irq(i); 1067 1131 } 1068 1132