]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
ENGR00227472 MXC V4L2 capture:Improve resource lock
authorLiu Ying <Ying.Liu@freescale.com>
Mon, 8 Oct 2012 07:55:04 +0000 (15:55 +0800)
committerLothar Waßmann <LW@KARO-electronics.de>
Fri, 24 May 2013 06:35:32 +0000 (08:35 +0200)
1) We get busy_lock semaphore before we get a dqueue event, so, when user
is blocked at DQBUF ioctrl, the user will also be blocked at QBUF ioctrl,
then the video performance will drop. This patch changes to get busy_lock
semaphore to protect DQBUF ioctrl until we successfully get a dqueue event.
2) Use queue_int_lock and dqueue_int_lock spinlocks to protect working_q/
ready_q/done_q in the end of frame interrupt handler camera_callback(), in
case, the handler and VIDIOC_QBUF/VIDIOC_DQBUF ioctrls are called on diff-
erent cores at the same time.
3) Protect ready_q with queue_int_lock spinlock in mxc_streamon(), in case,
VIDIOC_STREAMON and VIDIOC_QBUF ioctrls are called on different cores at
the same time.

Signed-off-by: Liu Ying <Ying.Liu@freescale.com>
(cherry picked from commit e92c2307ebcf66badc5db8d4449218e3489a9e78)

drivers/media/video/mxc/capture/mxc_v4l2_capture.c

index a451dfb311cb2caf629c6815123fd0633bb32f7b..0e82820cfdee7b74155568e60ea5f6fc0fb44140 100644 (file)
@@ -379,6 +379,7 @@ static inline int valid_mode(u32 palette)
 static int mxc_streamon(cam_data *cam)
 {
        struct mxc_v4l_frame *frame;
+       unsigned long lock_flags;
        int err = 0;
 
        pr_debug("In MVC:mxc_streamon\n");
@@ -418,6 +419,7 @@ static int mxc_streamon(cam_data *cam)
                }
        }
 
+       spin_lock_irqsave(&cam->queue_int_lock, lock_flags);
        cam->ping_pong_csi = 0;
        cam->local_buf_num = 0;
        if (cam->enc_update_eba) {
@@ -436,7 +438,9 @@ static int mxc_streamon(cam_data *cam)
                frame->ipu_buf_num = cam->ping_pong_csi;
                err |= cam->enc_update_eba(cam->ipu, frame->buffer.m.offset,
                                           &cam->ping_pong_csi);
+               spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags);
        } else {
+               spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags);
                return -EINVAL;
        }
 
@@ -1513,8 +1517,10 @@ static int mxc_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf)
                return -ERESTARTSYS;
        }
 
-       spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags);
+       if (down_interruptible(&cam->busy_lock))
+               return -EBUSY;
 
+       spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags);
        cam->enc_counter--;
 
        frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue);
@@ -1537,8 +1543,9 @@ static int mxc_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf)
        buf->flags = frame->buffer.flags;
        buf->m = cam->frame[frame->index].buffer.m;
        buf->timestamp = cam->frame[frame->index].buffer.timestamp;
-
        spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags);
+
+       up(&cam->busy_lock);
        return retval;
 }
 
@@ -1881,8 +1888,9 @@ static long mxc_v4l_do_ioctl(struct file *file,
        pr_debug("In MVC: mxc_v4l_do_ioctl %x\n", ioctlnr);
        wait_event_interruptible(cam->power_queue, cam->low_power == false);
        /* make this _really_ smp-safe */
-       if (down_interruptible(&cam->busy_lock))
-               return -EBUSY;
+       if (ioctlnr != VIDIOC_DQBUF)
+               if (down_interruptible(&cam->busy_lock))
+                       return -EBUSY;
 
        switch (ioctlnr) {
        /*!
@@ -1943,15 +1951,10 @@ static long mxc_v4l_do_ioctl(struct file *file,
                }
 
                mxc_streamoff(cam);
-               if (req->memory & V4L2_MEMORY_MMAP)
+               if (req->memory & V4L2_MEMORY_MMAP) {
                        mxc_free_frame_buf(cam);
-               cam->enc_counter = 0;
-               INIT_LIST_HEAD(&cam->ready_q);
-               INIT_LIST_HEAD(&cam->working_q);
-               INIT_LIST_HEAD(&cam->done_q);
-
-               if (req->memory & V4L2_MEMORY_MMAP)
                        retval = mxc_allocate_frame_buf(cam, req->count);
+               }
                break;
        }
 
@@ -2376,7 +2379,8 @@ static long mxc_v4l_do_ioctl(struct file *file,
                break;
        }
 
-       up(&cam->busy_lock);
+       if (ioctlnr != VIDIOC_DQBUF)
+               up(&cam->busy_lock);
        return retval;
 }
 
@@ -2510,6 +2514,8 @@ static void camera_callback(u32 mask, void *dev)
 
        pr_debug("In MVC:camera_callback\n");
 
+       spin_lock(&cam->queue_int_lock);
+       spin_lock(&cam->dqueue_int_lock);
        if (!list_empty(&cam->working_q)) {
                do_gettimeofday(&cur_time);
 
@@ -2564,6 +2570,8 @@ next:
        }
 
        cam->local_buf_num = (cam->local_buf_num == 0) ? 1 : 0;
+       spin_unlock(&cam->dqueue_int_lock);
+       spin_unlock(&cam->queue_int_lock);
 
        return;
 }