summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNaushir Patuck <naush@raspberrypi.com>2024-11-27 11:15:15 +0000
committerMauro Carvalho Chehab <mchehab+huawei@kernel.org>2024-12-19 12:50:18 +0100
commit7b1ec3e38906224c2b201e3317d2b6c7fdbeff9b (patch)
treeb79f1e8a41be1fa330be688bb9c7fbed91d21de6
parent697a252bb2ea414cc1c0b4cf4e3d94a879eaf162 (diff)
media: bcm2835-unicam: Fix for possible dummy buffer overrun
The Unicam hardware has been observed to cause a buffer overrun when using the dummy buffer as a circular buffer. The conditions that cause the overrun are not fully known, but it seems to occur when the memory bus is heavily loaded. To avoid the overrun, program the hardware with a buffer size of 0 when using the dummy buffer. This will cause overrun into the allocated dummy buffer, but avoid out of bounds writes. Signed-off-by: Naushir Patuck <naush@raspberrypi.com> Reviewed-by: Jacopo Mondi <jacopo.mondi@ideasonboard.com> Signed-off-by: Sakari Ailus <sakari.ailus@linux.intel.com> Signed-off-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
-rw-r--r--drivers/media/platform/broadcom/bcm2835-unicam.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/drivers/media/platform/broadcom/bcm2835-unicam.c b/drivers/media/platform/broadcom/bcm2835-unicam.c
index 550eb1b064f1..f10064107d54 100644
--- a/drivers/media/platform/broadcom/bcm2835-unicam.c
+++ b/drivers/media/platform/broadcom/bcm2835-unicam.c
@@ -640,7 +640,14 @@ static inline void unicam_reg_write_field(struct unicam_device *unicam, u32 offs
static void unicam_wr_dma_addr(struct unicam_node *node,
struct unicam_buffer *buf)
{
- dma_addr_t endaddr = buf->dma_addr + buf->size;
+ /*
+ * Due to a HW bug causing buffer overruns in circular buffer mode under
+ * certain (not yet fully known) conditions, the dummy buffer allocation
+ * is set to a a single page size, but the hardware gets programmed with
+ * a buffer size of 0.
+ */
+ dma_addr_t endaddr = buf->dma_addr +
+ (buf != &node->dummy_buf ? buf->size : 0);
if (node->id == UNICAM_IMAGE_NODE) {
unicam_reg_write(node->dev, UNICAM_IBSA0, buf->dma_addr);