aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/media/video/em28xx/em28xx-video.c
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2008-04-13 14:08:55 -0400
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-24 13:09:39 -0400
commitdbecb44c11d9517d604240b53581951ac4e3b5e6 (patch)
tree3bf65736b1ae105e16227110452aa72d2dc21847 /drivers/media/video/em28xx/em28xx-video.c
parent0cf4daee31d88086cf3508d1d8d1f4e451c27906 (diff)
V4L/DVB (7563): em28xx: Add missing checks
There are some cases where nobody is waiting for a buffer. Due to the lack of check, if you try to abort the userspace app, machine were hanging, since IRQ were trying to use a buffer that were disallocated. Signed-off-by: Mauro Carvalho Chehab <mchehab@infradead.org>
Diffstat (limited to 'drivers/media/video/em28xx/em28xx-video.c')
-rw-r--r--drivers/media/video/em28xx/em28xx-video.c35
1 files changed, 26 insertions, 9 deletions
diff --git a/drivers/media/video/em28xx/em28xx-video.c b/drivers/media/video/em28xx/em28xx-video.c
index db3bbacb3a77..10928dccaecc 100644
--- a/drivers/media/video/em28xx/em28xx-video.c
+++ b/drivers/media/video/em28xx/em28xx-video.c
@@ -270,19 +270,39 @@ static inline int get_next_buf(struct em28xx_dmaqueue *dma_q,
270 struct em28xx_buffer **buf) 270 struct em28xx_buffer **buf)
271{ 271{
272 struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); 272 struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
273 char *outp;
273 274
274 /* If the previous buffer were not filled yet, continue */ 275 if (list_empty(&dma_q->active)) {
276 em28xx_isocdbg("No active queue to serve\n");
277 dev->isoc_ctl.buf = NULL;
278 return 0;
279 }
280
281 /* Check if the last buffer were fully filled */
275 *buf = dev->isoc_ctl.buf; 282 *buf = dev->isoc_ctl.buf;
283
284 /* Nobody is waiting on this buffer - discards */
285 if (*buf && !waitqueue_active(&(*buf)->vb.done)) {
286 dev->isoc_ctl.buf = NULL;
287 *buf = NULL;
288 }
289
290 /* Returns the last buffer, to be filled with remaining data */
276 if (*buf) 291 if (*buf)
277 return 1; 292 return 1;
278 293
279 if (list_empty(&dma_q->active)) { 294 /* Get the next buffer */
295 *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
296
297 /* Nobody is waiting on the next buffer. returns */
298 if (!*buf || !waitqueue_active(&(*buf)->vb.done)) {
280 em28xx_isocdbg("No active queue to serve\n"); 299 em28xx_isocdbg("No active queue to serve\n");
281 return 0; 300 return 0;
282 } 301 }
283 302
284 *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue); 303 /* Cleans up buffer - Usefull for testing for frame/URB loss */
285 304 outp = videobuf_to_vmalloc(&(*buf)->vb);
305 memset(outp, 0, (*buf)->vb.size);
286 306
287 dev->isoc_ctl.buf = *buf; 307 dev->isoc_ctl.buf = *buf;
288 308
@@ -387,12 +407,11 @@ static void em28xx_irq_callback(struct urb *urb)
387 struct em28xx_dmaqueue *dma_q = urb->context; 407 struct em28xx_dmaqueue *dma_q = urb->context;
388 struct em28xx *dev = container_of(dma_q, struct em28xx, vidq); 408 struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
389 int rc, i; 409 int rc, i;
390 unsigned long flags;
391
392 spin_lock_irqsave(&dev->slock, flags);
393 410
394 /* Copy data from URB */ 411 /* Copy data from URB */
412 spin_lock(&dev->slock);
395 rc = em28xx_isoc_copy(urb); 413 rc = em28xx_isoc_copy(urb);
414 spin_unlock(&dev->slock);
396 415
397 /* Reset urb buffers */ 416 /* Reset urb buffers */
398 for (i = 0; i < urb->number_of_packets; i++) { 417 for (i = 0; i < urb->number_of_packets; i++) {
@@ -406,8 +425,6 @@ static void em28xx_irq_callback(struct urb *urb)
406 em28xx_err("urb resubmit failed (error=%i)\n", 425 em28xx_err("urb resubmit failed (error=%i)\n",
407 urb->status); 426 urb->status);
408 } 427 }
409
410 spin_unlock_irqrestore(&dev->slock, flags);
411} 428}
412 429
413/* 430/*