diff options
author | Heiner Kallweit <hkallweit1@gmail.com> | 2015-12-30 19:45:51 +0300 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@osg.samsung.com> | 2016-02-01 13:51:33 +0300 |
commit | d42fd29769f52c056032bbf1b9b2d1d914fd145a (patch) | |
tree | 6ed50b0f397471a2ae7604929af50dfa5a3cd131 /drivers/media/rc/nuvoton-cir.c | |
parent | 88205f01fe30590d04c81f09f003af8c2cf6aeaf (diff) | |
download | linux-d42fd29769f52c056032bbf1b9b2d1d914fd145a.tar.xz |
[media] media: rc: nuvoton-cir: fix interrupt handling
Only handle an interrupt if at least one combination of event bit
and related interrupt bit is set.
Previously it was just checked that at least one event bit and
at least one interrupt bit are set.
This fixes issues like the following which was caused by
interrupt sharing:
An interrupt intended for nvt_cir_isr was handled by nvt_cir_wake_isr
first and because status bit CIR_WAKE_IRSTS_IR_PENDING was set
the wake fifo was accidently cleared.
This patch also fixes the bug that nvt_cir_wake_isr returned IRQ_HANDLED
even if it detected that the (shared) interrupt was meant for another
handler.
Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Diffstat (limited to 'drivers/media/rc/nuvoton-cir.c')
-rw-r--r-- | drivers/media/rc/nuvoton-cir.c | 29 |
1 files changed, 12 insertions, 17 deletions
diff --git a/drivers/media/rc/nuvoton-cir.c b/drivers/media/rc/nuvoton-cir.c index 3097ff0eb176..291d870e618f 100644 --- a/drivers/media/rc/nuvoton-cir.c +++ b/drivers/media/rc/nuvoton-cir.c @@ -825,9 +825,13 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) * 0: CIR_IRSTS_GH - Min Length Detected */ status = nvt_cir_reg_read(nvt, CIR_IRSTS); - if (!status) { + iren = nvt_cir_reg_read(nvt, CIR_IREN); + + /* IRQ may be shared with CIR WAKE, therefore check for each + * status bit whether the related interrupt source is enabled + */ + if (!(status & iren)) { nvt_dbg_verbose("%s exiting, IRSTS 0x0", __func__); - nvt_cir_reg_write(nvt, 0xff, CIR_IRSTS); return IRQ_NONE; } @@ -835,13 +839,6 @@ static irqreturn_t nvt_cir_isr(int irq, void *data) nvt_cir_reg_write(nvt, status, CIR_IRSTS); nvt_cir_reg_write(nvt, 0, CIR_IRSTS); - /* Interrupt may be shared with CIR Wake, bail if CIR not enabled */ - iren = nvt_cir_reg_read(nvt, CIR_IREN); - if (!iren) { - nvt_dbg_verbose("%s exiting, CIR not enabled", __func__); - return IRQ_NONE; - } - nvt_cir_log_irqs(status, iren); if (status & CIR_IRSTS_RTR) { @@ -914,7 +911,12 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) nvt_dbg_wake("%s firing", __func__); status = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IRSTS); - if (!status) + iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); + + /* IRQ may be shared with CIR, therefore check for each + * status bit whether the related interrupt source is enabled + */ + if (!(status & iren)) return IRQ_NONE; if (status & CIR_WAKE_IRSTS_IR_PENDING) @@ -923,13 +925,6 @@ static irqreturn_t nvt_cir_wake_isr(int irq, void *data) nvt_cir_wake_reg_write(nvt, status, CIR_WAKE_IRSTS); nvt_cir_wake_reg_write(nvt, 0, CIR_WAKE_IRSTS); - /* Interrupt may be shared with CIR, bail if Wake not enabled */ - iren = nvt_cir_wake_reg_read(nvt, CIR_WAKE_IREN); - if (!iren) { - nvt_dbg_wake("%s exiting, wake not enabled", __func__); - return IRQ_HANDLED; - } - if ((status & CIR_WAKE_IRSTS_PE) && (nvt->wake_state == ST_WAKE_START)) { while (nvt_cir_wake_reg_read(nvt, CIR_WAKE_RD_FIFO_ONLY_IDX)) { |