[COMMON] media: smfc: handle exceptional situations
authorCho KyongHo <pullip.cho@samsung.com>
Wed, 1 Apr 2015 10:24:12 +0000 (19:24 +0900)
committerSeungchul Kim <sc377.kim@samsung.com>
Mon, 28 May 2018 05:30:52 +0000 (14:30 +0900)
The driver should be robust under very exceptional situations caused
by unexpected behaviors of processes. Some processes may be suddenly
killed without waiting for the completion of request task in the
driver or H/W. Another processes that is not well-designed so that
they can close the opened device node while forgeting to wait for
the completion of their requested tasks.
Even though processes works unexpectedly, SMFC driver now handles
all exceptional cases with waiting for the H/W's working before
releasing all resources referred by the driver. Other resources that
the driver does not care about is handled by the frameworks such as
videobuf2 and v4l2-mem2mem.

Change-Id: I5ec4c3d91a9328e163658b3732a5ab37de30e73c
Signed-off-by: Cho KyongHo <pullip.cho@samsung.com>
drivers/media/platform/exynos/smfc/smfc.c

index eacb32bf7b09f5361087de2ac928a368ac0b3dd0..b2ec853e32f96e60698a6c210a036f5671bde5ed 100644 (file)
@@ -277,14 +277,9 @@ static irqreturn_t exynos_smfc_irq_handler(int irq, void *priv)
        struct smfc_dev *smfc = priv;
        struct smfc_ctx *ctx = v4l2_m2m_get_curr_priv(smfc->m2mdev);
        enum vb2_buffer_state state = VB2_BUF_STATE_DONE;
-       struct vb2_v4l2_buffer *vb_capture;
+       u32 streamsize = smfc_get_streamsize(smfc);
 
-       vb_capture = v4l2_m2m_dst_buf_remove(ctx->m2mctx);
-
-       if (smfc_hwstatus_okay(smfc)) {
-               vb2_set_plane_payload(&vb_capture->vb2_buf, 0,
-                                     smfc_get_streamsize(smfc));
-       } else {
+       if (!smfc_hwstatus_okay(smfc)) {
                state = VB2_BUF_STATE_ERROR;
                smfc_hwconfigure_reset(smfc);
        }
@@ -297,9 +292,18 @@ static irqreturn_t exynos_smfc_irq_handler(int irq, void *priv)
 
        pm_runtime_put(smfc->dev);
 
-       v4l2_m2m_buf_done(v4l2_m2m_src_buf_remove(ctx->m2mctx), state);
-       v4l2_m2m_buf_done(vb_capture, state);
-       v4l2_m2m_job_finish(smfc->m2mdev, ctx->m2mctx);
+       /* ctx is NULL if streamoff is called before (de)compression finishes */
+       if (ctx) {
+               struct vb2_v4l2_buffer *vb_capture =
+                               v4l2_m2m_dst_buf_remove(ctx->m2mctx);
+
+               vb2_set_plane_payload(&vb_capture->vb2_buf, 0, streamsize);
+               v4l2_m2m_buf_done(v4l2_m2m_src_buf_remove(ctx->m2mctx), state);
+               v4l2_m2m_buf_done(vb_capture, state);
+               v4l2_m2m_job_finish(smfc->m2mdev, ctx->m2mctx);
+       } else {
+               dev_err(smfc->dev, "Spurious interrupt on H/W JPEG occurred\n");
+       }
 
        return IRQ_HANDLED;
 }
@@ -377,6 +381,11 @@ static void smfc_vb2_unlock(struct vb2_queue *vq)
        mutex_unlock(&ctx->smfc->video_device_mutex);
 }
 
+static void smfc_vb2_stop_streaming(struct vb2_queue *vq)
+{
+       vb2_wait_for_all_buffers(vq);
+}
+
 static struct vb2_ops smfc_vb2_ops = {
        .queue_setup    = smfc_vb2_queue_setup,
        .buf_prepare    = smfc_vb2_buf_prepare,
@@ -384,6 +393,7 @@ static struct vb2_ops smfc_vb2_ops = {
        .buf_queue      = smfc_vb2_buf_queue,
        .wait_finish    = smfc_vb2_lock,
        .wait_prepare   = smfc_vb2_unlock,
+       .stop_streaming = smfc_vb2_stop_streaming,
 };
 
 static int smfc_queue_init(void *priv, struct vb2_queue *src_vq,
@@ -914,7 +924,7 @@ static void smfc_m2m_device_run(void *priv)
 
 static void smfc_m2m_job_abort(void *priv)
 {
-       /* TODO: aborting next job */
+       /* nothing to do */
 }
 
 static struct v4l2_m2m_ops smfc_m2m_ops = {