summaryrefslogtreecommitdiff
path: root/drivers/staging/media/omap4iss/iss_csi2.c
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2015-11-10 01:01:57 +0300
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2015-11-19 16:14:23 +0300
commit769161fd2d90fc5b5304c73a0f2be7298c5ce430 (patch)
tree42dcee13e00f50ecfa526acdb41d433be6baecfc /drivers/staging/media/omap4iss/iss_csi2.c
parent425e186847971206981df9fce0c325655eb985b5 (diff)
downloadlinux-769161fd2d90fc5b5304c73a0f2be7298c5ce430.tar.xz
[media] media: omap4iss: csi2: Fix IRQ handling when stopping module
When stopping the CSI2 receiver the s_stream handler will wait for the IRQ handler to notice the stop request. The receiver, automatically disabled by the hardware after each frame, is then not reenabled by the IRQ handler as it returns immediately. As the IRQ handler check is performed before handling the context IRQ, the context IRQ source isn't cleared, and the CSI2 IRQ is then fired again immediately. The IRQ handler then fails to notice that the module is being stopped, processes the IRQ normally and reenables the CSI2 hardware. The problem goes unnoticed at stream stop time, but depending on the IRQ and s_stream scheduling timings, the CSI2 receiver can end up being hanged and will not produce any interrupt the next time it gets enabled, despite being soft-reset then. Fix this by checking for module stop after clearing the context IRQ source. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
Diffstat (limited to 'drivers/staging/media/omap4iss/iss_csi2.c')
-rw-r--r--drivers/staging/media/omap4iss/iss_csi2.c6
1 files changed, 3 insertions, 3 deletions
diff --git a/drivers/staging/media/omap4iss/iss_csi2.c b/drivers/staging/media/omap4iss/iss_csi2.c
index c6e6d47ac57f..b941035139ae 100644
--- a/drivers/staging/media/omap4iss/iss_csi2.c
+++ b/drivers/staging/media/omap4iss/iss_csi2.c
@@ -674,6 +674,9 @@ static void csi2_isr_ctx(struct iss_csi2_device *csi2,
status = iss_reg_read(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(n));
iss_reg_write(csi2->iss, csi2->regs1, CSI2_CTX_IRQSTATUS(n), status);
+ if (omap4iss_module_sync_is_stopping(&csi2->wait, &csi2->stopping))
+ return;
+
/* Propagate frame number */
if (status & CSI2_CTX_IRQ_FS) {
struct iss_pipeline *pipe =
@@ -776,9 +779,6 @@ void omap4iss_csi2_isr(struct iss_csi2_device *csi2)
pipe->error = true;
}
- if (omap4iss_module_sync_is_stopping(&csi2->wait, &csi2->stopping))
- return;
-
/* Successful cases */
if (csi2_irqstatus & CSI2_IRQ_CONTEXT0)
csi2_isr_ctx(csi2, &csi2->contexts[0]);