From: Ayoung Sim Date: Thu, 23 Aug 2018 08:10:04 +0000 (+0900) Subject: [COMMON] media: mfc: avoid the kernel panic in specific scenario X-Git-Url: https://git.stricted.de/?a=commitdiff_plain;h=0dabf95417cb1359c58e95f9ec9d535b094c2e5a;p=GitHub%2FLineageOS%2Fandroid_kernel_motorola_exynos9610.git [COMMON] media: mfc: avoid the kernel panic in specific scenario We do not support DRC(Dynamic Resolution Change) and seeking overlapped scenario. However, in this case, we avoid the kernel panic. wait_state is changed as below. DRC detected -> WAIT_DECODING -> g_fmt -> WAIT_DPB_FLUSH -> stramoff(dst) -> WAIT_NONE -> decoding(INIT_BUF, NAL_START) Change-Id: I81280249a962e2b3d4532b74ad247674441e4789 Signed-off-by: Ayoung Sim --- diff --git a/drivers/media/platform/exynos/mfc/mfc_data_struct.h b/drivers/media/platform/exynos/mfc/mfc_data_struct.h index ac55858e4e2e..5140316c92dc 100644 --- a/drivers/media/platform/exynos/mfc/mfc_data_struct.h +++ b/drivers/media/platform/exynos/mfc/mfc_data_struct.h @@ -132,7 +132,7 @@ enum mfc_queue_state { enum mfc_dec_wait_state { WAIT_NONE = 0, WAIT_DECODING, - WAIT_INITBUF_DONE, + WAIT_DPB_FLUSH, }; /** diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c b/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c index 2d045d42afa9..fe2730862371 100644 --- a/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c +++ b/drivers/media/platform/exynos/mfc/mfc_dec_v4l2.c @@ -284,12 +284,16 @@ static int mfc_dec_g_fmt_vid_cap_mplane(struct file *file, void *priv, if (ctx->state == MFCINST_GOT_INST || ctx->state == MFCINST_RES_CHANGE_FLUSH || ctx->state == MFCINST_RES_CHANGE_END) { - /* If the MFC is parsing the header, - * so wait until it is finished */ - if (mfc_wait_for_done_ctx(ctx, - MFC_REG_R2H_CMD_SEQ_DONE_RET)) { - mfc_err_dev("header parsing failed\n"); - return -EAGAIN; + /* If there is no source buffer to parsing, we can't SEQ_START */ + if ((ctx->wait_state == WAIT_DECODING) && + mfc_is_queue_count_same(&ctx->buf_queue_lock, &ctx->src_buf_queue, 0)) { + mfc_err_dev("There is no source buffer to parsing, keep previous resolution\n"); + return -EAGAIN; + } + /* If the MFC is parsing the header, so wait until it is finished */ + if (mfc_wait_for_done_ctx(ctx, MFC_REG_R2H_CMD_SEQ_DONE_RET)) { + mfc_err_dev("header parsing failed\n"); + return -EAGAIN; } } @@ -353,6 +357,11 @@ static int mfc_dec_g_fmt_vid_cap_mplane(struct file *file, void *priv, } } + if (ctx->wait_state == WAIT_DECODING) { + ctx->wait_state = WAIT_DPB_FLUSH; + mfc_debug(2, "wait DPB flush for decoding(INIT_BUFFER)\n"); + } + mfc_debug_leave(); return 0; diff --git a/drivers/media/platform/exynos/mfc/mfc_dec_vb2.c b/drivers/media/platform/exynos/mfc/mfc_dec_vb2.c index bf83abfbbfa0..fc24322ae065 100644 --- a/drivers/media/platform/exynos/mfc/mfc_dec_vb2.c +++ b/drivers/media/platform/exynos/mfc/mfc_dec_vb2.c @@ -365,10 +365,9 @@ static void __mfc_dec_dst_stop_streaming(struct mfc_ctx *ctx) index++; } - if (ctx->wait_state == WAIT_INITBUF_DONE || - ctx->wait_state == WAIT_DECODING) { + if (ctx->wait_state == WAIT_DPB_FLUSH) { ctx->wait_state = WAIT_NONE; - mfc_debug(2, "Decoding can be started now\n"); + mfc_debug(2, "Decoding(INIT_BUFFER) can be started now\n"); } } diff --git a/drivers/media/platform/exynos/mfc/mfc_isr.c b/drivers/media/platform/exynos/mfc/mfc_isr.c index c9470fec711c..7892589366db 100644 --- a/drivers/media/platform/exynos/mfc/mfc_isr.c +++ b/drivers/media/platform/exynos/mfc/mfc_isr.c @@ -1466,10 +1466,6 @@ static int __mfc_irq_ctx(struct mfc_ctx *ctx, unsigned int reason, unsigned int mfc_change_state(ctx, MFCINST_RUNNING); if (ctx->type == MFCINST_DECODER) { - if (ctx->wait_state == WAIT_DECODING) { - ctx->wait_state = WAIT_INITBUF_DONE; - mfc_debug(2, "INIT_BUFFER has done, but can't start decoding\n"); - } if (ctx->is_dpb_realloc) ctx->is_dpb_realloc = 0; }