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

[media] s5p-mfc: Don't allocate codec buffers on STREAMON

Currently, we allocate private codec buffers on STREAMON, which may fail
if we are out of memory. We don't check for failure though, which will
make us crash with the codec accessing random memory.

We shouldn't be failing STREAMON with out of memory errors though. So move
the allocation of private codec buffers to REQBUFS for OUTPUT queue. Also,
move MFC instance opening and closing to REQBUFS as well, as it's tied to
allocation and deallocation of private codec buffers.
Signed-off-by: default avatarPawel Osciak <posciak@chromium.org>
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 <m.chehab@samsung.com>
parent 818cd91a
...@@ -643,6 +643,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv) ...@@ -643,6 +643,7 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
case S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET: case S5P_MFC_R2H_CMD_CLOSE_INSTANCE_RET:
clear_work_bit(ctx); clear_work_bit(ctx);
ctx->inst_no = MFC_NO_INSTANCE_SET;
ctx->state = MFCINST_FREE; ctx->state = MFCINST_FREE;
wake_up(&ctx->queue); wake_up(&ctx->queue);
goto irq_cleanup_hw; goto irq_cleanup_hw;
...@@ -763,7 +764,7 @@ static int s5p_mfc_open(struct file *file) ...@@ -763,7 +764,7 @@ static int s5p_mfc_open(struct file *file)
goto err_bad_node; goto err_bad_node;
} }
ctx->fh.ctrl_handler = &ctx->ctrl_handler; ctx->fh.ctrl_handler = &ctx->ctrl_handler;
ctx->inst_no = -1; ctx->inst_no = MFC_NO_INSTANCE_SET;
/* Load firmware if this is the first instance */ /* Load firmware if this is the first instance */
if (dev->num_inst == 1) { if (dev->num_inst == 1) {
dev->watchdog_timer.expires = jiffies + dev->watchdog_timer.expires = jiffies +
...@@ -873,12 +874,11 @@ static int s5p_mfc_release(struct file *file) ...@@ -873,12 +874,11 @@ static int s5p_mfc_release(struct file *file)
vb2_queue_release(&ctx->vq_dst); vb2_queue_release(&ctx->vq_dst);
/* Mark context as idle */ /* Mark context as idle */
clear_work_bit_irqsave(ctx); clear_work_bit_irqsave(ctx);
/* If instance was initialised then /* If instance was initialised and not yet freed,
* return instance and free resources */ * return instance and free resources */
if (ctx->inst_no != MFC_NO_INSTANCE_SET) { if (ctx->state != MFCINST_FREE && ctx->state != MFCINST_INIT) {
mfc_debug(2, "Has to free instance\n"); mfc_debug(2, "Has to free instance\n");
s5p_mfc_close_mfc_inst(dev, ctx); s5p_mfc_close_mfc_inst(dev, ctx);
ctx->inst_no = MFC_NO_INSTANCE_SET;
} }
/* hardware locking scheme */ /* hardware locking scheme */
if (dev->curr_ctx == ctx->num) if (dev->curr_ctx == ctx->num)
......
...@@ -459,5 +459,6 @@ void s5p_mfc_close_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx) ...@@ -459,5 +459,6 @@ void s5p_mfc_close_mfc_inst(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx)
if (ctx->type == MFCINST_DECODER) if (ctx->type == MFCINST_DECODER)
s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx); s5p_mfc_hw_call(dev->mfc_ops, release_dec_desc_buffer, ctx);
ctx->inst_no = MFC_NO_INSTANCE_SET;
ctx->state = MFCINST_FREE; ctx->state = MFCINST_FREE;
} }
...@@ -475,11 +475,11 @@ static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, ...@@ -475,11 +475,11 @@ static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
ret = vb2_reqbufs(&ctx->vq_src, reqbufs); ret = vb2_reqbufs(&ctx->vq_src, reqbufs);
if (ret) if (ret)
goto out; goto out;
s5p_mfc_close_mfc_inst(dev, ctx);
ctx->src_bufs_cnt = 0; ctx->src_bufs_cnt = 0;
ctx->output_state = QUEUE_FREE;
} else if (ctx->output_state == QUEUE_FREE) { } else if (ctx->output_state == QUEUE_FREE) {
/* Can only request buffers after the instance /* Can only request buffers when we have a valid format set. */
* has been opened.
*/
WARN_ON(ctx->src_bufs_cnt != 0); WARN_ON(ctx->src_bufs_cnt != 0);
if (ctx->state != MFCINST_INIT) { if (ctx->state != MFCINST_INIT) {
mfc_err("Reqbufs called in an invalid state\n"); mfc_err("Reqbufs called in an invalid state\n");
...@@ -493,6 +493,13 @@ static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx, ...@@ -493,6 +493,13 @@ static int reqbufs_output(struct s5p_mfc_dev *dev, struct s5p_mfc_ctx *ctx,
if (ret) if (ret)
goto out; goto out;
ret = s5p_mfc_open_mfc_inst(dev, ctx);
if (ret) {
reqbufs->count = 0;
vb2_reqbufs(&ctx->vq_src, reqbufs);
goto out;
}
ctx->output_state = QUEUE_BUFS_REQUESTED; ctx->output_state = QUEUE_BUFS_REQUESTED;
} else { } else {
mfc_err("Buffers have already been requested\n"); mfc_err("Buffers have already been requested\n");
...@@ -594,7 +601,7 @@ static int vidioc_querybuf(struct file *file, void *priv, ...@@ -594,7 +601,7 @@ static int vidioc_querybuf(struct file *file, void *priv,
return -EINVAL; return -EINVAL;
} }
mfc_debug(2, "State: %d, buf->type: %d\n", ctx->state, buf->type); mfc_debug(2, "State: %d, buf->type: %d\n", ctx->state, buf->type);
if (ctx->state == MFCINST_INIT && if (ctx->state == MFCINST_GOT_INST &&
buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
ret = vb2_querybuf(&ctx->vq_src, buf); ret = vb2_querybuf(&ctx->vq_src, buf);
} else if (ctx->state == MFCINST_RUNNING && } else if (ctx->state == MFCINST_RUNNING &&
...@@ -670,24 +677,13 @@ static int vidioc_streamon(struct file *file, void *priv, ...@@ -670,24 +677,13 @@ static int vidioc_streamon(struct file *file, void *priv,
enum v4l2_buf_type type) enum v4l2_buf_type type)
{ {
struct s5p_mfc_ctx *ctx = fh_to_ctx(priv); struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
struct s5p_mfc_dev *dev = ctx->dev;
int ret = -EINVAL; int ret = -EINVAL;
mfc_debug_enter(); mfc_debug_enter();
if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) { if (type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
if (ctx->state == MFCINST_INIT) {
ctx->dst_bufs_cnt = 0;
ctx->src_bufs_cnt = 0;
ctx->capture_state = QUEUE_FREE;
ctx->output_state = QUEUE_FREE;
ret = s5p_mfc_open_mfc_inst(dev, ctx);
if (ret)
return ret;
}
ret = vb2_streamon(&ctx->vq_src, type); ret = vb2_streamon(&ctx->vq_src, type);
} else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) { else if (type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
ret = vb2_streamon(&ctx->vq_dst, type); ret = vb2_streamon(&ctx->vq_dst, type);
}
mfc_debug_leave(); mfc_debug_leave();
return ret; return ret;
} }
......
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