summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@infradead.org>2008-04-13 12:08:55 -0300
committerMauro Carvalho Chehab <mchehab@infradead.org>2008-04-13 12:08:55 -0300
commitc46748191d2f1175c2211b5ed20332935d06c9a8 (patch)
tree6b05cdaefcc6fd21d4e3e0ab53e96a2bfe401e3d
parent554dd58d9f1afff01a8d3e24d09f48e3e18566a1 (diff)
downloadmediapointer-dvb-s2-c46748191d2f1175c2211b5ed20332935d06c9a8.tar.gz
mediapointer-dvb-s2-c46748191d2f1175c2211b5ed20332935d06c9a8.tar.bz2
em28xx: Add missing checks
From: Mauro Carvalho Chehab <mchehab@infradead.org> 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>
-rw-r--r--linux/drivers/media/video/em28xx/em28xx-video.c37
1 files changed, 25 insertions, 12 deletions
diff --git a/linux/drivers/media/video/em28xx/em28xx-video.c b/linux/drivers/media/video/em28xx/em28xx-video.c
index 53e460cf9..0d8b359d1 100644
--- a/linux/drivers/media/video/em28xx/em28xx-video.c
+++ b/linux/drivers/media/video/em28xx/em28xx-video.c
@@ -290,24 +290,40 @@ static inline int get_next_buf(struct em28xx_dmaqueue *dma_q,
struct em28xx_buffer **buf)
{
struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
-#if 0
+#if 1
char *outp;
#endif
- /* If the previous buffer were not filled yet, continue */
+ if (list_empty(&dma_q->active)) {
+ em28xx_isocdbg("No active queue to serve\n");
+ dev->isoc_ctl.buf = NULL;
+ return 0;
+ }
+
+ /* Check if the last buffer were fully filled */
*buf = dev->isoc_ctl.buf;
+
+ /* Nobody is waiting on this buffer - discards */
+ if (*buf && !waitqueue_active(&(*buf)->vb.done)) {
+ dev->isoc_ctl.buf = NULL;
+ *buf = NULL;
+ }
+
+ /* Returns the last buffer, to be filled with remaining data */
if (*buf)
return 1;
- if (list_empty(&dma_q->active)) {
+ /* Get the next buffer */
+ *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
+
+ /* Nobody is waiting on the next buffer. returns */
+ if (!*buf || !waitqueue_active(&(*buf)->vb.done)) {
em28xx_isocdbg("No active queue to serve\n");
return 0;
}
- *buf = list_entry(dma_q->active.next, struct em28xx_buffer, vb.queue);
-
-#if 0
- /* Cleans up buffer - Usefull for testing for frame continuity */
+#if 1
+ /* Cleans up buffer - Usefull for testing for frame/URB loss */
outp = videobuf_to_vmalloc(&(*buf)->vb);
memset(outp, 0, (*buf)->vb.size);
#endif
@@ -419,12 +435,11 @@ static void em28xx_irq_callback(struct urb *urb)
struct em28xx_dmaqueue *dma_q = urb->context;
struct em28xx *dev = container_of(dma_q, struct em28xx, vidq);
int rc, i;
- unsigned long flags;
-
- spin_lock_irqsave(&dev->slock, flags);
/* Copy data from URB */
+ spin_lock(&dev->slock);
rc = em28xx_isoc_copy(urb);
+ spin_unlock(&dev->slock);
/* Reset urb buffers */
for (i = 0; i < urb->number_of_packets; i++) {
@@ -438,8 +453,6 @@ static void em28xx_irq_callback(struct urb *urb)
em28xx_err("urb resubmit failed (error=%i)\n",
urb->status);
}
-
- spin_unlock_irqrestore(&dev->slock, flags);
}
/*