media: cedrus: Add error handling for failed setup
During decoding setup stage for complex codecs like HEVC driver can detect inconsistent values in controls or some other task, like allocating memory, can fail. Currently setup stage has no way of signalling error. Change return type of setup callback to int and if returned value is not zero, skip decoding and finish job immediately with error flag. While currently there is only one place when setup can fail, it's expected that there will be more such cases in the future, when HEVC decoding is improved. Signed-off-by: Jernej Skrabec <jernej.skrabec@gmail.com> Reviewed-by: Ezequiel Garcia <ezequiel@vanguardiasur.com.ar> Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> Signed-off-by: Mauro Carvalho Chehab <mchehab@kernel.org>
This commit is contained in:
committed by
Mauro Carvalho Chehab
parent
1f258653e1
commit
4af46bcc49
@@ -162,7 +162,7 @@ struct cedrus_dec_ops {
|
||||
void (*irq_clear)(struct cedrus_ctx *ctx);
|
||||
void (*irq_disable)(struct cedrus_ctx *ctx);
|
||||
enum cedrus_irq_status (*irq_status)(struct cedrus_ctx *ctx);
|
||||
void (*setup)(struct cedrus_ctx *ctx, struct cedrus_run *run);
|
||||
int (*setup)(struct cedrus_ctx *ctx, struct cedrus_run *run);
|
||||
int (*start)(struct cedrus_ctx *ctx);
|
||||
void (*stop)(struct cedrus_ctx *ctx);
|
||||
void (*trigger)(struct cedrus_ctx *ctx);
|
||||
|
||||
@@ -28,6 +28,7 @@ void cedrus_device_run(void *priv)
|
||||
struct cedrus_dev *dev = ctx->dev;
|
||||
struct cedrus_run run = {};
|
||||
struct media_request *src_req;
|
||||
int error;
|
||||
|
||||
run.src = v4l2_m2m_next_src_buf(ctx->fh.m2m_ctx);
|
||||
run.dst = v4l2_m2m_next_dst_buf(ctx->fh.m2m_ctx);
|
||||
@@ -89,16 +90,26 @@ void cedrus_device_run(void *priv)
|
||||
|
||||
cedrus_dst_format_set(dev, &ctx->dst_fmt);
|
||||
|
||||
dev->dec_ops[ctx->current_codec]->setup(ctx, &run);
|
||||
error = dev->dec_ops[ctx->current_codec]->setup(ctx, &run);
|
||||
if (error)
|
||||
v4l2_err(&ctx->dev->v4l2_dev,
|
||||
"Failed to setup decoding job: %d\n", error);
|
||||
|
||||
/* Complete request(s) controls if needed. */
|
||||
|
||||
if (src_req)
|
||||
v4l2_ctrl_request_complete(src_req, &ctx->hdl);
|
||||
|
||||
dev->dec_ops[ctx->current_codec]->trigger(ctx);
|
||||
/* Trigger decoding if setup went well, bail out otherwise. */
|
||||
if (!error) {
|
||||
dev->dec_ops[ctx->current_codec]->trigger(ctx);
|
||||
|
||||
/* Start the watchdog timer. */
|
||||
schedule_delayed_work(&dev->watchdog_work,
|
||||
msecs_to_jiffies(2000));
|
||||
/* Start the watchdog timer. */
|
||||
schedule_delayed_work(&dev->watchdog_work,
|
||||
msecs_to_jiffies(2000));
|
||||
} else {
|
||||
v4l2_m2m_buf_done_and_job_finish(ctx->dev->m2m_dev,
|
||||
ctx->fh.m2m_ctx,
|
||||
VB2_BUF_STATE_ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -493,8 +493,7 @@ static void cedrus_h264_irq_disable(struct cedrus_ctx *ctx)
|
||||
reg & ~VE_H264_CTRL_INT_MASK);
|
||||
}
|
||||
|
||||
static void cedrus_h264_setup(struct cedrus_ctx *ctx,
|
||||
struct cedrus_run *run)
|
||||
static int cedrus_h264_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
|
||||
{
|
||||
struct cedrus_dev *dev = ctx->dev;
|
||||
|
||||
@@ -510,6 +509,8 @@ static void cedrus_h264_setup(struct cedrus_ctx *ctx,
|
||||
cedrus_write_frame_list(ctx, run);
|
||||
|
||||
cedrus_set_params(ctx, run);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cedrus_h264_start(struct cedrus_ctx *ctx)
|
||||
|
||||
@@ -326,8 +326,7 @@ static int cedrus_h265_is_low_delay(struct cedrus_run *run)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||
struct cedrus_run *run)
|
||||
static int cedrus_h265_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
|
||||
{
|
||||
struct cedrus_dev *dev = ctx->dev;
|
||||
const struct v4l2_ctrl_hevc_sps *sps;
|
||||
@@ -385,8 +384,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||
GFP_KERNEL, DMA_ATTR_NO_KERNEL_MAPPING);
|
||||
if (!ctx->codec.h265.mv_col_buf) {
|
||||
ctx->codec.h265.mv_col_buf_size = 0;
|
||||
// TODO: Abort the process here.
|
||||
return;
|
||||
return -ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,6 +701,8 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx,
|
||||
|
||||
/* Enable appropriate interruptions. */
|
||||
cedrus_write(dev, VE_DEC_H265_CTRL, VE_DEC_H265_CTRL_IRQ_MASK);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cedrus_h265_start(struct cedrus_ctx *ctx)
|
||||
|
||||
@@ -48,7 +48,7 @@ static void cedrus_mpeg2_irq_disable(struct cedrus_ctx *ctx)
|
||||
cedrus_write(dev, VE_DEC_MPEG_CTRL, reg);
|
||||
}
|
||||
|
||||
static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
|
||||
static int cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
|
||||
{
|
||||
const struct v4l2_ctrl_mpeg2_sequence *seq;
|
||||
const struct v4l2_ctrl_mpeg2_picture *pic;
|
||||
@@ -185,6 +185,8 @@ static void cedrus_mpeg2_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
|
||||
VE_DEC_MPEG_CTRL_MC_CACHE_EN;
|
||||
|
||||
cedrus_write(dev, VE_DEC_MPEG_CTRL, reg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cedrus_mpeg2_trigger(struct cedrus_ctx *ctx)
|
||||
|
||||
@@ -651,8 +651,7 @@ static void cedrus_vp8_irq_disable(struct cedrus_ctx *ctx)
|
||||
reg & ~VE_H264_CTRL_INT_MASK);
|
||||
}
|
||||
|
||||
static void cedrus_vp8_setup(struct cedrus_ctx *ctx,
|
||||
struct cedrus_run *run)
|
||||
static int cedrus_vp8_setup(struct cedrus_ctx *ctx, struct cedrus_run *run)
|
||||
{
|
||||
const struct v4l2_ctrl_vp8_frame *slice = run->vp8.frame_params;
|
||||
struct vb2_queue *cap_q = &ctx->fh.m2m_ctx->cap_q_ctx.q;
|
||||
@@ -855,6 +854,8 @@ static void cedrus_vp8_setup(struct cedrus_ctx *ctx,
|
||||
ctx->codec.vp8.last_sharpness_level =
|
||||
slice->lf.sharpness_level;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cedrus_vp8_start(struct cedrus_ctx *ctx)
|
||||
|
||||
Reference in New Issue
Block a user