media: uvcvideo: Protect queue internals with helper

The URB completion operation obtains the current buffer by reading
directly into the queue internal interface.

Protect this queue abstraction by providing a helper
uvc_queue_get_current_buffer() which can be used by both the decode
task, and the uvc_queue_next_buffer() functions.

Signed-off-by: Kieran Bingham <kieran.bingham@ideasonboard.com>
Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
Signed-off-by: Mauro Carvalho Chehab <mchehab+samsung@kernel.org>
This commit is contained in:
Kieran Bingham 2017-03-23 08:25:14 -04:00 committed by Mauro Carvalho Chehab
parent c6d664fe8a
commit e829b262a6
3 changed files with 30 additions and 10 deletions

View File

@ -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;

View File

@ -1484,11 +1484,7 @@ static void uvc_video_complete(struct urb *urb)
return;
}
spin_lock_irqsave(&queue->irqlock, flags);
if (!list_empty(&queue->irqqueue))
buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
queue);
spin_unlock_irqrestore(&queue->irqlock, flags);
buf = uvc_queue_get_current_buffer(queue);
if (vb2_qmeta) {
spin_lock_irqsave(&qmeta->irqlock, flags);

View File

@ -728,6 +728,7 @@ int uvc_queue_streamoff(struct uvc_video_queue *queue, enum v4l2_buf_type type);
void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
struct uvc_buffer *buf);
struct uvc_buffer *uvc_queue_get_current_buffer(struct uvc_video_queue *queue);
int uvc_queue_mmap(struct uvc_video_queue *queue,
struct vm_area_struct *vma);
__poll_t uvc_queue_poll(struct uvc_video_queue *queue, struct file *file,