]> Gitweb @ Texas Instruments - Open Source Git Repositories - git.TI.com/gitweb - android-sdk/kernel-video.git/commitdiff
v4l: ti-vps: vip: Different list_head for dequeue list vip
authorNikhil Devshatwar <nikhil.nd@ti.com>
Mon, 28 Apr 2014 14:21:14 +0000 (19:51 +0530)
committerRakesh Movva <r-movva@ti.com>
Thu, 1 May 2014 19:30:21 +0000 (14:30 -0500)
VIP driver maintains two lists
stream->vidq = List of buffers which are queued by user space (queue)
dev->vip_bufs = List of buffers waiting for DMA completion (dequeue)

At any point of time, a buffer would be present in only one of them.
But when buffers are dropped continously, and suddenly user space starts
queueing the buffers, some buffers need to be held by the dequeue list
even if they are already dequeued. This scenario causes list corruption
and eventually kernel crash.

Solution to this problem would be to use a different list for maintaining
buffers which are waiting for DMA. This would allow referencing the buffer
from both lists.

Change-Id: I5a615f32a183eecc33e01a3f71b2a4885be9b047
Signed-off-by: Nikhil Devshatwar <nikhil.nd@ti.com>
drivers/media/platform/ti-vps/vip.c
drivers/media/platform/ti-vps/vip.h

index 7bb7513e4f53463ebad4ed43e0860e8f7de73378..38982275f053186172e316d45437ac8cdf90b631 100644 (file)
@@ -932,7 +932,8 @@ static void vip_active_buf_next(struct vip_stream *stream)
        if (list_empty(&stream->vidq)) {
                vip_dprintk(dev, "Dropping frame");
                /* Increment drop_count for last buffer in the list */
-               buf = list_entry(dev->vip_bufs.prev, struct vip_buffer, list);
+               buf = list_entry(dev->vip_bufs.prev,
+                               struct vip_buffer, dq_list);
                buf->drop_count++;
                buf = NULL;
 
@@ -940,7 +941,8 @@ static void vip_active_buf_next(struct vip_stream *stream)
                buf = list_entry(stream->vidq.next, struct vip_buffer, list);
                buf->drop_count = 0;
                buf->allow_dq = true;
-               list_move_tail(&buf->list, &dev->vip_bufs);
+               list_del(&buf->list);
+               list_add_tail(&buf->dq_list, &dev->vip_bufs);
        } else {
                v4l2_err(&dev->v4l2_dev, "IRQ occurred when not streaming");
                spin_unlock_irqrestore(&dev->slock, flags);
@@ -958,7 +960,7 @@ static void vip_process_buffer_complete(struct vip_stream *stream)
        struct vip_buffer *buf;
        unsigned long flags, fld;
 
-       buf = list_first_entry(&dev->vip_bufs, struct vip_buffer, list);
+       buf = list_first_entry(&dev->vip_bufs, struct vip_buffer, dq_list);
 
        if (stream->port->flags & FLAG_INTERLACED) {
                vpdma_buf_unmap(dev->shared->vpdma, &dev->desc_list.buf);
@@ -977,7 +979,7 @@ static void vip_process_buffer_complete(struct vip_stream *stream)
 
                if (buf->drop_count-- == 0) {
                        spin_lock_irqsave(&dev->slock, flags);
-                       list_del(&buf->list);
+                       list_del(&buf->dq_list);
                        spin_unlock_irqrestore(&dev->slock, flags);
                }
 
@@ -1537,7 +1539,8 @@ static int vip_start_streaming(struct vb2_queue *vq, unsigned int count)
                return -EBUSY;
        }
 
-       list_move_tail(&buf->list, &dev->vip_bufs);
+       list_del(&buf->list);
+       list_add_tail(&buf->dq_list, &dev->vip_bufs);
        spin_unlock_irqrestore(&dev->slock, flags);
 
        start_dma(dev, buf);
@@ -1564,8 +1567,9 @@ static int vip_stop_streaming(struct vb2_queue *vq)
        disable_irqs(dev, dev->slice_id);
        /* release all active buffers */
        while (!list_empty(&dev->vip_bufs)) {
-               buf = list_entry(dev->vip_bufs.next, struct vip_buffer, list);
-               list_del(&buf->list);
+               buf = list_entry(dev->vip_bufs.next,
+                               struct vip_buffer, dq_list);
+               list_del(&buf->dq_list);
                vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
        }
        while (!list_empty(&stream->vidq)) {
index 8cf04ef770d97e17a1bb5f463bbfb9be23910d17..1b41164f7888219707f0094113e6682d141d4148 100644 (file)
@@ -38,6 +38,7 @@ struct vip_buffer {
        /* common v4l buffer stuff */
        struct vb2_buffer       vb;
        struct list_head        list;
+       struct list_head        dq_list;
        /* Number of buffers to drop after this */
        int                     drop_count;
        /* To make sure same buffer isn't dequeued again */