diff options
Diffstat (limited to 'drivers/media/usb/uvc/uvc_queue.c')
| -rw-r--r-- | drivers/media/usb/uvc/uvc_queue.c | 33 |
1 files changed, 28 insertions, 5 deletions
diff --git a/drivers/media/usb/uvc/uvc_queue.c b/drivers/media/usb/uvc/uvc_queue.c index 8964e16f2b22..74f9483911d0 100644 --- a/drivers/media/usb/uvc/uvc_queue.c +++ b/drivers/media/usb/uvc/uvc_queue.c @@ -430,6 +430,33 @@ void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect) spin_unlock_irqrestore(&queue->irqlock, flags); } +/* + * uvc_queue_get_current_buffer: Obtain the current working output buffer + * + * Buffers may span multiple packets, and even URBs, therefore the active buffer + * remains on the queue until the EOF marker. + */ +static struct uvc_buffer * +__uvc_queue_get_current_buffer(struct uvc_video_queue *queue) +{ + if (list_empty(&queue->irqqueue)) + return NULL; + + return list_first_entry(&queue->irqqueue, struct uvc_buffer, queue); +} + +struct uvc_buffer *uvc_queue_get_current_buffer(struct uvc_video_queue *queue) +{ + struct uvc_buffer *nextbuf; + unsigned long flags; + + spin_lock_irqsave(&queue->irqlock, flags); + nextbuf = __uvc_queue_get_current_buffer(queue); + spin_unlock_irqrestore(&queue->irqlock, flags); + + return nextbuf; +} + struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf) { @@ -446,11 +473,7 @@ struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, spin_lock_irqsave(&queue->irqlock, flags); list_del(&buf->queue); - if (!list_empty(&queue->irqqueue)) - nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer, - queue); - else - nextbuf = NULL; + nextbuf = __uvc_queue_get_current_buffer(queue); spin_unlock_irqrestore(&queue->irqlock, flags); buf->state = buf->error ? UVC_BUF_STATE_ERROR : UVC_BUF_STATE_DONE; |
