diff options
author | NeilBrown <neilb@suse.de> | 2011-11-26 15:17:41 -0500 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2011-12-20 12:53:25 -0500 |
commit | c1e61bcf8269d3bc4390a363ad2e1bc1dc226bda (patch) | |
tree | f64a5a7937d1a98f4fbb4f5940e325dc03c79889 /drivers/mfd/twl4030-irq.c | |
parent | 286f8f3cd615177d5d0f8af8059a3fa39f51fa97 (diff) |
mfd: Use request_threaded_irq for twl4030-irq instead of irq_set_chained_handler
irq_set_chained_handler sets 'desc->handle_irq'.
However this irq is called by handle_nested_irq from handle_twl4030_pih,
and that uses action->thread_fn.
So the handled set with irq_set_chained_handler is never called.
So change to use request_threaded_irq instead - that sets the correct field.
Tested on GTA04 Phoenux.
Signed-off-by: NeilBrown <neilb@suse.de>
Tested-by: Felipe Contreras <felipe.contreras@gmail.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd/twl4030-irq.c')
-rw-r--r-- | drivers/mfd/twl4030-irq.c | 13 |
1 files changed, 8 insertions, 5 deletions
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index 3d3d6ed48f8d..29f11e0765fe 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c | |||
@@ -432,6 +432,7 @@ struct sih_agent { | |||
432 | u32 edge_change; | 432 | u32 edge_change; |
433 | 433 | ||
434 | struct mutex irq_lock; | 434 | struct mutex irq_lock; |
435 | char *irq_name; | ||
435 | }; | 436 | }; |
436 | 437 | ||
437 | /*----------------------------------------------------------------------*/ | 438 | /*----------------------------------------------------------------------*/ |
@@ -589,7 +590,7 @@ static inline int sih_read_isr(const struct sih *sih) | |||
589 | * Generic handler for SIH interrupts ... we "know" this is called | 590 | * Generic handler for SIH interrupts ... we "know" this is called |
590 | * in task context, with IRQs enabled. | 591 | * in task context, with IRQs enabled. |
591 | */ | 592 | */ |
592 | static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc) | 593 | static irqreturn_t handle_twl4030_sih(int irq, void *data) |
593 | { | 594 | { |
594 | struct sih_agent *agent = irq_get_handler_data(irq); | 595 | struct sih_agent *agent = irq_get_handler_data(irq); |
595 | const struct sih *sih = agent->sih; | 596 | const struct sih *sih = agent->sih; |
@@ -602,7 +603,7 @@ static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc) | |||
602 | pr_err("twl4030: %s SIH, read ISR error %d\n", | 603 | pr_err("twl4030: %s SIH, read ISR error %d\n", |
603 | sih->name, isr); | 604 | sih->name, isr); |
604 | /* REVISIT: recover; eventually mask it all, etc */ | 605 | /* REVISIT: recover; eventually mask it all, etc */ |
605 | return; | 606 | return IRQ_HANDLED; |
606 | } | 607 | } |
607 | 608 | ||
608 | while (isr) { | 609 | while (isr) { |
@@ -616,6 +617,7 @@ static void handle_twl4030_sih(unsigned irq, struct irq_desc *desc) | |||
616 | pr_err("twl4030: %s SIH, invalid ISR bit %d\n", | 617 | pr_err("twl4030: %s SIH, invalid ISR bit %d\n", |
617 | sih->name, irq); | 618 | sih->name, irq); |
618 | } | 619 | } |
620 | return IRQ_HANDLED; | ||
619 | } | 621 | } |
620 | 622 | ||
621 | static unsigned twl4030_irq_next; | 623 | static unsigned twl4030_irq_next; |
@@ -668,18 +670,19 @@ int twl4030_sih_setup(int module) | |||
668 | activate_irq(irq); | 670 | activate_irq(irq); |
669 | } | 671 | } |
670 | 672 | ||
671 | status = irq_base; | ||
672 | twl4030_irq_next += i; | 673 | twl4030_irq_next += i; |
673 | 674 | ||
674 | /* replace generic PIH handler (handle_simple_irq) */ | 675 | /* replace generic PIH handler (handle_simple_irq) */ |
675 | irq = sih_mod + twl4030_irq_base; | 676 | irq = sih_mod + twl4030_irq_base; |
676 | irq_set_handler_data(irq, agent); | 677 | irq_set_handler_data(irq, agent); |
677 | irq_set_chained_handler(irq, handle_twl4030_sih); | 678 | agent->irq_name = kasprintf(GFP_KERNEL, "twl4030_%s", sih->name); |
679 | status = request_threaded_irq(irq, NULL, handle_twl4030_sih, 0, | ||
680 | agent->irq_name ?: sih->name, NULL); | ||
678 | 681 | ||
679 | pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name, | 682 | pr_info("twl4030: %s (irq %d) chaining IRQs %d..%d\n", sih->name, |
680 | irq, irq_base, twl4030_irq_next - 1); | 683 | irq, irq_base, twl4030_irq_next - 1); |
681 | 684 | ||
682 | return status; | 685 | return status < 0 ? status : irq_base; |
683 | } | 686 | } |
684 | 687 | ||
685 | /* FIXME need a call to reverse twl4030_sih_setup() ... */ | 688 | /* FIXME need a call to reverse twl4030_sih_setup() ... */ |