mirror of
https://github.com/torvalds/linux.git
synced 2024-12-30 14:52:05 +00:00
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:
parent
c6d664fe8a
commit
e829b262a6
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user