]> rtime.felk.cvut.cz Git - zynq/linux.git/blobdiff - drivers/media/usb/uvc/uvc_queue.c
uvcvideo: Prevent new URBs being processed at stream stop
[zynq/linux.git] / drivers / media / usb / uvc / uvc_queue.c
index 9447dab486b4c4f1bbc3974ade6e3b4ddadb8251..dbe24e2b44ed3d96677622d3b2f38eac7666ccaa 100644 (file)
@@ -179,13 +179,24 @@ static void uvc_stop_streaming(struct vb2_queue *vq)
 {
        struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
        struct uvc_streaming *stream = uvc_queue_to_stream(queue);
-       unsigned long flags;
+
+       /* Prevent new buffers coming in. */
+       spin_lock_irq(&queue->irqlock);
+       queue->flags |= UVC_QUEUE_STOPPING;
+       spin_unlock_irq(&queue->irqlock);
+
+       /*
+        * All pending work should be completed before disabling the stream, as
+        * all URBs will be free'd during uvc_video_enable(s, 0).
+        */
+       flush_workqueue(stream->async_wq);
 
        uvc_video_enable(stream, 0);
 
-       spin_lock_irqsave(&queue->irqlock, flags);
+       spin_lock_irq(&queue->irqlock);
        uvc_queue_return_buffers(queue, UVC_BUF_STATE_ERROR);
-       spin_unlock_irqrestore(&queue->irqlock, flags);
+       queue->flags &= ~UVC_QUEUE_STOPPING;
+       spin_unlock_irq(&queue->irqlock);
 }
 
 static const struct vb2_ops uvc_queue_qops = {