Skip to content

Commit 2a1d12e

Browse files
6by9pelwell
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 aeaa246 commit 2a1d12e

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
@@ -933,10 +933,14 @@ static irqreturn_t unicam_isr(int irq, void *dev)
933933
* as complete, as the HW will reuse that buffer.
934934
*/
935935
if (unicam->node[i].cur_frm &&
936-
unicam->node[i].cur_frm != unicam->node[i].next_frm)
936+
unicam->node[i].cur_frm != unicam->node[i].next_frm) {
937937
unicam_process_buffer_complete(&unicam->node[i],
938938
sequence);
939-
unicam->node[i].cur_frm = unicam->node[i].next_frm;
939+
unicam->node[i].cur_frm = unicam->node[i].next_frm;
940+
unicam->node[i].next_frm = NULL;
941+
} else {
942+
unicam->node[i].cur_frm = unicam->node[i].next_frm;
943+
}
940944
}
941945
unicam->sequence++;
942946
}
@@ -959,10 +963,25 @@ static irqreturn_t unicam_isr(int irq, void *dev)
959963
i);
960964
/*
961965
* Set the next frame output to go to a dummy frame
962-
* if we have not managed to obtain another frame
963-
* from the queue.
966+
* if no buffer currently queued.
964967
*/
965-
unicam_schedule_dummy_buffer(&unicam->node[i]);
968+
if (!unicam->node[i].next_frm ||
969+
unicam->node[i].next_frm == unicam->node[i].cur_frm) {
970+
unicam_schedule_dummy_buffer(&unicam->node[i]);
971+
} else if (unicam->node[i].cur_frm) {
972+
/*
973+
* Repeated FS without FE. Hardware will have
974+
* swapped buffers, but the cur_frm doesn't
975+
* contain valid data. Return cur_frm to the
976+
* queue.
977+
*/
978+
spin_lock(&unicam->node[i].dma_queue_lock);
979+
list_add_tail(&unicam->node[i].cur_frm->list,
980+
&unicam->node[i].dma_queue);
981+
spin_unlock(&unicam->node[i].dma_queue_lock);
982+
unicam->node[i].cur_frm = unicam->node[i].next_frm;
983+
unicam->node[i].next_frm = NULL;
984+
}
966985
}
967986

968987
unicam_queue_event_sof(unicam);

0 commit comments

Comments
 (0)