1cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart/*
2cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *	uvc_queue.c  --  USB Video Class driver - Buffers management
3cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
4cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *	Copyright (C) 2005-2010
5cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *	    Laurent Pinchart (laurent.pinchart@ideasonboard.com)
6cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
7cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *	This program is free software; you can redistribute it and/or modify
8cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *	it under the terms of the GNU General Public License as published by
9cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *	the Free Software Foundation; either version 2 of the License, or
10cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *	(at your option) any later version.
11cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart */
12cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
13cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart#include <linux/kernel.h>
14cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart#include <linux/mm.h>
15cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart#include <linux/list.h>
16cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart#include <linux/module.h>
17cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart#include <linux/usb.h>
18cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart#include <linux/videodev2.h>
19cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart#include <linux/vmalloc.h>
20cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart#include <linux/wait.h>
2160063497a95e716c9a689af3be2687d261f115b4Arun Sharma#include <linux/atomic.h>
22cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
23cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart#include "uvc.h"
24cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
25cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart/* ------------------------------------------------------------------------
26cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Video buffers queue management.
27cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
28cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Video queues is initialized by uvc_queue_init(). The function performs
29cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * basic initialization of the uvc_video_queue struct and never fails.
30cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
31cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Video buffer allocation and freeing are performed by uvc_alloc_buffers and
32cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * uvc_free_buffers respectively. The former acquires the video queue lock,
33cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * while the later must be called with the lock held (so that allocation can
34cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * free previously allocated buffers). Trying to free buffers that are mapped
35cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * to user space will return -EBUSY.
36cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
37cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Video buffers are managed using two queues. However, unlike most USB video
38cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * drivers that use an in queue and an out queue, we use a main queue to hold
39cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * all queued buffers (both 'empty' and 'done' buffers), and an irq queue to
40cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * hold empty buffers. This design (copied from video-buf) minimizes locking
41cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * in interrupt, as only one queue is shared between interrupt and user
42cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * contexts.
43cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
44cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Use cases
45cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * ---------
46cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
47cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Unless stated otherwise, all operations that modify the irq buffers queue
48cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * are protected by the irq spinlock.
49cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
50cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * 1. The user queues the buffers, starts streaming and dequeues a buffer.
51cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
52cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    The buffers are added to the main and irq queues. Both operations are
53cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    protected by the queue lock, and the later is protected by the irq
54cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    spinlock as well.
55cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
56cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    The completion handler fetches a buffer from the irq queue and fills it
57cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    with video data. If no buffer is available (irq queue empty), the handler
58cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    returns immediately.
59cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
60cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    When the buffer is full, the completion handler removes it from the irq
61cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    queue, marks it as ready (UVC_BUF_STATE_DONE) and wakes its wait queue.
62cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    At that point, any process waiting on the buffer will be woken up. If a
63cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    process tries to dequeue a buffer after it has been marked ready, the
64cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    dequeing will succeed immediately.
65cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
66cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * 2. Buffers are queued, user is waiting on a buffer and the device gets
67cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    disconnected.
68cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
69cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    When the device is disconnected, the kernel calls the completion handler
70cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    with an appropriate status code. The handler marks all buffers in the
71cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    irq queue as being erroneous (UVC_BUF_STATE_ERROR) and wakes them up so
72cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    that any process waiting on a buffer gets woken up.
73cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
74cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    Waking up up the first buffer on the irq list is not enough, as the
75cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    process waiting on the buffer might restart the dequeue operation
76cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *    immediately.
77cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
78cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart */
79cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
805d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartstatic void
815d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartuvc_queue_init(struct uvc_video_queue *queue, enum v4l2_buf_type type)
82cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart{
83cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	mutex_init(&queue->mutex);
84cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	spin_lock_init(&queue->irqlock);
85cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	INIT_LIST_HEAD(&queue->mainqueue);
86cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	INIT_LIST_HEAD(&queue->irqqueue);
87cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	queue->type = type;
88cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart}
89cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
90cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart/*
915d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart * Free the video buffers.
925d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart *
935d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart * This function must be called with the queue lock held.
945d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart */
955d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartstatic int uvc_free_buffers(struct uvc_video_queue *queue)
965d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart{
975d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	unsigned int i;
985d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart
995d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	for (i = 0; i < queue->count; ++i) {
1005d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart		if (queue->buffer[i].vma_use_count != 0)
1015d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart			return -EBUSY;
1025d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	}
1035d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart
1045d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	if (queue->count) {
1055d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart		vfree(queue->mem);
1065d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart		queue->count = 0;
1075d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	}
1085d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart
1095d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	return 0;
1105d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart}
1115d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart
1125d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart/*
113cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Allocate the video buffers.
114cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
115cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Pages are reserved to make sure they will not be swapped, as they will be
116cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * filled in the URB completion handler.
117cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
118cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Buffers will be individually mapped, so they must all be page aligned.
119cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart */
1205d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartstatic int
1215d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartuvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers,
1225d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart		  unsigned int buflength)
123cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart{
124cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	unsigned int bufsize = PAGE_ALIGN(buflength);
125cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	unsigned int i;
126cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	void *mem = NULL;
127cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	int ret;
128cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
129cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (nbuffers > UVC_MAX_VIDEO_BUFFERS)
130cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		nbuffers = UVC_MAX_VIDEO_BUFFERS;
131cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
132cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	mutex_lock(&queue->mutex);
133cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
134cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if ((ret = uvc_free_buffers(queue)) < 0)
135cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		goto done;
136cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
137cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	/* Bail out if no buffers should be allocated. */
138cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (nbuffers == 0)
139cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		goto done;
140cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
141cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	/* Decrement the number of buffers until allocation succeeds. */
142cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	for (; nbuffers > 0; --nbuffers) {
143cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		mem = vmalloc_32(nbuffers * bufsize);
144cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		if (mem != NULL)
145cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart			break;
146cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
147cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
148cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (mem == NULL) {
149cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		ret = -ENOMEM;
150cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		goto done;
151cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
152cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
153cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	for (i = 0; i < nbuffers; ++i) {
154cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		memset(&queue->buffer[i], 0, sizeof queue->buffer[i]);
155cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		queue->buffer[i].buf.index = i;
156cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		queue->buffer[i].buf.m.offset = i * bufsize;
157cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		queue->buffer[i].buf.length = buflength;
158cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		queue->buffer[i].buf.type = queue->type;
159cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		queue->buffer[i].buf.sequence = 0;
160cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		queue->buffer[i].buf.field = V4L2_FIELD_NONE;
161cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP;
162cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		queue->buffer[i].buf.flags = 0;
163cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		init_waitqueue_head(&queue->buffer[i].wait);
164cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
165cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
166cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	queue->mem = mem;
167cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	queue->count = nbuffers;
168cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	queue->buf_size = bufsize;
169cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	ret = nbuffers;
170cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
171cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchartdone:
172cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	mutex_unlock(&queue->mutex);
173cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	return ret;
174cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart}
175cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
176cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchartstatic void __uvc_query_buffer(struct uvc_buffer *buf,
177cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		struct v4l2_buffer *v4l2_buf)
178cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart{
179cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	memcpy(v4l2_buf, &buf->buf, sizeof *v4l2_buf);
180cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
181cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (buf->vma_use_count)
182cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		v4l2_buf->flags |= V4L2_BUF_FLAG_MAPPED;
183cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
184cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	switch (buf->state) {
185cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	case UVC_BUF_STATE_ERROR:
186cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	case UVC_BUF_STATE_DONE:
187cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		v4l2_buf->flags |= V4L2_BUF_FLAG_DONE;
188cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		break;
189cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	case UVC_BUF_STATE_QUEUED:
190cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	case UVC_BUF_STATE_ACTIVE:
191cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		v4l2_buf->flags |= V4L2_BUF_FLAG_QUEUED;
192cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		break;
193cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	case UVC_BUF_STATE_IDLE:
194cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	default:
195cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		break;
196cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
197cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart}
198cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
1995d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartstatic int
2005d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartuvc_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
201cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart{
202cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	int ret = 0;
203cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
204cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	mutex_lock(&queue->mutex);
205cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (v4l2_buf->index >= queue->count) {
206cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		ret = -EINVAL;
207cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		goto done;
208cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
209cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
210cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	__uvc_query_buffer(&queue->buffer[v4l2_buf->index], v4l2_buf);
211cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
212cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchartdone:
213cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	mutex_unlock(&queue->mutex);
214cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	return ret;
215cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart}
216cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
217cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart/*
218cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Queue a video buffer. Attempting to queue a buffer that has already been
219cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * queued will return -EINVAL.
220cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart */
2215d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartstatic int
2225d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartuvc_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf)
223cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart{
224cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	struct uvc_buffer *buf;
225cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	unsigned long flags;
226cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	int ret = 0;
227cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
228cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	uvc_trace(UVC_TRACE_CAPTURE, "Queuing buffer %u.\n", v4l2_buf->index);
229cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
230cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (v4l2_buf->type != queue->type ||
231cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	    v4l2_buf->memory != V4L2_MEMORY_MMAP) {
232cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
233cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart			"and/or memory (%u).\n", v4l2_buf->type,
234cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart			v4l2_buf->memory);
235cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		return -EINVAL;
236cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
237cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
238cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	mutex_lock(&queue->mutex);
239cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (v4l2_buf->index >= queue->count) {
240cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		uvc_trace(UVC_TRACE_CAPTURE, "[E] Out of range index.\n");
241cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		ret = -EINVAL;
242cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		goto done;
243cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
244cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
245cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	buf = &queue->buffer[v4l2_buf->index];
246cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (buf->state != UVC_BUF_STATE_IDLE) {
247cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state "
248cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart			"(%u).\n", buf->state);
249cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		ret = -EINVAL;
250cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		goto done;
251cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
252cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
253cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
254cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	    v4l2_buf->bytesused > buf->buf.length) {
255cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
256cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		ret = -EINVAL;
257cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		goto done;
258cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
259cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
260cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (v4l2_buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
261cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		buf->buf.bytesused = 0;
262cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	else
263cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		buf->buf.bytesused = v4l2_buf->bytesused;
264cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
265cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	spin_lock_irqsave(&queue->irqlock, flags);
266cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (queue->flags & UVC_QUEUE_DISCONNECTED) {
267cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		spin_unlock_irqrestore(&queue->irqlock, flags);
268cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		ret = -ENODEV;
269cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		goto done;
270cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
271cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	buf->state = UVC_BUF_STATE_QUEUED;
272cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
273cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	ret = (queue->flags & UVC_QUEUE_PAUSED) != 0;
274cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	queue->flags &= ~UVC_QUEUE_PAUSED;
275cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
276cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	list_add_tail(&buf->stream, &queue->mainqueue);
277cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	list_add_tail(&buf->queue, &queue->irqqueue);
278cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	spin_unlock_irqrestore(&queue->irqlock, flags);
279cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
280cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchartdone:
281cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	mutex_unlock(&queue->mutex);
282cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	return ret;
283cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart}
284cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
285cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchartstatic int uvc_queue_waiton(struct uvc_buffer *buf, int nonblocking)
286cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart{
287cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (nonblocking) {
288cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		return (buf->state != UVC_BUF_STATE_QUEUED &&
289cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart			buf->state != UVC_BUF_STATE_ACTIVE)
290cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart			? 0 : -EAGAIN;
291cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
292cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
293cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	return wait_event_interruptible(buf->wait,
294cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		buf->state != UVC_BUF_STATE_QUEUED &&
295cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		buf->state != UVC_BUF_STATE_ACTIVE);
296cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart}
297cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
298cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart/*
299cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Dequeue a video buffer. If nonblocking is false, block until a buffer is
300cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * available.
301cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart */
3025d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartstatic int
3035d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartuvc_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *v4l2_buf,
3045d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart		   int nonblocking)
305cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart{
306cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	struct uvc_buffer *buf;
307cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	int ret = 0;
308cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
309cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (v4l2_buf->type != queue->type ||
310cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	    v4l2_buf->memory != V4L2_MEMORY_MMAP) {
311cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer type (%u) "
312cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart			"and/or memory (%u).\n", v4l2_buf->type,
313cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart			v4l2_buf->memory);
314cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		return -EINVAL;
315cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
316cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
317cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	mutex_lock(&queue->mutex);
318cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (list_empty(&queue->mainqueue)) {
319cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		uvc_trace(UVC_TRACE_CAPTURE, "[E] Empty buffer queue.\n");
320cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		ret = -EINVAL;
321cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		goto done;
322cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
323cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
324cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
325cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if ((ret = uvc_queue_waiton(buf, nonblocking)) < 0)
326cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		goto done;
327cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
328cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	uvc_trace(UVC_TRACE_CAPTURE, "Dequeuing buffer %u (%u, %u bytes).\n",
329cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		buf->buf.index, buf->state, buf->buf.bytesused);
330cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
331cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	switch (buf->state) {
332cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	case UVC_BUF_STATE_ERROR:
333cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		uvc_trace(UVC_TRACE_CAPTURE, "[W] Corrupted data "
334cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart			"(transmission error).\n");
335cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		ret = -EIO;
336cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	case UVC_BUF_STATE_DONE:
337cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		buf->state = UVC_BUF_STATE_IDLE;
338cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		break;
339cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
340cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	case UVC_BUF_STATE_IDLE:
341cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	case UVC_BUF_STATE_QUEUED:
342cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	case UVC_BUF_STATE_ACTIVE:
343cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	default:
344cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		uvc_trace(UVC_TRACE_CAPTURE, "[E] Invalid buffer state %u "
345cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart			"(driver bug?).\n", buf->state);
346cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		ret = -EINVAL;
347cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		goto done;
348cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
349cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
350cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	list_del(&buf->stream);
351cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	__uvc_query_buffer(buf, v4l2_buf);
352cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
353cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchartdone:
354cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	mutex_unlock(&queue->mutex);
355cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	return ret;
356cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart}
357cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
358cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart/*
359cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Poll the video queue.
360cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
361cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * This function implements video queue polling and is intended to be used by
362cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * the device poll handler.
363cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart */
3645d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartstatic unsigned int
3655d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartuvc_queue_poll(struct uvc_video_queue *queue, struct file *file,
3665d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	       poll_table *wait)
367cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart{
368cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	struct uvc_buffer *buf;
369cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	unsigned int mask = 0;
370cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
371cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	mutex_lock(&queue->mutex);
372cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (list_empty(&queue->mainqueue))
373cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		goto done;
374cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
375cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	buf = list_first_entry(&queue->mainqueue, struct uvc_buffer, stream);
376cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
377cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	poll_wait(file, &buf->wait, wait);
378cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (buf->state == UVC_BUF_STATE_DONE ||
379cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	    buf->state == UVC_BUF_STATE_ERROR)
380cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		mask |= POLLOUT | POLLWRNORM;
381cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
382cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchartdone:
383cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	mutex_unlock(&queue->mutex);
384cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	return mask;
385cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart}
386cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
387cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart/*
388cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * VMA operations.
389cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart */
390cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchartstatic void uvc_vm_open(struct vm_area_struct *vma)
391cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart{
392cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	struct uvc_buffer *buffer = vma->vm_private_data;
393cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	buffer->vma_use_count++;
394cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart}
395cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
396cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchartstatic void uvc_vm_close(struct vm_area_struct *vma)
397cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart{
398cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	struct uvc_buffer *buffer = vma->vm_private_data;
399cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	buffer->vma_use_count--;
400cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart}
401cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
402cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchartstatic struct vm_operations_struct uvc_vm_ops = {
403cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	.open		= uvc_vm_open,
404cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	.close		= uvc_vm_close,
405cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart};
406cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
407cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart/*
408cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Memory-map a buffer.
409cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
410cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * This function implements video buffer memory mapping and is intended to be
411cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * used by the device mmap handler.
412cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart */
4135d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartstatic int
4145d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartuvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
415cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart{
416cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	struct uvc_buffer *uninitialized_var(buffer);
417cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	struct page *page;
418cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	unsigned long addr, start, size;
419cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	unsigned int i;
420cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	int ret = 0;
421cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
422cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	start = vma->vm_start;
423cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	size = vma->vm_end - vma->vm_start;
424cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
425cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	mutex_lock(&queue->mutex);
426cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
427cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	for (i = 0; i < queue->count; ++i) {
428cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		buffer = &queue->buffer[i];
429cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
430cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart			break;
431cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
432cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
433cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (i == queue->count || size != queue->buf_size) {
434cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		ret = -EINVAL;
435cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		goto done;
436cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
437cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
438cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	/*
439cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	 * VM_IO marks the area as being an mmaped region for I/O to a
440cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	 * device. It also prevents the region from being core dumped.
441cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	 */
442cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	vma->vm_flags |= VM_IO;
443cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
444cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	addr = (unsigned long)queue->mem + buffer->buf.m.offset;
445cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	while (size > 0) {
446cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		page = vmalloc_to_page((void *)addr);
447cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		if ((ret = vm_insert_page(vma, start, page)) < 0)
448cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart			goto done;
449cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
450cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		start += PAGE_SIZE;
451cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		addr += PAGE_SIZE;
452cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		size -= PAGE_SIZE;
453cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
454cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
455cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	vma->vm_ops = &uvc_vm_ops;
456cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	vma->vm_private_data = buffer;
457cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	uvc_vm_open(vma);
458cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
459cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchartdone:
460cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	mutex_unlock(&queue->mutex);
461cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	return ret;
462cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart}
463cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
464cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart/*
4655d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart * Cancel the video buffers queue.
4665d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart *
4675d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart * Cancelling the queue marks all buffers on the irq queue as erroneous,
4685d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart * wakes them up and removes them from the queue.
4695d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart *
4705d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart * If the disconnect parameter is set, further calls to uvc_queue_buffer will
4715d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart * fail with -ENODEV.
4725d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart *
4735d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart * This function acquires the irq spinlock and can be called from interrupt
4745d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart * context.
4755d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart */
4765d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartstatic void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect)
4775d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart{
4785d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	struct uvc_buffer *buf;
4795d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	unsigned long flags;
4805d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart
4815d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	spin_lock_irqsave(&queue->irqlock, flags);
4825d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	while (!list_empty(&queue->irqqueue)) {
4835d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart		buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
4845d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart				       queue);
4855d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart		list_del(&buf->queue);
4865d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart		buf->state = UVC_BUF_STATE_ERROR;
4875d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart		wake_up(&buf->wait);
4885d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	}
4895d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	/* This must be protected by the irqlock spinlock to avoid race
4905d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	 * conditions between uvc_queue_buffer and the disconnection event that
4915d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	 * could result in an interruptible wait in uvc_dequeue_buffer. Do not
4925d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	 * blindly replace this logic by checking for the UVC_DEV_DISCONNECTED
4935d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	 * state outside the queue code.
4945d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	 */
4955d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	if (disconnect)
4965d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart		queue->flags |= UVC_QUEUE_DISCONNECTED;
4975d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart	spin_unlock_irqrestore(&queue->irqlock, flags);
4985d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart}
4995d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart
5005d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchart/*
501cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Enable or disable the video buffers queue.
502cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
503cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * The queue must be enabled before starting video acquisition and must be
504cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * disabled after stopping it. This ensures that the video buffers queue
505cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * state can be properly initialized before buffers are accessed from the
506cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * interrupt handler.
507cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
508cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Enabling the video queue initializes parameters (such as sequence number,
509cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * sync pattern, ...). If the queue is already enabled, return -EBUSY.
510cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
511cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * Disabling the video queue cancels the queue and removes all buffers from
512cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * the main queue.
513cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart *
514cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * This function can't be called from interrupt context. Use
515cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart * uvc_queue_cancel() instead.
516cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart */
5175d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartstatic int uvc_queue_enable(struct uvc_video_queue *queue, int enable)
518cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart{
519cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	unsigned int i;
520cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	int ret = 0;
521cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
522cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	mutex_lock(&queue->mutex);
523cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (enable) {
524cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		if (uvc_queue_streaming(queue)) {
525cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart			ret = -EBUSY;
526cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart			goto done;
527cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		}
528cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		queue->sequence = 0;
529cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		queue->flags |= UVC_QUEUE_STREAMING;
530cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		queue->buf_used = 0;
531cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	} else {
532cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		uvc_queue_cancel(queue, 0);
533cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		INIT_LIST_HEAD(&queue->mainqueue);
534cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
535cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		for (i = 0; i < queue->count; ++i)
536cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart			queue->buffer[i].state = UVC_BUF_STATE_IDLE;
537cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
538cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		queue->flags &= ~UVC_QUEUE_STREAMING;
539cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
540cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
541cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchartdone:
542cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	mutex_unlock(&queue->mutex);
543cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	return ret;
544cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart}
545cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
5466190c79df861d2c78a7448fe6d4260e5fa53b9b9Bhupesh Sharma/* called with queue->irqlock held.. */
5475d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartstatic struct uvc_buffer *
5485d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartuvc_queue_next_buffer(struct uvc_video_queue *queue, struct uvc_buffer *buf)
549cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart{
550cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	struct uvc_buffer *nextbuf;
551cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
552cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if ((queue->flags & UVC_QUEUE_DROP_INCOMPLETE) &&
553cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	    buf->buf.length != buf->buf.bytesused) {
554cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		buf->state = UVC_BUF_STATE_QUEUED;
555cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		buf->buf.bytesused = 0;
556cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		return buf;
557cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	}
558cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
559cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	list_del(&buf->queue);
560cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (!list_empty(&queue->irqqueue))
561cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		nextbuf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
562cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart					   queue);
563cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	else
564cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		nextbuf = NULL;
565cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
566cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	buf->buf.sequence = queue->sequence++;
567cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	do_gettimeofday(&buf->buf.timestamp);
568cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
569cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	wake_up(&buf->wait);
570cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	return nextbuf;
571cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart}
572cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
5735d9955f8a978c1992a0f9966d22c43471214d43bLaurent Pinchartstatic struct uvc_buffer *uvc_queue_head(struct uvc_video_queue *queue)
574cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart{
575cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	struct uvc_buffer *buf = NULL;
576cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
577cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	if (!list_empty(&queue->irqqueue))
578cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
579cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart				       queue);
580cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	else
581cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart		queue->flags |= UVC_QUEUE_PAUSED;
582cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
583cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart	return buf;
584cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart}
585cdda479f15cd13fa50a913ca85129c0437cc7b91Laurent Pinchart
586