Skip to content

Commit 5b0b516

Browse files
6by9popcornmix
authored andcommitted
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 <[email protected]>
1 parent 127fcc8 commit 5b0b516

File tree

1 file changed

+24
-5
lines changed

1 file changed

+24
-5
lines changed

drivers/media/platform/bcm2835/bcm2835-unicam.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -932,10 +932,14 @@ static irqreturn_t unicam_isr(int irq, void *dev)
932932
* as complete, as the HW will reuse that buffer.
933933
*/
934934
if (unicam->node[i].cur_frm &&
935-
unicam->node[i].cur_frm != unicam->node[i].next_frm)
935+
unicam->node[i].cur_frm != unicam->node[i].next_frm) {
936936
unicam_process_buffer_complete(&unicam->node[i],
937937
sequence);
938-
unicam->node[i].cur_frm = unicam->node[i].next_frm;
938+
unicam->node[i].cur_frm = unicam->node[i].next_frm;
939+
unicam->node[i].next_frm = NULL;
940+
} else {
941+
unicam->node[i].cur_frm = unicam->node[i].next_frm;
942+
}
939943
}
940944
unicam->sequence++;
941945
}
@@ -958,10 +962,25 @@ static irqreturn_t unicam_isr(int irq, void *dev)
958962
i);
959963
/*
960964
* Set the next frame output to go to a dummy frame
961-
* if we have not managed to obtain another frame
962-
* from the queue.
965+
* if no buffer currently queued.
963966
*/
964-
unicam_schedule_dummy_buffer(&unicam->node[i]);
967+
if (!unicam->node[i].next_frm ||
968+
unicam->node[i].next_frm == unicam->node[i].cur_frm) {
969+
unicam_schedule_dummy_buffer(&unicam->node[i]);
970+
} else if (unicam->node[i].cur_frm) {
971+
/*
972+
* Repeated FS without FE. Hardware will have
973+
* swapped buffers, but the cur_frm doesn't
974+
* contain valid data. Return cur_frm to the
975+
* queue.
976+
*/
977+
spin_lock(&unicam->node[i].dma_queue_lock);
978+
list_add_tail(&unicam->node[i].cur_frm->list,
979+
&unicam->node[i].dma_queue);
980+
spin_unlock(&unicam->node[i].dma_queue_lock);
981+
unicam->node[i].cur_frm = unicam->node[i].next_frm;
982+
unicam->node[i].next_frm = NULL;
983+
}
965984
}
966985

967986
unicam_queue_event_sof(unicam);

0 commit comments

Comments
 (0)