aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/cx18
diff options
context:
space:
mode:
authorSimon Farnsworth <simon.farnsworth@onelan.co.uk>2011-09-05 11:23:12 -0400
committerMauro Carvalho Chehab <mchehab@redhat.com>2011-09-18 07:03:39 -0400
commit09fc9802c31a9358a4e34642aa5f569111752879 (patch)
treeb07a8c6e035df000702b3f2bbfaeb8acd85418d6 /drivers/media/video/cx18
parent16e3d2f4fab6e001a79705fa273418afc10188f8 (diff)
[media] cx18: Fix videobuf capture
When we moved to 3.0, we found that the cx18 driver was oopsing on close with: NULL pointer deref at: [ 2290.461009] Call Trace: [ 2290.461009] [<c046007b>] ? pm_qos_add_request+0xc/0x6e [ 2290.461009] [<c082631c>] __mutex_lock_common+0x87/0x125 [ 2290.461009] [<f8970e92>] ? cx18_queue_flush+0x31/0x87 [cx18] [ 2290.461009] [<c0436b85>] ? __might_sleep+0x29/0xe4 [ 2290.461009] [<c0826515>] __mutex_lock_slowpath+0x25/0x27 [ 2290.461009] [<c08264b2>] ? mutex_lock+0x2e/0x3b [ 2290.461009] [<c08264b2>] mutex_lock+0x2e/0x3b [ 2290.461009] [<f88d3137>] videobuf_queue_lock+0x13/0x15 [videobuf_core] [ 2290.461009] [<f88d3f86>] __videobuf_free+0xfc/0x112 [videobuf_core] [ 2290.461009] [<f89741e6>] cx18_v4l2_close+0x158/0x172 [cx18] [ 2290.461009] [<c0507522>] ? cpumask_next+0x1a/0x1d [ 2290.461009] [<f88a319d>] v4l2_release+0x35/0x52 [videodev] [ 2290.461009] [<c04f5717>] fput+0x100/0x1a5 [ 2290.461009] [<c04f2e09>] filp_close+0x5c/0x64 [ 2290.461009] [<c04f2e70>] sys_close+0x5f/0x93 [ 2290.461009] [<c082cd5f>] sysenter_do_call+0x12/0x28 Some digging showed that a merge at some previous point partially added broken mmap() support, causing this trace. Remove the broken code completely. On top of that, the calculation in place for "buffer full" depended on UYUV instead of HM12, while our GStreamer code was picking HM12 in some circumstances. Finally, the V4L2_CAP_STREAMING capability was never exposed. Patch it into the YUV encoder node only. Signed-off-by: Simon Farnsworth <simon.farnsworth@onelan.co.uk> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers/media/video/cx18')
-rw-r--r--drivers/media/video/cx18/cx18-driver.h5
-rw-r--r--drivers/media/video/cx18/cx18-fileops.c2
-rw-r--r--drivers/media/video/cx18/cx18-ioctl.c18
-rw-r--r--drivers/media/video/cx18/cx18-mailbox.c2
-rw-r--r--drivers/media/video/cx18/cx18-streams.c13
5 files changed, 26 insertions, 14 deletions
diff --git a/drivers/media/video/cx18/cx18-driver.h b/drivers/media/video/cx18/cx18-driver.h
index 183420723060..b9a94fc5146d 100644
--- a/drivers/media/video/cx18/cx18-driver.h
+++ b/drivers/media/video/cx18/cx18-driver.h
@@ -409,6 +409,7 @@ struct cx18_stream {
409 409
410 /* Videobuf for YUV video */ 410 /* Videobuf for YUV video */
411 u32 pixelformat; 411 u32 pixelformat;
412 u32 vb_bytes_per_frame;
412 struct list_head vb_capture; /* video capture queue */ 413 struct list_head vb_capture; /* video capture queue */
413 spinlock_t vb_lock; 414 spinlock_t vb_lock;
414 struct timer_list vb_timeout; 415 struct timer_list vb_timeout;
@@ -430,10 +431,6 @@ struct cx18_open_id {
430 u32 open_id; 431 u32 open_id;
431 int type; 432 int type;
432 struct cx18 *cx; 433 struct cx18 *cx;
433
434 struct videobuf_queue vbuf_q;
435 spinlock_t s_lock; /* Protect vbuf_q */
436 enum v4l2_buf_type vb_type;
437}; 434};
438 435
439static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh) 436static inline struct cx18_open_id *fh2id(struct v4l2_fh *fh)
diff --git a/drivers/media/video/cx18/cx18-fileops.c b/drivers/media/video/cx18/cx18-fileops.c
index 07411f34885a..14cb961c22bd 100644
--- a/drivers/media/video/cx18/cx18-fileops.c
+++ b/drivers/media/video/cx18/cx18-fileops.c
@@ -784,8 +784,6 @@ int cx18_v4l2_close(struct file *filp)
784 cx18_release_stream(s); 784 cx18_release_stream(s);
785 } else { 785 } else {
786 cx18_stop_capture(id, 0); 786 cx18_stop_capture(id, 0);
787 if (id->type == CX18_ENC_STREAM_TYPE_YUV)
788 videobuf_mmap_free(&id->vbuf_q);
789 } 787 }
790 kfree(id); 788 kfree(id);
791 mutex_unlock(&cx->serialize_lock); 789 mutex_unlock(&cx->serialize_lock);
diff --git a/drivers/media/video/cx18/cx18-ioctl.c b/drivers/media/video/cx18/cx18-ioctl.c
index afe0a29e7200..66b1c15c3541 100644
--- a/drivers/media/video/cx18/cx18-ioctl.c
+++ b/drivers/media/video/cx18/cx18-ioctl.c
@@ -160,12 +160,7 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
160 pixfmt->priv = 0; 160 pixfmt->priv = 0;
161 if (id->type == CX18_ENC_STREAM_TYPE_YUV) { 161 if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
162 pixfmt->pixelformat = s->pixelformat; 162 pixfmt->pixelformat = s->pixelformat;
163 /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2))) 163 pixfmt->sizeimage = s->vb_bytes_per_frame;
164 UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
165 if (s->pixelformat == V4L2_PIX_FMT_HM12)
166 pixfmt->sizeimage = pixfmt->height * 720 * 3 / 2;
167 else
168 pixfmt->sizeimage = pixfmt->height * 720 * 2;
169 pixfmt->bytesperline = 720; 164 pixfmt->bytesperline = 720;
170 } else { 165 } else {
171 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG; 166 pixfmt->pixelformat = V4L2_PIX_FMT_MPEG;
@@ -296,6 +291,12 @@ static int cx18_s_fmt_vid_cap(struct file *file, void *fh,
296 return -EBUSY; 291 return -EBUSY;
297 292
298 s->pixelformat = fmt->fmt.pix.pixelformat; 293 s->pixelformat = fmt->fmt.pix.pixelformat;
294 /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
295 UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
296 if (s->pixelformat == V4L2_PIX_FMT_HM12)
297 s->vb_bytes_per_frame = h * 720 * 3 / 2;
298 else
299 s->vb_bytes_per_frame = h * 720 * 2;
299 300
300 mbus_fmt.width = cx->cxhdl.width = w; 301 mbus_fmt.width = cx->cxhdl.width = w;
301 mbus_fmt.height = cx->cxhdl.height = h; 302 mbus_fmt.height = cx->cxhdl.height = h;
@@ -463,13 +464,16 @@ static int cx18_s_register(struct file *file, void *fh,
463static int cx18_querycap(struct file *file, void *fh, 464static int cx18_querycap(struct file *file, void *fh,
464 struct v4l2_capability *vcap) 465 struct v4l2_capability *vcap)
465{ 466{
466 struct cx18 *cx = fh2id(fh)->cx; 467 struct cx18_open_id *id = fh2id(fh);
468 struct cx18 *cx = id->cx;
467 469
468 strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver)); 470 strlcpy(vcap->driver, CX18_DRIVER_NAME, sizeof(vcap->driver));
469 strlcpy(vcap->card, cx->card_name, sizeof(vcap->card)); 471 strlcpy(vcap->card, cx->card_name, sizeof(vcap->card));
470 snprintf(vcap->bus_info, sizeof(vcap->bus_info), 472 snprintf(vcap->bus_info, sizeof(vcap->bus_info),
471 "PCI:%s", pci_name(cx->pci_dev)); 473 "PCI:%s", pci_name(cx->pci_dev));
472 vcap->capabilities = cx->v4l2_cap; /* capabilities */ 474 vcap->capabilities = cx->v4l2_cap; /* capabilities */
475 if (id->type == CX18_ENC_STREAM_TYPE_YUV)
476 vcap->capabilities |= V4L2_CAP_STREAMING;
473 return 0; 477 return 0;
474} 478}
475 479
diff --git a/drivers/media/video/cx18/cx18-mailbox.c b/drivers/media/video/cx18/cx18-mailbox.c
index c07191e09fcb..0c7796e76ac0 100644
--- a/drivers/media/video/cx18/cx18-mailbox.c
+++ b/drivers/media/video/cx18/cx18-mailbox.c
@@ -196,7 +196,7 @@ static void cx18_mdl_send_to_videobuf(struct cx18_stream *s,
196 } 196 }
197 197
198 /* If we've filled the buffer as per the callers res then dispatch it */ 198 /* If we've filled the buffer as per the callers res then dispatch it */
199 if (vb_buf->bytes_used >= (vb_buf->vb.width * vb_buf->vb.height * 2)) { 199 if (vb_buf->bytes_used >= s->vb_bytes_per_frame) {
200 dispatch = 1; 200 dispatch = 1;
201 vb_buf->bytes_used = 0; 201 vb_buf->bytes_used = 0;
202 } 202 }
diff --git a/drivers/media/video/cx18/cx18-streams.c b/drivers/media/video/cx18/cx18-streams.c
index 852f420fd271..638cca156b58 100644
--- a/drivers/media/video/cx18/cx18-streams.c
+++ b/drivers/media/video/cx18/cx18-streams.c
@@ -138,6 +138,12 @@ static int cx18_prepare_buffer(struct videobuf_queue *q,
138 buf->tvnorm = cx->std; 138 buf->tvnorm = cx->std;
139 s->pixelformat = pixelformat; 139 s->pixelformat = pixelformat;
140 140
141 /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
142 UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
143 if (s->pixelformat == V4L2_PIX_FMT_HM12)
144 s->vb_bytes_per_frame = height * 720 * 3 / 2;
145 else
146 s->vb_bytes_per_frame = height * 720 * 2;
141 cx18_dma_free(q, s, buf); 147 cx18_dma_free(q, s, buf);
142 } 148 }
143 149
@@ -154,6 +160,12 @@ static int cx18_prepare_buffer(struct videobuf_queue *q,
154 buf->tvnorm = cx->std; 160 buf->tvnorm = cx->std;
155 s->pixelformat = pixelformat; 161 s->pixelformat = pixelformat;
156 162
163 /* HM12 YUV size is (Y=(h*720) + UV=(h*(720/2)))
164 UYUV YUV size is (Y=(h*720) + UV=(h*(720))) */
165 if (s->pixelformat == V4L2_PIX_FMT_HM12)
166 s->vb_bytes_per_frame = height * 720 * 3 / 2;
167 else
168 s->vb_bytes_per_frame = height * 720 * 2;
157 rc = videobuf_iolock(q, &buf->vb, NULL); 169 rc = videobuf_iolock(q, &buf->vb, NULL);
158 if (rc != 0) 170 if (rc != 0)
159 goto fail; 171 goto fail;
@@ -287,6 +299,7 @@ static void cx18_stream_init(struct cx18 *cx, int type)
287 299
288 /* Assume the previous pixel default */ 300 /* Assume the previous pixel default */
289 s->pixelformat = V4L2_PIX_FMT_HM12; 301 s->pixelformat = V4L2_PIX_FMT_HM12;
302 s->vb_bytes_per_frame = cx->cxhdl.height * 720 * 3 / 2;
290 } 303 }
291} 304}
292 305