mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-28 21:33:52 +00:00
media: mediatek: vcodec: adding lock to protect encoder context list
Add a lock for the ctx_list, to avoid accessing a NULL pointer
within the 'vpu_enc_ipi_handler' function when the ctx_list has
been deleted due to an unexpected behavior on the SCP IP block.
Fixes: 1972e32431
("media: mediatek: vcodec: Fix possible invalid memory access for encoder")
Signed-off-by: Yunfei Dong <yunfei.dong@mediatek.com>
Reviewed-by: Nicolas Dufresne <nicolas.dufresne@collabora.com>
Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Signed-off-by: Sebastian Fricke <sebastian.fricke@collabora.com>
Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
This commit is contained in:
parent
6467cda18c
commit
afaaf3a0f6
4 changed files with 11 additions and 2 deletions
|
@ -65,12 +65,12 @@ static void mtk_vcodec_vpu_reset_enc_handler(void *priv)
|
||||||
|
|
||||||
dev_err(&dev->plat_dev->dev, "Watchdog timeout!!");
|
dev_err(&dev->plat_dev->dev, "Watchdog timeout!!");
|
||||||
|
|
||||||
mutex_lock(&dev->dev_mutex);
|
mutex_lock(&dev->dev_ctx_lock);
|
||||||
list_for_each_entry(ctx, &dev->ctx_list, list) {
|
list_for_each_entry(ctx, &dev->ctx_list, list) {
|
||||||
ctx->state = MTK_STATE_ABORT;
|
ctx->state = MTK_STATE_ABORT;
|
||||||
mtk_v4l2_vdec_dbg(0, ctx, "[%d] Change to state MTK_STATE_ABORT", ctx->id);
|
mtk_v4l2_vdec_dbg(0, ctx, "[%d] Change to state MTK_STATE_ABORT", ctx->id);
|
||||||
}
|
}
|
||||||
mutex_unlock(&dev->dev_mutex);
|
mutex_unlock(&dev->dev_ctx_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct mtk_vcodec_fw_ops mtk_vcodec_vpu_msg = {
|
static const struct mtk_vcodec_fw_ops mtk_vcodec_vpu_msg = {
|
||||||
|
|
|
@ -177,7 +177,9 @@ static int fops_vcodec_open(struct file *file)
|
||||||
mtk_v4l2_venc_dbg(2, ctx, "Create instance [%d]@%p m2m_ctx=%p ",
|
mtk_v4l2_venc_dbg(2, ctx, "Create instance [%d]@%p m2m_ctx=%p ",
|
||||||
ctx->id, ctx, ctx->m2m_ctx);
|
ctx->id, ctx, ctx->m2m_ctx);
|
||||||
|
|
||||||
|
mutex_lock(&dev->dev_ctx_lock);
|
||||||
list_add(&ctx->list, &dev->ctx_list);
|
list_add(&ctx->list, &dev->ctx_list);
|
||||||
|
mutex_unlock(&dev->dev_ctx_lock);
|
||||||
|
|
||||||
mutex_unlock(&dev->dev_mutex);
|
mutex_unlock(&dev->dev_mutex);
|
||||||
mtk_v4l2_venc_dbg(0, ctx, "%s encoder [%d]", dev_name(&dev->plat_dev->dev),
|
mtk_v4l2_venc_dbg(0, ctx, "%s encoder [%d]", dev_name(&dev->plat_dev->dev),
|
||||||
|
@ -212,7 +214,9 @@ static int fops_vcodec_release(struct file *file)
|
||||||
v4l2_fh_exit(&ctx->fh);
|
v4l2_fh_exit(&ctx->fh);
|
||||||
v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
|
v4l2_ctrl_handler_free(&ctx->ctrl_hdl);
|
||||||
|
|
||||||
|
mutex_lock(&dev->dev_ctx_lock);
|
||||||
list_del_init(&ctx->list);
|
list_del_init(&ctx->list);
|
||||||
|
mutex_unlock(&dev->dev_ctx_lock);
|
||||||
kfree(ctx);
|
kfree(ctx);
|
||||||
mutex_unlock(&dev->dev_mutex);
|
mutex_unlock(&dev->dev_mutex);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -294,6 +298,7 @@ static int mtk_vcodec_probe(struct platform_device *pdev)
|
||||||
|
|
||||||
mutex_init(&dev->enc_mutex);
|
mutex_init(&dev->enc_mutex);
|
||||||
mutex_init(&dev->dev_mutex);
|
mutex_init(&dev->dev_mutex);
|
||||||
|
mutex_init(&dev->dev_ctx_lock);
|
||||||
spin_lock_init(&dev->irqlock);
|
spin_lock_init(&dev->irqlock);
|
||||||
|
|
||||||
snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s",
|
snprintf(dev->v4l2_dev.name, sizeof(dev->v4l2_dev.name), "%s",
|
||||||
|
|
|
@ -178,6 +178,7 @@ struct mtk_vcodec_enc_ctx {
|
||||||
*
|
*
|
||||||
* @enc_mutex: encoder hardware lock.
|
* @enc_mutex: encoder hardware lock.
|
||||||
* @dev_mutex: video_device lock
|
* @dev_mutex: video_device lock
|
||||||
|
* @dev_ctx_lock: the lock of context list
|
||||||
* @encode_workqueue: encode work queue
|
* @encode_workqueue: encode work queue
|
||||||
*
|
*
|
||||||
* @enc_irq: h264 encoder irq resource
|
* @enc_irq: h264 encoder irq resource
|
||||||
|
@ -205,6 +206,7 @@ struct mtk_vcodec_enc_dev {
|
||||||
/* encoder hardware mutex lock */
|
/* encoder hardware mutex lock */
|
||||||
struct mutex enc_mutex;
|
struct mutex enc_mutex;
|
||||||
struct mutex dev_mutex;
|
struct mutex dev_mutex;
|
||||||
|
struct mutex dev_ctx_lock;
|
||||||
struct workqueue_struct *encode_workqueue;
|
struct workqueue_struct *encode_workqueue;
|
||||||
|
|
||||||
int enc_irq;
|
int enc_irq;
|
||||||
|
|
|
@ -47,12 +47,14 @@ static bool vpu_enc_check_ap_inst(struct mtk_vcodec_enc_dev *enc_dev, struct ven
|
||||||
struct mtk_vcodec_enc_ctx *ctx;
|
struct mtk_vcodec_enc_ctx *ctx;
|
||||||
int ret = false;
|
int ret = false;
|
||||||
|
|
||||||
|
mutex_lock(&enc_dev->dev_ctx_lock);
|
||||||
list_for_each_entry(ctx, &enc_dev->ctx_list, list) {
|
list_for_each_entry(ctx, &enc_dev->ctx_list, list) {
|
||||||
if (!IS_ERR_OR_NULL(ctx) && ctx->vpu_inst == vpu) {
|
if (!IS_ERR_OR_NULL(ctx) && ctx->vpu_inst == vpu) {
|
||||||
ret = true;
|
ret = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
mutex_unlock(&enc_dev->dev_ctx_lock);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue