mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-29 10:08:59 +00:00
20ea6adbf1
Build system: x86_64 Build-tested: bcm2708, bcm2709, bcm2710, bcm2711 Run-tested: bcm2708/RPiB+, bcm2709/RPi3B, bcm2710/RPi3B, bcm2711/RPi4B Signed-off-by: Marty Jones <mj8263788@gmail.com> Signed-off-by: Álvaro Fernández Rojas <noltari@gmail.com>
64 lines
2.3 KiB
Diff
64 lines
2.3 KiB
Diff
From a7f335da17a96f0d54101f68d3c7e5baf3324b2c Mon Sep 17 00:00:00 2001
|
|
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
|
Date: Fri, 4 Feb 2022 16:12:35 +0000
|
|
Subject: [PATCH] media: bcm2835-unicam: Handle a repeated frame start
|
|
with no end
|
|
|
|
In the case of 2 frame starts being received with no frame end
|
|
between, the queued buffer held in next_frm was lost as the
|
|
pointer was overwritten with the dummy buffer.
|
|
|
|
Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
|
|
---
|
|
.../media/platform/bcm2835/bcm2835-unicam.c | 29 +++++++++++++++----
|
|
1 file changed, 24 insertions(+), 5 deletions(-)
|
|
|
|
--- a/drivers/media/platform/bcm2835/bcm2835-unicam.c
|
|
+++ b/drivers/media/platform/bcm2835/bcm2835-unicam.c
|
|
@@ -931,10 +931,14 @@ static irqreturn_t unicam_isr(int irq, v
|
|
* as complete, as the HW will reuse that buffer.
|
|
*/
|
|
if (unicam->node[i].cur_frm &&
|
|
- unicam->node[i].cur_frm != unicam->node[i].next_frm)
|
|
+ unicam->node[i].cur_frm != unicam->node[i].next_frm) {
|
|
unicam_process_buffer_complete(&unicam->node[i],
|
|
sequence);
|
|
- unicam->node[i].cur_frm = unicam->node[i].next_frm;
|
|
+ unicam->node[i].cur_frm = unicam->node[i].next_frm;
|
|
+ unicam->node[i].next_frm = NULL;
|
|
+ } else {
|
|
+ unicam->node[i].cur_frm = unicam->node[i].next_frm;
|
|
+ }
|
|
}
|
|
unicam->sequence++;
|
|
}
|
|
@@ -957,10 +961,25 @@ static irqreturn_t unicam_isr(int irq, v
|
|
i);
|
|
/*
|
|
* Set the next frame output to go to a dummy frame
|
|
- * if we have not managed to obtain another frame
|
|
- * from the queue.
|
|
+ * if no buffer currently queued.
|
|
*/
|
|
- unicam_schedule_dummy_buffer(&unicam->node[i]);
|
|
+ if (!unicam->node[i].next_frm ||
|
|
+ unicam->node[i].next_frm == unicam->node[i].cur_frm) {
|
|
+ unicam_schedule_dummy_buffer(&unicam->node[i]);
|
|
+ } else if (unicam->node[i].cur_frm) {
|
|
+ /*
|
|
+ * Repeated FS without FE. Hardware will have
|
|
+ * swapped buffers, but the cur_frm doesn't
|
|
+ * contain valid data. Return cur_frm to the
|
|
+ * queue.
|
|
+ */
|
|
+ spin_lock(&unicam->node[i].dma_queue_lock);
|
|
+ list_add_tail(&unicam->node[i].cur_frm->list,
|
|
+ &unicam->node[i].dma_queue);
|
|
+ spin_unlock(&unicam->node[i].dma_queue_lock);
|
|
+ unicam->node[i].cur_frm = unicam->node[i].next_frm;
|
|
+ unicam->node[i].next_frm = NULL;
|
|
+ }
|
|
}
|
|
|
|
unicam_queue_event_sof(unicam);
|