summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLiu Ying <b17645@freescale.com>2009-12-23 18:46:44 -0500
committerLiu Ying <b17645@freescale.com>2009-12-23 18:46:44 -0500
commit980b76bf7f6e382408a8062fdef201e41be084fd (patch)
tree09dec09b26310f904142361478e7639393989bd4
parentf9fdfe6805e816b60d65cc0ea74dcadfd4e12e50 (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>
-rw-r--r--drivers/media/video/mxc/capture/csi_v4l2_capture.c12
-rw-r--r--drivers/media/video/mxc/capture/mxc_v4l2_capture.c12
-rw-r--r--drivers/media/video/mxc/capture/mxc_v4l2_capture.h3
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;