aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2012-11-16 10:03:07 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2012-11-22 09:36:53 -0500
commitc4697d7f96f40cdc8f88bcdf4bf13d74ea11c4cc (patch)
tree8ff45f6260ae50eea7764b2b3db19babe90e2cce
parentaec968326df3c60d140c4bcb00f2ee982acd01cb (diff)
[media] vpif_display: protect dma_queue by a spin_lock
The dma_queue list is accessed by both the interrupt handler and by normal code. It needs to be protected by a lock to prevent possible list corruption. Corruption has been observed in 'real-life' conditions. Adding this lock made it go away. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Acked-by: Lad, Prabhakar <prabhakar.lad@ti.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
-rw-r--r--drivers/media/platform/davinci/vpif_display.c22
1 files changed, 20 insertions, 2 deletions
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index e5109ae0593d..9f2b603be9c9 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -177,11 +177,14 @@ static void vpif_buffer_queue(struct vb2_buffer *vb)
177 struct vpif_disp_buffer, vb); 177 struct vpif_disp_buffer, vb);
178 struct channel_obj *ch = fh->channel; 178 struct channel_obj *ch = fh->channel;
179 struct common_obj *common; 179 struct common_obj *common;
180 unsigned long flags;
180 181
181 common = &ch->common[VPIF_VIDEO_INDEX]; 182 common = &ch->common[VPIF_VIDEO_INDEX];
182 183
183 /* add the buffer to the DMA queue */ 184 /* add the buffer to the DMA queue */
185 spin_lock_irqsave(&common->irqlock, flags);
184 list_add_tail(&buf->list, &common->dma_queue); 186 list_add_tail(&buf->list, &common->dma_queue);
187 spin_unlock_irqrestore(&common->irqlock, flags);
185} 188}
186 189
187/* 190/*
@@ -246,10 +249,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
246 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX]; 249 struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
247 struct vpif_params *vpif = &ch->vpifparams; 250 struct vpif_params *vpif = &ch->vpifparams;
248 unsigned long addr = 0; 251 unsigned long addr = 0;
252 unsigned long flags;
249 int ret; 253 int ret;
250 254
251 /* If buffer queue is empty, return error */ 255 /* If buffer queue is empty, return error */
256 spin_lock_irqsave(&common->irqlock, flags);
252 if (list_empty(&common->dma_queue)) { 257 if (list_empty(&common->dma_queue)) {
258 spin_unlock_irqrestore(&common->irqlock, flags);
253 vpif_err("buffer queue is empty\n"); 259 vpif_err("buffer queue is empty\n");
254 return -EIO; 260 return -EIO;
255 } 261 }
@@ -260,6 +266,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
260 struct vpif_disp_buffer, list); 266 struct vpif_disp_buffer, list);
261 267
262 list_del(&common->cur_frm->list); 268 list_del(&common->cur_frm->list);
269 spin_unlock_irqrestore(&common->irqlock, flags);
263 /* Mark state of the current frame to active */ 270 /* Mark state of the current frame to active */
264 common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE; 271 common->cur_frm->vb.state = VB2_BUF_STATE_ACTIVE;
265 272
@@ -330,6 +337,7 @@ static int vpif_stop_streaming(struct vb2_queue *vq)
330 struct vpif_fh *fh = vb2_get_drv_priv(vq); 337 struct vpif_fh *fh = vb2_get_drv_priv(vq);
331 struct channel_obj *ch = fh->channel; 338 struct channel_obj *ch = fh->channel;
332 struct common_obj *common; 339 struct common_obj *common;
340 unsigned long flags;
333 341
334 if (!vb2_is_streaming(vq)) 342 if (!vb2_is_streaming(vq))
335 return 0; 343 return 0;
@@ -337,12 +345,14 @@ static int vpif_stop_streaming(struct vb2_queue *vq)
337 common = &ch->common[VPIF_VIDEO_INDEX]; 345 common = &ch->common[VPIF_VIDEO_INDEX];
338 346
339 /* release all active buffers */ 347 /* release all active buffers */
348 spin_lock_irqsave(&common->irqlock, flags);
340 while (!list_empty(&common->dma_queue)) { 349 while (!list_empty(&common->dma_queue)) {
341 common->next_frm = list_entry(common->dma_queue.next, 350 common->next_frm = list_entry(common->dma_queue.next,
342 struct vpif_disp_buffer, list); 351 struct vpif_disp_buffer, list);
343 list_del(&common->next_frm->list); 352 list_del(&common->next_frm->list);
344 vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR); 353 vb2_buffer_done(&common->next_frm->vb, VB2_BUF_STATE_ERROR);
345 } 354 }
355 spin_unlock_irqrestore(&common->irqlock, flags);
346 356
347 return 0; 357 return 0;
348} 358}
@@ -363,11 +373,13 @@ static void process_progressive_mode(struct common_obj *common)
363{ 373{
364 unsigned long addr = 0; 374 unsigned long addr = 0;
365 375
376 spin_lock(&common->irqlock);
366 /* Get the next buffer from buffer queue */ 377 /* Get the next buffer from buffer queue */
367 common->next_frm = list_entry(common->dma_queue.next, 378 common->next_frm = list_entry(common->dma_queue.next,
368 struct vpif_disp_buffer, list); 379 struct vpif_disp_buffer, list);
369 /* Remove that buffer from the buffer queue */ 380 /* Remove that buffer from the buffer queue */
370 list_del(&common->next_frm->list); 381 list_del(&common->next_frm->list);
382 spin_unlock(&common->irqlock);
371 /* Mark status of the buffer as active */ 383 /* Mark status of the buffer as active */
372 common->next_frm->vb.state = VB2_BUF_STATE_ACTIVE; 384 common->next_frm->vb.state = VB2_BUF_STATE_ACTIVE;
373 385
@@ -398,16 +410,18 @@ static void process_interlaced_mode(int fid, struct common_obj *common)
398 common->cur_frm = common->next_frm; 410 common->cur_frm = common->next_frm;
399 411
400 } else if (1 == fid) { /* odd field */ 412 } else if (1 == fid) { /* odd field */
413 spin_lock(&common->irqlock);
401 if (list_empty(&common->dma_queue) 414 if (list_empty(&common->dma_queue)
402 || (common->cur_frm != common->next_frm)) { 415 || (common->cur_frm != common->next_frm)) {
416 spin_unlock(&common->irqlock);
403 return; 417 return;
404 } 418 }
419 spin_unlock(&common->irqlock);
405 /* one field is displayed configure the next 420 /* one field is displayed configure the next
406 * frame if it is available else hold on current 421 * frame if it is available else hold on current
407 * frame */ 422 * frame */
408 /* Get next from the buffer queue */ 423 /* Get next from the buffer queue */
409 process_progressive_mode(common); 424 process_progressive_mode(common);
410
411 } 425 }
412} 426}
413 427
@@ -437,8 +451,12 @@ static irqreturn_t vpif_channel_isr(int irq, void *dev_id)
437 continue; 451 continue;
438 452
439 if (1 == ch->vpifparams.std_info.frm_fmt) { 453 if (1 == ch->vpifparams.std_info.frm_fmt) {
440 if (list_empty(&common->dma_queue)) 454 spin_lock(&common->irqlock);
455 if (list_empty(&common->dma_queue)) {
456 spin_unlock(&common->irqlock);
441 continue; 457 continue;
458 }
459 spin_unlock(&common->irqlock);
442 460
443 /* Progressive mode */ 461 /* Progressive mode */
444 if (!channel_first_int[i][channel_id]) { 462 if (!channel_first_int[i][channel_id]) {