| From 4b3e88c865fd959bfb1c82f1500d613b6f23498e Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Fri, 19 Nov 2021 11:41:20 +0100 |
| Subject: media: coda: fix CODA960 JPEG encoder buffer overflow |
| |
| From: Philipp Zabel <p.zabel@pengutronix.de> |
| |
| [ Upstream commit 1a59cd88f55068710f6549bee548846661673780 ] |
| |
| Stop the CODA960 JPEG encoder from overflowing capture buffers. |
| The bitstream buffer overflow interrupt doesn't seem to be connected, |
| so this has to be handled via timeout instead. |
| |
| Reported-by: Martin Weber <martin.weber@br-automation.com> |
| Fixes: 96f6f62c4656 ("media: coda: jpeg: add CODA960 JPEG encoder support") |
| Tested-by: Martin Weber <martin.weber@br-automation.com> |
| Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> |
| Signed-off-by: Hans Verkuil <hverkuil-cisco@xs4all.nl> |
| Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| drivers/media/platform/coda/coda-common.c | 8 +++++--- |
| drivers/media/platform/coda/coda-jpeg.c | 21 ++++++++++++++++++++- |
| 2 files changed, 25 insertions(+), 4 deletions(-) |
| |
| diff --git a/drivers/media/platform/coda/coda-common.c b/drivers/media/platform/coda/coda-common.c |
| index 87a2c706f7477..1eed69d29149f 100644 |
| --- a/drivers/media/platform/coda/coda-common.c |
| +++ b/drivers/media/platform/coda/coda-common.c |
| @@ -1537,11 +1537,13 @@ static void coda_pic_run_work(struct work_struct *work) |
| |
| if (!wait_for_completion_timeout(&ctx->completion, |
| msecs_to_jiffies(1000))) { |
| - dev_err(dev->dev, "CODA PIC_RUN timeout\n"); |
| + if (ctx->use_bit) { |
| + dev_err(dev->dev, "CODA PIC_RUN timeout\n"); |
| |
| - ctx->hold = true; |
| + ctx->hold = true; |
| |
| - coda_hw_reset(ctx); |
| + coda_hw_reset(ctx); |
| + } |
| |
| if (ctx->ops->run_timeout) |
| ctx->ops->run_timeout(ctx); |
| diff --git a/drivers/media/platform/coda/coda-jpeg.c b/drivers/media/platform/coda/coda-jpeg.c |
| index b11cfbe166dd3..a72f4655e5ad5 100644 |
| --- a/drivers/media/platform/coda/coda-jpeg.c |
| +++ b/drivers/media/platform/coda/coda-jpeg.c |
| @@ -1127,7 +1127,8 @@ static int coda9_jpeg_prepare_encode(struct coda_ctx *ctx) |
| coda_write(dev, 0, CODA9_REG_JPEG_GBU_BT_PTR); |
| coda_write(dev, 0, CODA9_REG_JPEG_GBU_WD_PTR); |
| coda_write(dev, 0, CODA9_REG_JPEG_GBU_BBSR); |
| - coda_write(dev, 0, CODA9_REG_JPEG_BBC_STRM_CTRL); |
| + coda_write(dev, BIT(31) | ((end_addr - start_addr - header_len) / 256), |
| + CODA9_REG_JPEG_BBC_STRM_CTRL); |
| coda_write(dev, 0, CODA9_REG_JPEG_GBU_CTRL); |
| coda_write(dev, 0, CODA9_REG_JPEG_GBU_FF_RPTR); |
| coda_write(dev, 127, CODA9_REG_JPEG_GBU_BBER); |
| @@ -1257,6 +1258,23 @@ static void coda9_jpeg_finish_encode(struct coda_ctx *ctx) |
| coda_hw_reset(ctx); |
| } |
| |
| +static void coda9_jpeg_encode_timeout(struct coda_ctx *ctx) |
| +{ |
| + struct coda_dev *dev = ctx->dev; |
| + u32 end_addr, wr_ptr; |
| + |
| + /* Handle missing BBC overflow interrupt via timeout */ |
| + end_addr = coda_read(dev, CODA9_REG_JPEG_BBC_END_ADDR); |
| + wr_ptr = coda_read(dev, CODA9_REG_JPEG_BBC_WR_PTR); |
| + if (wr_ptr >= end_addr - 256) { |
| + v4l2_err(&dev->v4l2_dev, "JPEG too large for capture buffer\n"); |
| + coda9_jpeg_finish_encode(ctx); |
| + return; |
| + } |
| + |
| + coda_hw_reset(ctx); |
| +} |
| + |
| static void coda9_jpeg_release(struct coda_ctx *ctx) |
| { |
| int i; |
| @@ -1276,6 +1294,7 @@ const struct coda_context_ops coda9_jpeg_encode_ops = { |
| .start_streaming = coda9_jpeg_start_encoding, |
| .prepare_run = coda9_jpeg_prepare_encode, |
| .finish_run = coda9_jpeg_finish_encode, |
| + .run_timeout = coda9_jpeg_encode_timeout, |
| .release = coda9_jpeg_release, |
| }; |
| |
| -- |
| 2.34.1 |
| |