Commit f2035364 authored by Pawel Osciak's avatar Pawel Osciak Committed by Mauro Carvalho Chehab

[media] s5p-mfc: fix a race in interrupt flags handling

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: default avatarPawel Osciak <posciak@chromium.org>
Signed-off-by: default avatarKiran AVND <avnd.kiran@samsung.com>
Signed-off-by: default avatarArun Kumar K <arun.kk@samsung.com>
Signed-off-by: default avatarKamil Debski <k.debski@samsung.com>
Signed-off-by: default avatarMauro Carvalho Chehab <mchehab@osg.samsung.com>
parent 9841dde5
...@@ -468,7 +468,6 @@ int s5p_mfc_open_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx) ...@@ -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); set_work_bit_irqsave(ctx);
s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
if (s5p_mfc_wait_for_done_ctx(ctx, if (s5p_mfc_wait_for_done_ctx(ctx,
S5P_MFC_R2H_CMD_OPEN_INSTANCE_RET, 0)) { 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) ...@@ -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; ctx->state = MFCINST_RETURN_INST;
set_work_bit_irqsave(ctx); set_work_bit_irqsave(ctx);
s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
/* Wait until instance is returned or timeout occurred */ /* Wait until instance is returned or timeout occurred */
if (s5p_mfc_wait_for_done_ctx(ctx, if (s5p_mfc_wait_for_done_ctx(ctx,
......
...@@ -334,7 +334,6 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f) ...@@ -334,7 +334,6 @@ static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
MFCINST_RES_CHANGE_END)) { MFCINST_RES_CHANGE_END)) {
/* If the MFC is parsing the header, /* If the MFC is parsing the header,
* so wait until it is finished */ * 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, s5p_mfc_wait_for_done_ctx(ctx, S5P_MFC_R2H_CMD_SEQ_DONE_RET,
0); 0);
} }
...@@ -746,7 +745,6 @@ static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl) ...@@ -746,7 +745,6 @@ static int s5p_mfc_dec_g_v_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL; return -EINVAL;
} }
/* Should wait for the header to be parsed */ /* Should wait for the header to be parsed */
s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_wait_for_done_ctx(ctx, s5p_mfc_wait_for_done_ctx(ctx,
S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0); S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
if (ctx->state >= MFCINST_HEAD_PARSED && if (ctx->state >= MFCINST_HEAD_PARSED &&
...@@ -1058,7 +1056,6 @@ static void s5p_mfc_stop_streaming(struct vb2_queue *q) ...@@ -1058,7 +1056,6 @@ static void s5p_mfc_stop_streaming(struct vb2_queue *q)
if (IS_MFCV6_PLUS(dev) && (ctx->state == MFCINST_RUNNING)) { if (IS_MFCV6_PLUS(dev) && (ctx->state == MFCINST_RUNNING)) {
ctx->state = MFCINST_FLUSH; ctx->state = MFCINST_FLUSH;
set_work_bit_irqsave(ctx); set_work_bit_irqsave(ctx);
s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev); s5p_mfc_hw_call_void(dev->mfc_ops, try_run, dev);
if (s5p_mfc_wait_for_done_ctx(ctx, if (s5p_mfc_wait_for_done_ctx(ctx,
S5P_MFC_R2H_CMD_DPB_FLUSH_RET, 0)) S5P_MFC_R2H_CMD_DPB_FLUSH_RET, 0))
......
...@@ -1663,7 +1663,6 @@ static int s5p_mfc_enc_g_v_ctrl(struct v4l2_ctrl *ctrl) ...@@ -1663,7 +1663,6 @@ static int s5p_mfc_enc_g_v_ctrl(struct v4l2_ctrl *ctrl)
return -EINVAL; return -EINVAL;
} }
/* Should wait for the header to be produced */ /* Should wait for the header to be produced */
s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_wait_for_done_ctx(ctx, s5p_mfc_wait_for_done_ctx(ctx,
S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0); S5P_MFC_R2H_CMD_SEQ_DONE_RET, 0);
if (ctx->state >= MFCINST_HEAD_PARSED && if (ctx->state >= MFCINST_HEAD_PARSED &&
......
...@@ -1178,7 +1178,6 @@ static void s5p_mfc_run_res_change(struct s5p_mfc_ctx *ctx) ...@@ -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); s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_decode_one_frame_v5(ctx, MFC_DEC_RES_CHANGE); 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) ...@@ -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; last_frame = MFC_DEC_LAST_FRAME;
s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0); s5p_mfc_set_dec_stream_buffer_v5(ctx, 0, 0, 0);
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_decode_one_frame_v5(ctx, last_frame); s5p_mfc_decode_one_frame_v5(ctx, last_frame);
return 0; return 0;
} }
...@@ -1212,7 +1210,6 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame) ...@@ -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); ctx->consumed_stream, temp_vb->b->v4l2_planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags); spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx);
if (temp_vb->b->v4l2_planes[0].bytesused == 0) { if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
last_frame = MFC_DEC_LAST_FRAME; last_frame = MFC_DEC_LAST_FRAME;
mfc_debug(2, "Setting ctx->state to FINISHING\n"); 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) ...@@ -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); s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags); spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx);
mfc_debug(2, "encoding buffer with index=%d state=%d\n", mfc_debug(2, "encoding buffer with index=%d state=%d\n",
src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state); src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state);
s5p_mfc_encode_one_frame_v5(ctx); s5p_mfc_encode_one_frame_v5(ctx);
...@@ -1297,7 +1293,6 @@ static void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *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); 0, temp_vb->b->v4l2_planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags); spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_init_decode_v5(ctx); s5p_mfc_init_decode_v5(ctx);
} }
...@@ -1317,7 +1312,6 @@ static void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *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); s5p_mfc_set_enc_stream_buffer_v5(ctx, dst_addr, dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags); spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_init_encode_v5(ctx); s5p_mfc_init_encode_v5(ctx);
} }
...@@ -1352,7 +1346,6 @@ static int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *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); 0, temp_vb->b->v4l2_planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags); spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_set_dec_frame_buffer_v5(ctx); ret = s5p_mfc_set_dec_frame_buffer_v5(ctx);
if (ret) { if (ret) {
mfc_err("Failed to alloc frame mem\n"); mfc_err("Failed to alloc frame mem\n");
...@@ -1396,6 +1389,8 @@ static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev) ...@@ -1396,6 +1389,8 @@ static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
* Now obtaining frames from MFC buffer * Now obtaining frames from MFC buffer
*/ */
s5p_mfc_clock_on(); s5p_mfc_clock_on();
s5p_mfc_clean_ctx_int_flags(ctx);
if (ctx->type == MFCINST_DECODER) { if (ctx->type == MFCINST_DECODER) {
s5p_mfc_set_dec_desc_buffer(ctx); s5p_mfc_set_dec_desc_buffer(ctx);
switch (ctx->state) { switch (ctx->state) {
...@@ -1406,12 +1401,10 @@ static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev) ...@@ -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); ret = s5p_mfc_run_dec_frame(ctx, MFC_DEC_FRAME);
break; break;
case MFCINST_INIT: case MFCINST_INIT:
s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd, ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
ctx); ctx);
break; break;
case MFCINST_RETURN_INST: case MFCINST_RETURN_INST:
s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd, ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
ctx); ctx);
break; break;
...@@ -1444,12 +1437,10 @@ static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev) ...@@ -1444,12 +1437,10 @@ static void s5p_mfc_try_run_v5(struct s5p_mfc_dev *dev)
ret = s5p_mfc_run_enc_frame(ctx); ret = s5p_mfc_run_enc_frame(ctx);
break; break;
case MFCINST_INIT: case MFCINST_INIT:
s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd, ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
ctx); ctx);
break; break;
case MFCINST_RETURN_INST: case MFCINST_RETURN_INST:
s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd, ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
ctx); ctx);
break; break;
......
...@@ -1394,7 +1394,6 @@ static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush) ...@@ -1394,7 +1394,6 @@ static inline void s5p_mfc_set_flush(struct s5p_mfc_ctx *ctx, int flush)
if (flush) { if (flush) {
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx);
writel(ctx->inst_no, mfc_regs->instance_id); writel(ctx->inst_no, mfc_regs->instance_id);
s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev, s5p_mfc_hw_call_void(dev->mfc_cmds, cmd_host2risc, dev,
S5P_FIMV_H2R_CMD_FLUSH_V6, NULL); 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) ...@@ -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); s5p_mfc_set_dec_stream_buffer_v6(ctx, 0, 0, 0);
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_decode_one_frame_v6(ctx, MFC_DEC_LAST_FRAME); 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) ...@@ -1572,7 +1570,6 @@ static inline int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx)
spin_unlock_irqrestore(&dev->irqlock, flags); spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx);
if (temp_vb->b->v4l2_planes[0].bytesused == 0) { if (temp_vb->b->v4l2_planes[0].bytesused == 0) {
last_frame = 1; last_frame = 1;
mfc_debug(2, "Setting ctx->state to FINISHING\n"); 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) ...@@ -1629,7 +1626,6 @@ static inline int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
spin_unlock_irqrestore(&dev->irqlock, flags); spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_encode_one_frame_v6(ctx); s5p_mfc_encode_one_frame_v6(ctx);
return 0; return 0;
...@@ -1651,7 +1647,6 @@ static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx) ...@@ -1651,7 +1647,6 @@ static inline void s5p_mfc_run_init_dec(struct s5p_mfc_ctx *ctx)
temp_vb->b->v4l2_planes[0].bytesused); temp_vb->b->v4l2_planes[0].bytesused);
spin_unlock_irqrestore(&dev->irqlock, flags); spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_init_decode_v6(ctx); s5p_mfc_init_decode_v6(ctx);
} }
...@@ -1671,7 +1666,6 @@ static inline void s5p_mfc_run_init_enc(struct s5p_mfc_ctx *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); s5p_mfc_set_enc_stream_buffer_v6(ctx, dst_addr, dst_size);
spin_unlock_irqrestore(&dev->irqlock, flags); spin_unlock_irqrestore(&dev->irqlock, flags);
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx);
s5p_mfc_init_encode_v6(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) ...@@ -1691,7 +1685,6 @@ static inline int s5p_mfc_run_init_dec_buffers(struct s5p_mfc_ctx *ctx)
} }
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_set_dec_frame_buffer_v6(ctx); ret = s5p_mfc_set_dec_frame_buffer_v6(ctx);
if (ret) { if (ret) {
mfc_err("Failed to alloc frame mem.\n"); 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) ...@@ -1706,7 +1699,6 @@ static inline int s5p_mfc_run_init_enc_buffers(struct s5p_mfc_ctx *ctx)
int ret; int ret;
dev->curr_ctx = ctx->num; dev->curr_ctx = ctx->num;
s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_set_enc_ref_buffer_v6(ctx); ret = s5p_mfc_set_enc_ref_buffer_v6(ctx);
if (ret) { if (ret) {
mfc_err("Failed to alloc frame mem.\n"); mfc_err("Failed to alloc frame mem.\n");
...@@ -1755,6 +1747,8 @@ static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev) ...@@ -1755,6 +1747,8 @@ static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
* Now obtaining frames from MFC buffer */ * Now obtaining frames from MFC buffer */
s5p_mfc_clock_on(); s5p_mfc_clock_on();
s5p_mfc_clean_ctx_int_flags(ctx);
if (ctx->type == MFCINST_DECODER) { if (ctx->type == MFCINST_DECODER) {
switch (ctx->state) { switch (ctx->state) {
case MFCINST_FINISHING: case MFCINST_FINISHING:
...@@ -1764,12 +1758,10 @@ static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev) ...@@ -1764,12 +1758,10 @@ static void s5p_mfc_try_run_v6(struct s5p_mfc_dev *dev)
ret = s5p_mfc_run_dec_frame(ctx); ret = s5p_mfc_run_dec_frame(ctx);
break; break;
case MFCINST_INIT: case MFCINST_INIT:
s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd, ret = s5p_mfc_hw_call(dev->mfc_cmds, open_inst_cmd,
ctx); ctx);
break; break;
case MFCINST_RETURN_INST: case MFCINST_RETURN_INST:
s5p_mfc_clean_ctx_int_flags(ctx);
ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd, ret = s5p_mfc_hw_call(dev->mfc_cmds, close_inst_cmd,
ctx); ctx);
break; break;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment