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; uvc_video_enable(stream, 0); spin_lock_irqsave(&queue->irqlock, flags); uvc_queue_return_buffers(queue, UVC_BUF_STATE_ERROR); spin_unlock_irqrestore(&queue->irqlock, flags); }
/* * Cancel the video buffers queue. * * Cancelling the queue marks all buffers on the irq queue as erroneous, * wakes them up and removes them from the queue. * * If the disconnect parameter is set, further calls to uvc_queue_buffer will * fail with -ENODEV. * * This function acquires the irq spinlock and can be called from interrupt * context. */ void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect) { unsigned long flags; spin_lock_irqsave(&queue->irqlock, flags); uvc_queue_return_buffers(queue, UVC_BUF_STATE_ERROR); /* This must be protected by the irqlock spinlock to avoid race * conditions between uvc_buffer_queue and the disconnection event that * could result in an interruptible wait in uvc_dequeue_buffer. Do not * blindly replace this logic by checking for the UVC_QUEUE_DISCONNECTED * state outside the queue code. */ if (disconnect) queue->flags |= UVC_QUEUE_DISCONNECTED; spin_unlock_irqrestore(&queue->irqlock, flags); }
static int uvc_start_streaming(struct vb2_queue *vq, unsigned int count) { struct uvc_video_queue *queue = vb2_get_drv_priv(vq); struct uvc_streaming *stream = uvc_queue_to_stream(queue); unsigned long flags; int ret; queue->buf_used = 0; ret = uvc_video_enable(stream, 1); if (ret == 0) return 0; spin_lock_irqsave(&queue->irqlock, flags); uvc_queue_return_buffers(queue, UVC_BUF_STATE_QUEUED); spin_unlock_irqrestore(&queue->irqlock, flags); return ret; }
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); /* 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); if (vq->type != V4L2_BUF_TYPE_META_CAPTURE) uvc_video_enable(uvc_queue_to_stream(queue), 0); spin_lock_irq(&queue->irqlock); uvc_queue_return_buffers(queue, UVC_BUF_STATE_ERROR); queue->flags &= ~UVC_QUEUE_STOPPING; spin_unlock_irq(&queue->irqlock); }