diff options
author | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-04-13 14:08:55 -0400 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@infradead.org> | 2008-04-24 13:09:39 -0400 |
commit | dbecb44c11d9517d604240b53581951ac4e3b5e6 (patch) | |
tree | 3bf65736b1ae105e16227110452aa72d2dc21847 /drivers/media/video/em28xx/em28xx-video.c | |
parent | 0cf4daee31d88086cf3508d1d8d1f4e451c27906 (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.c | 35 |
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 | /* |