[media] s5p-mfc: fix a race in interrupt flags handling
authorPawel Osciak <posciak@chromium.org>
Tue, 21 Oct 2014 11:07:07 +0000 (08:07 -0300)
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>
Tue, 28 Oct 2014 17:54:11 +0000 (15:54 -0200)
Interrupt result flags have to be cleared before a hardware job is run.
Otherwise, if they are cleared asynchronously, we may end up clearing them
after the interrupt for which we wanted to wait has already arrived, thus
overwriting the job results that we intended to wait for.

To prevent this, clear the flags only under hw_lock and before running
a hardware job.

Signed-off-by: Pawel Osciak <posciak@chromium.org>
Signed-off-by: Kiran AVND <avnd.kiran@samsung.com>
Signed-off-by: Arun Kumar K <arun.kk@samsung.com>
Signed-off-by: Kamil Debski <k.debski@samsung.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v5.c
drivers/media/platform/s5p-mfc/s5p_mfc_opr_v6.c

index 6308150e638f7b006c169e59ca39141781e7ce71..40d8a03a141d339940960456773a65054284249e 100644 (file)
@@ -468,7 +468,6 @@ int s5p_mfc_open_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
        }
 
        set_work_bit_irqsave(ctx);
-       s5p_mfc_clean_ctx_int_flags(ctx);
        s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
        if (s5p_mfc_wait_for_done_ctx(ctx,
                S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) {
@@ -494,7 +493,6 @@ void s5p_mfc_close_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
 {
        ctx->state = MFCINST_RETURN_INST;
        set_work_bit_irqsave(ctx);
-       s5p_mfc_clean_ctx_int_flags(ctx);
        s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
        /* Wait until instance is returned or timeout occurred */
        if (s5p_mfc_wait_for_done_ctx(ctx,
index de90465dbc7afa522bf822d02afa6435ce30e2bc..74bcec8228eed98804c49ab0547dde9c89b71d00 100644 (file)
@@ -334,7 +334,6 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
                                                MFCINST_RES_CHANGE_END)) {
                /* If the MFC is parsing the header,
                 * so wait until it is finished */
-               s5p_mfc_clean_ctx_int_flags(ctx);
                s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET,
                                                                        0);
        }
@@ -746,7 +745,6 @@ static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl)
                        return -EINVAL;
                }
                /* Should wait for the header to be parsed */
-               s5p_mfc_clean_ctx_int_flags(ctx);
                s5p_mfc_wait_for_done_ctx(ctx,
                                S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
                if (ctx->state >= MFCINST_HEAD_PARSED &&
@@ -1058,7 +1056,6 @@ static void s5p_mfc_stop_streaming(struct vb2_queue *q)
                if (IS_MFCV6_PLUS(dev) && (ctx->state == MFCINST_RUNNING)) {
                        ctx->state = MFCINST_FLUSH;
                        set_work_bit_irqsave(ctx);
-                       s5p_mfc_clean_ctx_int_flags(ctx);
                        s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
                        if (s5p_mfc_wait_for_done_ctx(ctx,
                                S5P_MFC_R2H_CMD_DPB_FLUSH_RET, 0))
index 6a1c890a390d128a7e4299f4004bc36be53e5ed4..7f919e42b279b71a3318c4616b2f64c8156ded4b 100644 (file)
@@ -1663,7 +1663,6 @@ static int s5p_mfc_enc_g_v_ctrl(struct v4l2_ctrl *ctrl)
                        return -EINVAL;
                }
                /* Should wait for the header to be produced */
-               s5p_mfc_clean_ctx_int_flags(ctx);
                s5p_mfc_wait_for_done_ctx(ctx,
                                S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
                if (ctx->state >= MFCINST_HEAD_PARSED &&
index 7cf07963187dd33e254cc3d89db849f2ae877faf..0c4fcf2dfd09c68cd41e12481b44944a585a52fc 100644 (file)
@@ -1178,7 +1178,6 @@ static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx)
 
        s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
        dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
        s5p_mfc_decode_one_frame_v5(ctx, MFC_DEC_RES_CHANGE);
 }
 
@@ -1192,7 +1191,6 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
                last_frame = MFC_DEC_LAST_FRAME;
                s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
                dev->curr_ctx = ctx->num;
-               s5p_mfc_clean_ctx_int_flags(ctx);
                s5p_mfc_decode_one_frame_v5(ctx, last_frame);
                return 0;
        }
@@ -1212,7 +1210,6 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
                ctx->consumed_stream, temp_vb->b->v4l2_planes[0].bytesused);
        spin_unlock_irqrestore(&dev->irqlock, flags);
        dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
        if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
                last_frame = MFC_DEC_LAST_FRAME;
                mfc_debug(2, "Setting ctx->state to FINISHING\n");
@@ -1273,7 +1270,6 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
        s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
        spin_unlock_irqrestore(&dev->irqlock, flags);
        dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
        mfc_debug(2, "encoding buffer with index=%d state=%d\n",
                  src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state);
        s5p_mfc_encode_one_frame_v5(ctx);
@@ -1297,7 +1293,6 @@ static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
                                0, temp_vb->b->v4l2_planes[0].bytesused);
        spin_unlock_irqrestore(&dev->irqlock, flags);
        dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
        s5p_mfc_init_decode_v5(ctx);
 }
 
@@ -1317,7 +1312,6 @@ static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
        s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
        spin_unlock_irqrestore(&dev->irqlock, flags);
        dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
        s5p_mfc_init_encode_v5(ctx);
 }
 
@@ -1352,7 +1346,6 @@ static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
                                0, temp_vb->b->v4l2_planes[0].bytesused);
        spin_unlock_irqrestore(&dev->irqlock, flags);
        dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
        ret = s5p_mfc_set_dec_frame_buffer_v5(ctx);
        if (ret) {
                mfc_err("Failed to alloc frame mem\n");
@@ -1396,6 +1389,8 @@ static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
         * Now obtaining frames from MFC buffer
         */
        s5p_mfc_clock_on();
+       s5p_mfc_clean_ctx_int_flags(ctx);
+
        if (ctx->type == MFCINST_DECODER) {
                s5p_mfc_set_dec_desc_buffer(ctx);
                switch (ctx->state) {
@@ -1406,12 +1401,10 @@ static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
                        ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
                        break;
                case MFCINST_INIT:
-                       s5p_mfc_clean_ctx_int_flags(ctx);
                        ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
                                        ctx);
                        break;
                case MFCINST_RETURN_INST:
-                       s5p_mfc_clean_ctx_int_flags(ctx);
                        ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
                                        ctx);
                        break;
@@ -1444,12 +1437,10 @@ static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
                        ret = s5p_mfc_run_enc_frame(ctx);
                        break;
                case MFCINST_INIT:
-                       s5p_mfc_clean_ctx_int_flags(ctx);
                        ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
                                        ctx);
                        break;
                case MFCINST_RETURN_INST:
-                       s5p_mfc_clean_ctx_int_flags(ctx);
                        ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
                                        ctx);
                        break;
index 7b1cf736843ca62c1e4ea2ba7dfa2949d233b9f0..9aea179943cef37a5912a8bb04d2a39497d10fcd 100644 (file)
@@ -1394,7 +1394,6 @@ static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
 
        if (flush) {
                dev->curr_ctx = ctx->num;
-               s5p_mfc_clean_ctx_int_flags(ctx);
                writel(ctx->inst_no, mfc_regs->instance_id);
                s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev,
                                S5P_FIMV_H2R_CMD_FLUSH_V6, NULL);
@@ -1535,7 +1534,6 @@ static inline void s5p_mfc_run_dec_last_frames(struct s5p_mfc_ctx *ctx)
 
        s5p_mfc_set_dec_stream_buffer_v6(ctx, 0, 0, 0);
        dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
        s5p_mfc_decode_one_frame_v6(ctx, MFC_DEC_LAST_FRAME);
 }
 
@@ -1572,7 +1570,6 @@ static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
        spin_unlock_irqrestore(&dev->irqlock, flags);
 
        dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
        if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
                last_frame = 1;
                mfc_debug(2, "Setting ctx->state to FINISHING\n");
@@ -1629,7 +1626,6 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
        spin_unlock_irqrestore(&dev->irqlock, flags);
 
        dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
        s5p_mfc_encode_one_frame_v6(ctx);
 
        return 0;
@@ -1651,7 +1647,6 @@ static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
                        temp_vb->b->v4l2_planes[0].bytesused);
        spin_unlock_irqrestore(&dev->irqlock, flags);
        dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
        s5p_mfc_init_decode_v6(ctx);
 }
 
@@ -1671,7 +1666,6 @@ static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *ctx)
        s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
        spin_unlock_irqrestore(&dev->irqlock, flags);
        dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
        s5p_mfc_init_encode_v6(ctx);
 }
 
@@ -1691,7 +1685,6 @@ static inline int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
        }
 
        dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
        ret = s5p_mfc_set_dec_frame_buffer_v6(ctx);
        if (ret) {
                mfc_err("Failed to alloc frame mem.\n");
@@ -1706,7 +1699,6 @@ static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx)
        int ret;
 
        dev->curr_ctx = ctx->num;
-       s5p_mfc_clean_ctx_int_flags(ctx);
        ret = s5p_mfc_set_enc_ref_buffer_v6(ctx);
        if (ret) {
                mfc_err("Failed to alloc frame mem.\n");
@@ -1755,6 +1747,8 @@ static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
         * Now obtaining frames from MFC buffer */
 
        s5p_mfc_clock_on();
+       s5p_mfc_clean_ctx_int_flags(ctx);
+
        if (ctx->type == MFCINST_DECODER) {
                switch (ctx->state) {
                case MFCINST_FINISHING:
@@ -1764,12 +1758,10 @@ static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
                        ret = s5p_mfc_run_dec_frame(ctx);
                        break;
                case MFCINST_INIT:
-                       s5p_mfc_clean_ctx_int_flags(ctx);
                        ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
                                        ctx);
                        break;
                case MFCINST_RETURN_INST:
-                       s5p_mfc_clean_ctx_int_flags(ctx);
                        ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
                                        ctx);
                        break;