{
        struct au0828_dmaqueue  *dma_q = urb->context;
        struct au0828_dev *dev = container_of(dma_q, struct au0828_dev, vidq);
+       unsigned long flags = 0;
        int rc, i;
 
        switch (urb->status) {
        }
 
        /* Copy data from URB */
-       spin_lock(&dev->slock);
+       spin_lock_irqsave(&dev->slock, flags);
        rc = dev->isoc_ctl.isoc_copy(dev, urb);
-       spin_unlock(&dev->slock);
+       spin_unlock_irqrestore(&dev->slock, flags);
 
        /* Reset urb buffers */
        for (i = 0; i < urb->number_of_packets; i++) {
 
        list_del(&buf->vb.queue);
        wake_up(&buf->vb.done);
-
-       /* Reset the timer for "no video condition" */
-       mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
 }
 
 static inline void vbi_buffer_filled(struct au0828_dev *dev,
 
        list_del(&buf->vb.queue);
        wake_up(&buf->vb.done);
-
-       /* Reset the timer for "no video condition" */
-       mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
 }
 
 /*
                                        outp = NULL;
                                else
                                        outp = videobuf_to_vmalloc(&buf->vb);
+
+                               /* As long as isoc traffic is arriving, keep
+                                  resetting the timer */
+                               if (dev->vid_timeout_running)
+                                       mod_timer(&dev->vid_timeout,
+                                                 jiffies + (HZ / 10));
+                               if (dev->vbi_timeout_running)
+                                       mod_timer(&dev->vbi_timeout,
+                                                 jiffies + (HZ / 10));
                        }
 
                        if (buf != NULL) {
        struct au0828_dmaqueue *dma_q = &dev->vidq;
        struct au0828_buffer *buf;
        unsigned char *vid_data;
+       unsigned long flags = 0;
 
-       spin_lock(&dev->slock);
+       spin_lock_irqsave(&dev->slock, flags);
 
        buf = dev->isoc_ctl.buf;
        if (buf != NULL) {
                vid_data = videobuf_to_vmalloc(&buf->vb);
                memset(vid_data, 0x00, buf->vb.size); /* Blank green frame */
                buffer_filled(dev, dma_q, buf);
-               get_next_buf(dma_q, &buf);
        }
+       get_next_buf(dma_q, &buf);
+
+       if (dev->vid_timeout_running == 1)
+               mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
 
-       spin_unlock(&dev->slock);
+       spin_unlock_irqrestore(&dev->slock, flags);
 }
 
 void au0828_vbi_buffer_timeout(unsigned long data)
        struct au0828_dmaqueue *dma_q = &dev->vbiq;
        struct au0828_buffer *buf;
        unsigned char *vbi_data;
+       unsigned long flags = 0;
 
-       spin_lock(&dev->slock);
+       spin_lock_irqsave(&dev->slock, flags);
 
        buf = dev->isoc_ctl.vbi_buf;
        if (buf != NULL) {
                vbi_data = videobuf_to_vmalloc(&buf->vb);
                memset(vbi_data, 0x00, buf->vb.size);
                vbi_buffer_filled(dev, dma_q, buf);
-               vbi_get_next_buf(dma_q, &buf);
        }
+       vbi_get_next_buf(dma_q, &buf);
 
-       spin_unlock(&dev->slock);
+       if (dev->vbi_timeout_running == 1)
+               mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
+       spin_unlock_irqrestore(&dev->slock, flags);
 }
 
 
                                    V4L2_FIELD_SEQ_TB,
                                    sizeof(struct au0828_buffer), fh, NULL);
 
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-               dev->vid_timeout.function = au0828_vid_buffer_timeout;
-               dev->vid_timeout.data = (unsigned long) dev;
-               init_timer(&dev->vid_timeout);
-       } else {
-               dev->vbi_timeout.function = au0828_vbi_buffer_timeout;
-               dev->vbi_timeout.data = (unsigned long) dev;
-               init_timer(&dev->vbi_timeout);
-       }
-
        return ret;
 }
 
        struct au0828_dev *dev = fh->dev;
 
        if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
-               del_timer(&dev->vid_timeout);
+               /* Cancel timeout thread in case they didn't call streamoff */
+               dev->vid_timeout_running = 0;
+               del_timer_sync(&dev->vid_timeout);
+
                videobuf_stop(&fh->vb_vidq);
                res_free(fh, AU0828_RESOURCE_VIDEO);
        }
 
        if (res_check(fh, AU0828_RESOURCE_VBI)) {
-               del_timer(&dev->vbi_timeout);
+               /* Cancel timeout thread in case they didn't call streamoff */
+               dev->vbi_timeout_running = 0;
+               del_timer_sync(&dev->vbi_timeout);
+
                videobuf_stop(&fh->vb_vbiq);
                res_free(fh, AU0828_RESOURCE_VBI);
        }
                v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
        }
 
-       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
+       if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
                rc = videobuf_streamon(&fh->vb_vidq);
-       else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
+               dev->vid_timeout_running = 1;
+               mod_timer(&dev->vid_timeout, jiffies + (HZ / 10));
+       } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
                rc = videobuf_streamon(&fh->vb_vbiq);
+               dev->vbi_timeout_running = 1;
+               mod_timer(&dev->vbi_timeout, jiffies + (HZ / 10));
+       }
 
        return rc;
 }
                fh, type, fh->resources, dev->resources);
 
        if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               dev->vid_timeout_running = 0;
+               del_timer_sync(&dev->vid_timeout);
+
                v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
                rc = au0828_stream_interrupt(dev);
                if (rc != 0)
                videobuf_streamoff(&fh->vb_vidq);
                res_free(fh, AU0828_RESOURCE_VIDEO);
        } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+               dev->vbi_timeout_running = 0;
+               del_timer_sync(&dev->vbi_timeout);
+
                videobuf_streamoff(&fh->vb_vbiq);
                res_free(fh, AU0828_RESOURCE_VBI);
        }
        INIT_LIST_HEAD(&dev->vbiq.active);
        INIT_LIST_HEAD(&dev->vbiq.queued);
 
+       dev->vid_timeout.function = au0828_vid_buffer_timeout;
+       dev->vid_timeout.data = (unsigned long) dev;
+       init_timer(&dev->vid_timeout);
+
+       dev->vbi_timeout.function = au0828_vbi_buffer_timeout;
+       dev->vbi_timeout.data = (unsigned long) dev;
+       init_timer(&dev->vbi_timeout);
+
        dev->width = NTSC_STD_W;
        dev->height = NTSC_STD_H;
        dev->field_size = dev->width * dev->height;