From a1babd4b34ae511507b8734f8fddf763a44b4ffc Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Thu, 10 Feb 2022 06:21:32 +0100 Subject: [PATCH] Allwinner: linux: Update cedrus patches --- ...edrus-hevc-Improve-buffer-management.patch | 35 +++--- ...edia-cedrus-Fix-H265-aux-buffer-size.patch | 32 +++++ ...drus-Add-watchdog-for-job-completion.patch | 113 ++++++++++++++++++ 3 files changed, 162 insertions(+), 18 deletions(-) create mode 100644 projects/Allwinner/patches/linux/0054-media-cedrus-Fix-H265-aux-buffer-size.patch create mode 100644 projects/Allwinner/patches/linux/0055-media-cedrus-Add-watchdog-for-job-completion.patch diff --git a/projects/Allwinner/patches/linux/0028-media-cedrus-hevc-Improve-buffer-management.patch b/projects/Allwinner/patches/linux/0028-media-cedrus-hevc-Improve-buffer-management.patch index 7d82e8b9c3..3c7312e7dd 100644 --- a/projects/Allwinner/patches/linux/0028-media-cedrus-hevc-Improve-buffer-management.patch +++ b/projects/Allwinner/patches/linux/0028-media-cedrus-hevc-Improve-buffer-management.patch @@ -6,8 +6,8 @@ Subject: [PATCH] media: cedrus: hevc: Improve buffer management Signed-off-by: Jernej Skrabec --- drivers/staging/media/sunxi/cedrus/cedrus.h | 9 +- - .../staging/media/sunxi/cedrus/cedrus_h265.c | 117 ++++++++++-------- - 2 files changed, 69 insertions(+), 57 deletions(-) + .../staging/media/sunxi/cedrus/cedrus_h265.c | 116 ++++++++++-------- + 2 files changed, 68 insertions(+), 57 deletions(-) diff --git a/drivers/staging/media/sunxi/cedrus/cedrus.h b/drivers/staging/media/sunxi/cedrus/cedrus.h index c9ec43be260f..6fa2df354cbf 100644 @@ -37,10 +37,10 @@ index c9ec43be260f..6fa2df354cbf 100644 dma_addr_t neighbor_info_buf_addr; void *entry_points_buf; diff --git a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -index 3b355de4c097..9e21a40867d7 100644 +index 3b355de4c097..802b85434949 100644 --- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c -@@ -91,26 +91,66 @@ static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data, +@@ -91,26 +91,65 @@ static void cedrus_h265_sram_write_data(struct cedrus_dev *dev, void *data, static inline dma_addr_t cedrus_h265_frame_info_mv_col_buf_addr(struct cedrus_ctx *ctx, @@ -66,19 +66,18 @@ index 3b355de4c097..9e21a40867d7 100644 + return 0; + + if (!cedrus_buf->codec.h265.mv_col_buf_size) { -+ unsigned int ctb_size_luma, width_in_ctb_luma; + unsigned int log2_max_luma_coding_block_size; ++ unsigned int ctb_size_luma; + + log2_max_luma_coding_block_size = + sps->log2_min_luma_coding_block_size_minus3 + 3 + + sps->log2_diff_max_min_luma_coding_block_size; + ctb_size_luma = 1 << log2_max_luma_coding_block_size; -+ width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples, -+ ctb_size_luma); + -+ cedrus_buf->codec.h265.mv_col_buf_size = ALIGN(width_in_ctb_luma * ++ cedrus_buf->codec.h265.mv_col_buf_size = ++ DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma) * + DIV_ROUND_UP(sps->pic_height_in_luma_samples, ctb_size_luma) * -+ CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE, 1024); ++ CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE + SZ_1K; + + cedrus_buf->codec.h265.mv_col_buf = + dma_alloc_coherent(ctx->dev->dev, @@ -115,7 +114,7 @@ index 3b355de4c097..9e21a40867d7 100644 }; u32 offset = VE_DEC_H265_SRAM_OFFSET_FRAME_INFO + VE_DEC_H265_SRAM_OFFSET_FRAME_INFO_UNIT * index; -@@ -134,7 +174,8 @@ static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx, +@@ -134,7 +173,8 @@ static void cedrus_h265_frame_info_write_single(struct cedrus_ctx *ctx, static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx, const struct v4l2_hevc_dpb_entry *dpb, @@ -125,7 +124,7 @@ index 3b355de4c097..9e21a40867d7 100644 { struct vb2_queue *vq = v4l2_m2m_get_vq(ctx->fh.m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE); -@@ -149,7 +190,7 @@ static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx, +@@ -149,7 +189,7 @@ static void cedrus_h265_frame_info_write_dpb(struct cedrus_ctx *ctx, cedrus_h265_frame_info_write_single(ctx, i, dpb[i].field_pic, pic_order_cnt, @@ -134,7 +133,7 @@ index 3b355de4c097..9e21a40867d7 100644 } } -@@ -386,36 +427,6 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, +@@ -386,36 +426,6 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, width_in_ctb_luma = DIV_ROUND_UP(sps->pic_width_in_luma_samples, ctb_size_luma); @@ -171,7 +170,7 @@ index 3b355de4c097..9e21a40867d7 100644 /* Activate H265 engine. */ cedrus_engine_enable(ctx, CEDRUS_CODEC_H265); -@@ -669,7 +680,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, +@@ -669,7 +679,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, /* Write decoded picture buffer in pic list. */ cedrus_h265_frame_info_write_dpb(ctx, slice_params->dpb, @@ -180,7 +179,7 @@ index 3b355de4c097..9e21a40867d7 100644 /* Output frame. */ -@@ -680,7 +691,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, +@@ -680,7 +690,7 @@ static void cedrus_h265_setup(struct cedrus_ctx *ctx, cedrus_h265_frame_info_write_single(ctx, output_pic_list_index, slice_params->pic_struct != 0, pic_order_cnt, @@ -189,7 +188,7 @@ index 3b355de4c097..9e21a40867d7 100644 cedrus_write(dev, VE_DEC_H265_OUTPUT_FRAME_IDX, output_pic_list_index); -@@ -729,9 +740,6 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx) +@@ -729,9 +739,6 @@ static int cedrus_h265_start(struct cedrus_ctx *ctx) { struct cedrus_dev *dev = ctx->dev; @@ -199,7 +198,7 @@ index 3b355de4c097..9e21a40867d7 100644 ctx->codec.h265.neighbor_info_buf = dma_alloc_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, &ctx->codec.h265.neighbor_info_buf_addr, -@@ -757,14 +765,6 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx) +@@ -757,14 +764,6 @@ static void cedrus_h265_stop(struct cedrus_ctx *ctx) { struct cedrus_dev *dev = ctx->dev; @@ -214,7 +213,7 @@ index 3b355de4c097..9e21a40867d7 100644 dma_free_coherent(dev->dev, CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE, ctx->codec.h265.neighbor_info_buf, ctx->codec.h265.neighbor_info_buf_addr); -@@ -780,6 +780,16 @@ static void cedrus_h265_trigger(struct cedrus_ctx *ctx) +@@ -780,6 +779,16 @@ static void cedrus_h265_trigger(struct cedrus_ctx *ctx) cedrus_write(dev, VE_DEC_H265_TRIGGER, VE_DEC_H265_TRIGGER_DEC_SLICE); } @@ -231,7 +230,7 @@ index 3b355de4c097..9e21a40867d7 100644 struct cedrus_dec_ops cedrus_dec_ops_h265 = { .irq_clear = cedrus_h265_irq_clear, .irq_disable = cedrus_h265_irq_disable, -@@ -788,4 +798,5 @@ struct cedrus_dec_ops cedrus_dec_ops_h265 = { +@@ -788,4 +797,5 @@ struct cedrus_dec_ops cedrus_dec_ops_h265 = { .start = cedrus_h265_start, .stop = cedrus_h265_stop, .trigger = cedrus_h265_trigger, diff --git a/projects/Allwinner/patches/linux/0054-media-cedrus-Fix-H265-aux-buffer-size.patch b/projects/Allwinner/patches/linux/0054-media-cedrus-Fix-H265-aux-buffer-size.patch new file mode 100644 index 0000000000..3c907d0914 --- /dev/null +++ b/projects/Allwinner/patches/linux/0054-media-cedrus-Fix-H265-aux-buffer-size.patch @@ -0,0 +1,32 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Wed, 9 Feb 2022 19:03:06 +0100 +Subject: [PATCH] media: cedrus: Fix H265 aux buffer size + +Neighbour info buffer size needs to be 794 kiB in size on H6. This is +actually mentioned in comment, but smaller size is used nevertheless. + +Increase buffer size to conform H6 needs. Since increase is not that big +in absolute numbers, it doesn't make sense to complicate logic for older +generations. + +Bug was discovered using iommu, which reported access error when trying +to play H265 video. + +Fixes: 86caab29da78 ("media: cedrus: Add HEVC/H.265 decoding support") +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus_h265.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/staging/media/sunxi/cedrus/cedrus_h265.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_h265.c +@@ -23,7 +23,7 @@ + * Subsequent BSP implementations seem to double the neighbor info buffer size + * for the H6 SoC, which may be related to 10 bit H265 support. + */ +-#define CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE (397 * SZ_1K) ++#define CEDRUS_H265_NEIGHBOR_INFO_BUF_SIZE (794 * SZ_1K) + #define CEDRUS_H265_ENTRY_POINTS_BUF_SIZE (4 * SZ_1K) + #define CEDRUS_H265_MV_COL_BUF_UNIT_CTB_SIZE 160 + diff --git a/projects/Allwinner/patches/linux/0055-media-cedrus-Add-watchdog-for-job-completion.patch b/projects/Allwinner/patches/linux/0055-media-cedrus-Add-watchdog-for-job-completion.patch new file mode 100644 index 0000000000..bfc94d178d --- /dev/null +++ b/projects/Allwinner/patches/linux/0055-media-cedrus-Add-watchdog-for-job-completion.patch @@ -0,0 +1,113 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: Jernej Skrabec +Date: Tue, 1 Feb 2022 19:14:18 +0100 +Subject: [PATCH] media: cedrus: Add watchdog for job completion + +Currently, if job is not completed for whatever reason, userspace +application can hang on ioctl and thus become unkillable. + +In order to prevent that, implement watchdog, which will complete job +after 2 seconds with error state. + +Concept is borrowed from hantro driver. + +Signed-off-by: Jernej Skrabec +--- + drivers/staging/media/sunxi/cedrus/cedrus.c | 2 ++ + drivers/staging/media/sunxi/cedrus/cedrus.h | 3 +++ + .../staging/media/sunxi/cedrus/cedrus_dec.c | 4 +++ + .../staging/media/sunxi/cedrus/cedrus_hw.c | 25 +++++++++++++++++++ + .../staging/media/sunxi/cedrus/cedrus_hw.h | 2 ++ + 5 files changed, 36 insertions(+) + +--- a/drivers/staging/media/sunxi/cedrus/cedrus.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.c +@@ -476,6 +476,8 @@ static int cedrus_probe(struct platform_ + + mutex_init(&dev->dev_mutex); + ++ INIT_DELAYED_WORK(&dev->watchdog_work, cedrus_watchdog); ++ + ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev); + if (ret) { + dev_err(&pdev->dev, "Failed to register V4L2 device\n"); +--- a/drivers/staging/media/sunxi/cedrus/cedrus.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus.h +@@ -23,6 +23,7 @@ + #include + + #include ++#include + + #define CEDRUS_NAME "cedrus" + +@@ -199,6 +200,8 @@ struct cedrus_dev { + struct reset_control *rstc; + + unsigned int capabilities; ++ ++ struct delayed_work watchdog_work; + }; + + extern struct cedrus_dec_ops cedrus_dec_ops_mpeg2; +--- a/drivers/staging/media/sunxi/cedrus/cedrus_dec.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_dec.c +@@ -93,4 +93,8 @@ void cedrus_device_run(void *priv) + v4l2_ctrl_request_complete(src_req, &ctx->hdl); + + dev->dec_ops[ctx->current_codec]->trigger(ctx); ++ ++ /* Start the watchdog timer. */ ++ schedule_delayed_work(&dev->watchdog_work, ++ msecs_to_jiffies(2000)); + } +--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.c ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.c +@@ -117,6 +117,13 @@ static irqreturn_t cedrus_irq(int irq, v + enum vb2_buffer_state state; + enum cedrus_irq_status status; + ++ /* ++ * If cancel_delayed_work returns false it means watchdog already ++ * executed and finished the job. ++ */ ++ if (!cancel_delayed_work(&dev->watchdog_work)) ++ return IRQ_HANDLED; ++ + ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); + if (!ctx) { + v4l2_err(&dev->v4l2_dev, +@@ -142,6 +149,24 @@ static irqreturn_t cedrus_irq(int irq, v + return IRQ_HANDLED; + } + ++void cedrus_watchdog(struct work_struct *work) ++{ ++ struct cedrus_dev *dev; ++ struct cedrus_ctx *ctx; ++ ++ dev = container_of(to_delayed_work(work), ++ struct cedrus_dev, watchdog_work); ++ ++ ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev); ++ if (!ctx) ++ return; ++ ++ v4l2_err(&dev->v4l2_dev, "frame processing timed out!\n"); ++ reset_control_reset(dev->rstc); ++ v4l2_m2m_buf_done_and_job_finish(ctx->dev->m2m_dev, ctx->fh.m2m_ctx, ++ VB2_BUF_STATE_ERROR); ++} ++ + int cedrus_hw_suspend(struct device *device) + { + struct cedrus_dev *dev = dev_get_drvdata(device); +--- a/drivers/staging/media/sunxi/cedrus/cedrus_hw.h ++++ b/drivers/staging/media/sunxi/cedrus/cedrus_hw.h +@@ -28,4 +28,6 @@ int cedrus_hw_resume(struct device *devi + int cedrus_hw_probe(struct cedrus_dev *dev); + void cedrus_hw_remove(struct cedrus_dev *dev); + ++void cedrus_watchdog(struct work_struct *work); ++ + #endif