diff options
author | Felipe Balbi <balbi@ti.com> | 2011-06-30 05:51:06 -0400 |
---|---|---|
committer | Samuel Ortiz <sameo@linux.intel.com> | 2011-10-24 08:09:11 -0400 |
commit | 7750c9b0d24c78c1f6b10d9ce0508945f250e5b2 (patch) | |
tree | 4bcb661c8f9435fb1cf0ce7442e6f7eacba62dc8 /drivers/mfd | |
parent | 91e3569ff487784edd206de1b324507b5ecc8439 (diff) |
mfd: Drop the twl4030-irq kthread
... and use threaded IRQ infrastructure. Later
patches will come dropping both workqueues and
setting the nested thread flag.
Signed-off-by: Felipe Balbi <balbi@ti.com>
Reviewed-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Signed-off-by: Samuel Ortiz <sameo@linux.intel.com>
Diffstat (limited to 'drivers/mfd')
-rw-r--r-- | drivers/mfd/twl4030-irq.c | 94 |
1 files changed, 21 insertions, 73 deletions
diff --git a/drivers/mfd/twl4030-irq.c b/drivers/mfd/twl4030-irq.c index 291364c3943e..e1e0944af2e6 100644 --- a/drivers/mfd/twl4030-irq.c +++ b/drivers/mfd/twl4030-irq.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <linux/init.h> | 30 | #include <linux/init.h> |
31 | #include <linux/interrupt.h> | 31 | #include <linux/interrupt.h> |
32 | #include <linux/irq.h> | 32 | #include <linux/irq.h> |
33 | #include <linux/kthread.h> | ||
34 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
35 | 34 | ||
36 | #include <linux/i2c/twl.h> | 35 | #include <linux/i2c/twl.h> |
@@ -278,59 +277,6 @@ static const struct sih sih_modules_twl5031[8] = { | |||
278 | 277 | ||
279 | static unsigned twl4030_irq_base; | 278 | static unsigned twl4030_irq_base; |
280 | 279 | ||
281 | static struct completion irq_event; | ||
282 | |||
283 | /* | ||
284 | * This thread processes interrupts reported by the Primary Interrupt Handler. | ||
285 | */ | ||
286 | static int twl4030_irq_thread(void *data) | ||
287 | { | ||
288 | long irq = (long)data; | ||
289 | static unsigned i2c_errors; | ||
290 | static const unsigned max_i2c_errors = 100; | ||
291 | |||
292 | |||
293 | current->flags |= PF_NOFREEZE; | ||
294 | |||
295 | while (!kthread_should_stop()) { | ||
296 | int ret; | ||
297 | int module_irq; | ||
298 | u8 pih_isr; | ||
299 | |||
300 | /* Wait for IRQ, then read PIH irq status (also blocking) */ | ||
301 | wait_for_completion_interruptible(&irq_event); | ||
302 | |||
303 | ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr, | ||
304 | REG_PIH_ISR_P1); | ||
305 | if (ret) { | ||
306 | pr_warning("twl4030: I2C error %d reading PIH ISR\n", | ||
307 | ret); | ||
308 | if (++i2c_errors >= max_i2c_errors) { | ||
309 | printk(KERN_ERR "Maximum I2C error count" | ||
310 | " exceeded. Terminating %s.\n", | ||
311 | __func__); | ||
312 | break; | ||
313 | } | ||
314 | complete(&irq_event); | ||
315 | continue; | ||
316 | } | ||
317 | |||
318 | /* these handlers deal with the relevant SIH irq status */ | ||
319 | local_irq_disable(); | ||
320 | for (module_irq = twl4030_irq_base; | ||
321 | pih_isr; | ||
322 | pih_isr >>= 1, module_irq++) { | ||
323 | if (pih_isr & 0x1) | ||
324 | generic_handle_irq(module_irq); | ||
325 | } | ||
326 | local_irq_enable(); | ||
327 | |||
328 | enable_irq(irq); | ||
329 | } | ||
330 | |||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | /* | 280 | /* |
335 | * handle_twl4030_pih() is the desc->handle method for the twl4030 interrupt. | 281 | * handle_twl4030_pih() is the desc->handle method for the twl4030 interrupt. |
336 | * This is a chained interrupt, so there is no desc->action method for it. | 282 | * This is a chained interrupt, so there is no desc->action method for it. |
@@ -342,9 +288,25 @@ static int twl4030_irq_thread(void *data) | |||
342 | */ | 288 | */ |
343 | static irqreturn_t handle_twl4030_pih(int irq, void *devid) | 289 | static irqreturn_t handle_twl4030_pih(int irq, void *devid) |
344 | { | 290 | { |
345 | /* Acknowledge, clear *AND* mask the interrupt... */ | 291 | int module_irq; |
346 | disable_irq_nosync(irq); | 292 | irqreturn_t ret; |
347 | complete(devid); | 293 | u8 pih_isr; |
294 | |||
295 | ret = twl_i2c_read_u8(TWL4030_MODULE_PIH, &pih_isr, | ||
296 | REG_PIH_ISR_P1); | ||
297 | if (ret) { | ||
298 | pr_warning("twl4030: I2C error %d reading PIH ISR\n", ret); | ||
299 | return IRQ_NONE; | ||
300 | } | ||
301 | |||
302 | /* these handlers deal with the relevant SIH irq status */ | ||
303 | for (module_irq = twl4030_irq_base; | ||
304 | pih_isr; | ||
305 | pih_isr >>= 1, module_irq++) { | ||
306 | if (pih_isr & 0x1) | ||
307 | generic_handle_irq(module_irq); | ||
308 | } | ||
309 | |||
348 | return IRQ_HANDLED; | 310 | return IRQ_HANDLED; |
349 | } | 311 | } |
350 | /*----------------------------------------------------------------------*/ | 312 | /*----------------------------------------------------------------------*/ |
@@ -763,7 +725,6 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
763 | 725 | ||
764 | int status; | 726 | int status; |
765 | int i; | 727 | int i; |
766 | struct task_struct *task; | ||
767 | 728 | ||
768 | /* | 729 | /* |
769 | * Mask and clear all TWL4030 interrupts since initially we do | 730 | * Mask and clear all TWL4030 interrupts since initially we do |
@@ -806,27 +767,14 @@ int twl4030_init_irq(int irq_num, unsigned irq_base, unsigned irq_end) | |||
806 | } | 767 | } |
807 | 768 | ||
808 | /* install an irq handler to demultiplex the TWL4030 interrupt */ | 769 | /* install an irq handler to demultiplex the TWL4030 interrupt */ |
809 | 770 | status = request_threaded_irq(irq_num, NULL, handle_twl4030_pih, | |
810 | 771 | IRQF_DISABLED, "TWL4030-PIH", NULL); | |
811 | init_completion(&irq_event); | ||
812 | |||
813 | status = request_irq(irq_num, handle_twl4030_pih, IRQF_DISABLED, | ||
814 | "TWL4030-PIH", &irq_event); | ||
815 | if (status < 0) { | 772 | if (status < 0) { |
816 | pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status); | 773 | pr_err("twl4030: could not claim irq%d: %d\n", irq_num, status); |
817 | goto fail_rqirq; | 774 | goto fail_rqirq; |
818 | } | 775 | } |
819 | 776 | ||
820 | task = kthread_run(twl4030_irq_thread, (void *)(long)irq_num, | ||
821 | "twl4030-irq"); | ||
822 | if (IS_ERR(task)) { | ||
823 | pr_err("twl4030: could not create irq %d thread!\n", irq_num); | ||
824 | status = PTR_ERR(task); | ||
825 | goto fail_kthread; | ||
826 | } | ||
827 | return status; | 777 | return status; |
828 | fail_kthread: | ||
829 | free_irq(irq_num, &irq_event); | ||
830 | fail_rqirq: | 778 | fail_rqirq: |
831 | /* clean up twl4030_sih_setup */ | 779 | /* clean up twl4030_sih_setup */ |
832 | fail: | 780 | fail: |