diff options
author | Liu Ying <b17645@freescale.com> | 2009-12-23 18:46:44 -0500 |
---|---|---|
committer | Liu Ying <b17645@freescale.com> | 2009-12-23 18:46:44 -0500 |
commit | 980b76bf7f6e382408a8062fdef201e41be084fd (patch) | |
tree | 09dec09b26310f904142361478e7639393989bd4 /drivers/media | |
parent | f9fdfe6805e816b60d65cc0ea74dcadfd4e12e50 (diff) |
ENGR00119582 V4L2 capture:Fix race condition for accessing kernel resource
Some kernel resource can be accessed in interrupt handler and user
controlled V4L2 ioctrls, so there is a race condition which makes
the kernel malfunction potentially.
Signed-off-by: Liu Ying <b17645@freescale.com>
Diffstat (limited to 'drivers/media')
-rw-r--r-- | drivers/media/video/mxc/capture/csi_v4l2_capture.c | 12 | ||||
-rw-r--r-- | drivers/media/video/mxc/capture/mxc_v4l2_capture.c | 12 | ||||
-rw-r--r-- | drivers/media/video/mxc/capture/mxc_v4l2_capture.h | 3 |
3 files changed, 20 insertions, 7 deletions
diff --git a/drivers/media/video/mxc/capture/csi_v4l2_capture.c b/drivers/media/video/mxc/capture/csi_v4l2_capture.c index a0762940567e..9bddc3692996 100644 --- a/drivers/media/video/mxc/capture/csi_v4l2_capture.c +++ b/drivers/media/video/mxc/capture/csi_v4l2_capture.c @@ -626,6 +626,7 @@ static int csi_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf) { int retval = 0; struct mxc_v4l_frame *frame; + unsigned long lock_flags; if (!wait_event_interruptible_timeout(cam->enc_queue, cam->enc_counter != 0, 10 * HZ)) { @@ -638,6 +639,8 @@ static int csi_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf) return -ERESTARTSYS; } + spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags); + cam->enc_counter--; frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue); @@ -656,6 +659,8 @@ static int csi_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf) retval = -EINVAL; } + spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags); + buf->bytesused = cam->v2f.fmt.pix.sizeimage; buf->index = frame->index; buf->flags = frame->buffer.flags; @@ -987,7 +992,7 @@ static long csi_v4l_do_ioctl(struct file *file, int index = buf->index; pr_debug(" case VIDIOC_QBUF\n"); - spin_lock_irqsave(&cam->int_lock, lock_flags); + spin_lock_irqsave(&cam->queue_int_lock, lock_flags); cam->frame[index].buffer.m.offset = buf->m.offset; if ((cam->frame[index].buffer.flags & 0x7) == V4L2_BUF_FLAG_MAPPED) { @@ -1024,7 +1029,7 @@ static long csi_v4l_do_ioctl(struct file *file, retval = -EINVAL; } buf->flags = cam->frame[index].buffer.flags; - spin_unlock_irqrestore(&cam->int_lock, lock_flags); + spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags); break; } @@ -1227,7 +1232,8 @@ static void init_camera_struct(cam_data *cam) cam->enc_callback = camera_callback; csi_start_callback(cam); init_waitqueue_head(&cam->power_queue); - spin_lock_init(&cam->int_lock); + spin_lock_init(&cam->queue_int_lock); + spin_lock_init(&cam->dqueue_int_lock); } /*! diff --git a/drivers/media/video/mxc/capture/mxc_v4l2_capture.c b/drivers/media/video/mxc/capture/mxc_v4l2_capture.c index 9d69219b06c1..62c190dd05c9 100644 --- a/drivers/media/video/mxc/capture/mxc_v4l2_capture.c +++ b/drivers/media/video/mxc/capture/mxc_v4l2_capture.c @@ -1265,6 +1265,7 @@ static int mxc_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf) { int retval = 0; struct mxc_v4l_frame *frame; + unsigned long lock_flags; pr_debug("In MVC:mxc_v4l_dqueue\n"); @@ -1280,6 +1281,8 @@ static int mxc_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf) return -ERESTARTSYS; } + spin_lock_irqsave(&cam->dqueue_int_lock, lock_flags); + cam->enc_counter--; frame = list_entry(cam->done_q.next, struct mxc_v4l_frame, queue); @@ -1297,6 +1300,8 @@ static int mxc_v4l_dqueue(cam_data *cam, struct v4l2_buffer *buf) retval = -EINVAL; } + spin_unlock_irqrestore(&cam->dqueue_int_lock, lock_flags); + buf->bytesused = cam->v2f.fmt.pix.sizeimage; buf->index = frame->index; buf->flags = frame->buffer.flags; @@ -1723,7 +1728,7 @@ static long mxc_v4l_do_ioctl(struct file *file, int index = buf->index; pr_debug(" case VIDIOC_QBUF\n"); - spin_lock_irqsave(&cam->int_lock, lock_flags); + spin_lock_irqsave(&cam->queue_int_lock, lock_flags); cam->frame[index].buffer.m.offset = buf->m.offset; if ((cam->frame[index].buffer.flags & 0x7) == V4L2_BUF_FLAG_MAPPED) { @@ -1760,7 +1765,7 @@ static long mxc_v4l_do_ioctl(struct file *file, } buf->flags = cam->frame[index].buffer.flags; - spin_unlock_irqrestore(&cam->int_lock, lock_flags); + spin_unlock_irqrestore(&cam->queue_int_lock, lock_flags); break; } @@ -2322,7 +2327,8 @@ static void init_camera_struct(cam_data *cam) cam->enc_callback = camera_callback; init_waitqueue_head(&cam->power_queue); - spin_lock_init(&cam->int_lock); + spin_lock_init(&cam->queue_int_lock); + spin_lock_init(&cam->dqueue_int_lock); } /*! diff --git a/drivers/media/video/mxc/capture/mxc_v4l2_capture.h b/drivers/media/video/mxc/capture/mxc_v4l2_capture.h index a9c0c4d159da..7982b5cf4308 100644 --- a/drivers/media/video/mxc/capture/mxc_v4l2_capture.h +++ b/drivers/media/video/mxc/capture/mxc_v4l2_capture.h @@ -108,7 +108,8 @@ typedef struct _cam_data { struct list_head done_q; struct list_head working_q; int ping_pong_csi; - spinlock_t int_lock; + spinlock_t queue_int_lock; + spinlock_t dqueue_int_lock; struct mxc_v4l_frame frame[FRAME_NUM]; int skip_frame; wait_queue_head_t enc_queue; |