1 From 5631d65a09fe2249d22fad0985c25dc776b41808 Mon Sep 17 00:00:00 2001
2 From: Naushir Patuck <naush@raspberrypi.com>
3 Date: Fri, 2 Sep 2022 08:35:35 +0100
4 Subject: [PATCH] media: bcm2835-unicam: Fix for possible dummy buffer
7 The Unicam hardware has been observed to cause a buffer overrun when using the
8 dummy buffer as a circular buffer. The conditions that cause the overrun are not
9 fully known, but it seems to occur when the memory bus is heavily loaded.
11 To avoid the overrun, program the hardware with a buffer size of 0 when using
12 the dummy buffer. This will cause overrun into the allocated dummy buffer, but
13 avoid out of bounds writes.
15 Signed-off-by: Naushir Patuck <naush@raspberrypi.com>
17 drivers/media/platform/bcm2835/bcm2835-unicam.c | 14 ++++++++------
18 1 file changed, 8 insertions(+), 6 deletions(-)
20 --- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
21 +++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
22 @@ -126,8 +126,11 @@ MODULE_PARM_DESC(media_controller, "Use
23 #define UNICAM_EMBEDDED_SIZE 16384
26 - * Size of the dummy buffer. Can be any size really, but the DMA
27 - * allocation works in units of page sizes.
28 + * Size of the dummy buffer allocation.
30 + * Due to a HW bug causing buffer overruns in circular buffer mode under certain
31 + * (not yet fully known) conditions, the dummy buffer allocation is set to a
32 + * a single page size, but the hardware gets programmed with a buffer size of 0.
34 #define DUMMY_BUF_SIZE (PAGE_SIZE)
36 @@ -843,8 +846,7 @@ static void unicam_schedule_dummy_buffer
37 unicam_dbg(3, dev, "Scheduling dummy buffer for node %d\n",
40 - unicam_wr_dma_addr(dev, node->dummy_buf_dma_addr, DUMMY_BUF_SIZE,
42 + unicam_wr_dma_addr(dev, node->dummy_buf_dma_addr, 0, node->pad_id);
43 node->next_frm = NULL;
46 @@ -2662,8 +2664,8 @@ static void unicam_stop_streaming(struct
47 * This is only really needed if the embedded data pad is
48 * disabled before the image pad.
50 - unicam_wr_dma_addr(dev, node->dummy_buf_dma_addr,
51 - DUMMY_BUF_SIZE, METADATA_PAD);
52 + unicam_wr_dma_addr(dev, node->dummy_buf_dma_addr, 0,
56 /* Clear all queued buffers for the node */