15fd54aceSGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0+
200a2430fSAndrzej Pietrasiewicz /*
300a2430fSAndrzej Pietrasiewicz * uvc_queue.c -- USB Video Class driver - Buffers management
400a2430fSAndrzej Pietrasiewicz *
500a2430fSAndrzej Pietrasiewicz * Copyright (C) 2005-2010
600a2430fSAndrzej Pietrasiewicz * Laurent Pinchart ([email protected])
700a2430fSAndrzej Pietrasiewicz */
800a2430fSAndrzej Pietrasiewicz
900a2430fSAndrzej Pietrasiewicz #include <linux/atomic.h>
1000a2430fSAndrzej Pietrasiewicz #include <linux/kernel.h>
1100a2430fSAndrzej Pietrasiewicz #include <linux/mm.h>
1200a2430fSAndrzej Pietrasiewicz #include <linux/list.h>
1300a2430fSAndrzej Pietrasiewicz #include <linux/module.h>
1400a2430fSAndrzej Pietrasiewicz #include <linux/usb.h>
1500a2430fSAndrzej Pietrasiewicz #include <linux/videodev2.h>
1600a2430fSAndrzej Pietrasiewicz #include <linux/vmalloc.h>
1700a2430fSAndrzej Pietrasiewicz #include <linux/wait.h>
1800a2430fSAndrzej Pietrasiewicz
1900a2430fSAndrzej Pietrasiewicz #include <media/v4l2-common.h>
20e81e7f9aSMichael Grzeschik #include <media/videobuf2-dma-sg.h>
2100a2430fSAndrzej Pietrasiewicz #include <media/videobuf2-vmalloc.h>
2200a2430fSAndrzej Pietrasiewicz
2300a2430fSAndrzej Pietrasiewicz #include "uvc.h"
24*1dc2527cSMichael Grzeschik #include "uvc_video.h"
2500a2430fSAndrzej Pietrasiewicz
2600a2430fSAndrzej Pietrasiewicz /* ------------------------------------------------------------------------
2700a2430fSAndrzej Pietrasiewicz * Video buffers queue management.
2800a2430fSAndrzej Pietrasiewicz *
297ea95b11SAndrzej Pietrasiewicz * Video queues is initialized by uvcg_queue_init(). The function performs
3000a2430fSAndrzej Pietrasiewicz * basic initialization of the uvc_video_queue struct and never fails.
3100a2430fSAndrzej Pietrasiewicz *
3200a2430fSAndrzej Pietrasiewicz * Video buffers are managed by videobuf2. The driver uses a mutex to protect
3300a2430fSAndrzej Pietrasiewicz * the videobuf2 queue operations by serializing calls to videobuf2 and a
3400a2430fSAndrzej Pietrasiewicz * spinlock to protect the IRQ queue that holds the buffers to be processed by
3500a2430fSAndrzej Pietrasiewicz * the driver.
3600a2430fSAndrzej Pietrasiewicz */
3700a2430fSAndrzej Pietrasiewicz
3800a2430fSAndrzej Pietrasiewicz /* -----------------------------------------------------------------------------
3900a2430fSAndrzej Pietrasiewicz * videobuf2 queue operations
4000a2430fSAndrzej Pietrasiewicz */
4100a2430fSAndrzej Pietrasiewicz
uvc_queue_setup(struct vb2_queue * vq,unsigned int * nbuffers,unsigned int * nplanes,unsigned int sizes[],struct device * alloc_devs[])42df9ecb0cSHans Verkuil static int uvc_queue_setup(struct vb2_queue *vq,
4300a2430fSAndrzej Pietrasiewicz unsigned int *nbuffers, unsigned int *nplanes,
4436c0f8b3SHans Verkuil unsigned int sizes[], struct device *alloc_devs[])
4500a2430fSAndrzej Pietrasiewicz {
4600a2430fSAndrzej Pietrasiewicz struct uvc_video_queue *queue = vb2_get_drv_priv(vq);
4700a2430fSAndrzej Pietrasiewicz struct uvc_video *video = container_of(queue, struct uvc_video, queue);
4800a2430fSAndrzej Pietrasiewicz
4900a2430fSAndrzej Pietrasiewicz if (*nbuffers > UVC_MAX_VIDEO_BUFFERS)
5000a2430fSAndrzej Pietrasiewicz *nbuffers = UVC_MAX_VIDEO_BUFFERS;
51*1dc2527cSMichael Grzeschik if (*nbuffers < UVCG_STREAMING_MIN_BUFFERS)
52*1dc2527cSMichael Grzeschik *nbuffers = UVCG_STREAMING_MIN_BUFFERS;
5300a2430fSAndrzej Pietrasiewicz
5400a2430fSAndrzej Pietrasiewicz *nplanes = 1;
5500a2430fSAndrzej Pietrasiewicz
5600a2430fSAndrzej Pietrasiewicz sizes[0] = video->imagesize;
5700a2430fSAndrzej Pietrasiewicz
5800a2430fSAndrzej Pietrasiewicz return 0;
5900a2430fSAndrzej Pietrasiewicz }
6000a2430fSAndrzej Pietrasiewicz
uvc_buffer_prepare(struct vb2_buffer * vb)6100a2430fSAndrzej Pietrasiewicz static int uvc_buffer_prepare(struct vb2_buffer *vb)
6200a2430fSAndrzej Pietrasiewicz {
6300a2430fSAndrzej Pietrasiewicz struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
6498ad0329SMichael Grzeschik struct uvc_video *video = container_of(queue, struct uvc_video, queue);
652d700715SJunghak Sung struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
662d700715SJunghak Sung struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
6700a2430fSAndrzej Pietrasiewicz
682d700715SJunghak Sung if (vb->type == V4L2_BUF_TYPE_VIDEO_OUTPUT &&
6900a2430fSAndrzej Pietrasiewicz vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0)) {
7000a2430fSAndrzej Pietrasiewicz uvc_trace(UVC_TRACE_CAPTURE, "[E] Bytes used out of bounds.\n");
7100a2430fSAndrzej Pietrasiewicz return -EINVAL;
7200a2430fSAndrzej Pietrasiewicz }
7300a2430fSAndrzej Pietrasiewicz
7400a2430fSAndrzej Pietrasiewicz if (unlikely(queue->flags & UVC_QUEUE_DISCONNECTED))
7500a2430fSAndrzej Pietrasiewicz return -ENODEV;
7600a2430fSAndrzej Pietrasiewicz
7700a2430fSAndrzej Pietrasiewicz buf->state = UVC_BUF_STATE_QUEUED;
7888c8e05eSGreg Kroah-Hartman if (queue->use_sg) {
79e81e7f9aSMichael Grzeschik buf->sgt = vb2_dma_sg_plane_desc(vb, 0);
80e81e7f9aSMichael Grzeschik buf->sg = buf->sgt->sgl;
8188c8e05eSGreg Kroah-Hartman } else {
8200a2430fSAndrzej Pietrasiewicz buf->mem = vb2_plane_vaddr(vb, 0);
8388c8e05eSGreg Kroah-Hartman }
8400a2430fSAndrzej Pietrasiewicz buf->length = vb2_plane_size(vb, 0);
8598ad0329SMichael Grzeschik if (vb->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
8600a2430fSAndrzej Pietrasiewicz buf->bytesused = 0;
8798ad0329SMichael Grzeschik } else {
8800a2430fSAndrzej Pietrasiewicz buf->bytesused = vb2_get_plane_payload(vb, 0);
8998ad0329SMichael Grzeschik buf->req_payload_size =
9098ad0329SMichael Grzeschik DIV_ROUND_UP(buf->bytesused +
9198ad0329SMichael Grzeschik (video->reqs_per_frame * UVCG_REQUEST_HEADER_LEN),
9298ad0329SMichael Grzeschik video->reqs_per_frame);
9398ad0329SMichael Grzeschik }
9400a2430fSAndrzej Pietrasiewicz
9500a2430fSAndrzej Pietrasiewicz return 0;
9600a2430fSAndrzej Pietrasiewicz }
9700a2430fSAndrzej Pietrasiewicz
uvc_buffer_queue(struct vb2_buffer * vb)9800a2430fSAndrzej Pietrasiewicz static void uvc_buffer_queue(struct vb2_buffer *vb)
9900a2430fSAndrzej Pietrasiewicz {
10000a2430fSAndrzej Pietrasiewicz struct uvc_video_queue *queue = vb2_get_drv_priv(vb->vb2_queue);
1012d700715SJunghak Sung struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1022d700715SJunghak Sung struct uvc_buffer *buf = container_of(vbuf, struct uvc_buffer, buf);
10300a2430fSAndrzej Pietrasiewicz unsigned long flags;
10400a2430fSAndrzej Pietrasiewicz
10500a2430fSAndrzej Pietrasiewicz spin_lock_irqsave(&queue->irqlock, flags);
10600a2430fSAndrzej Pietrasiewicz
10700a2430fSAndrzej Pietrasiewicz if (likely(!(queue->flags & UVC_QUEUE_DISCONNECTED))) {
10800a2430fSAndrzej Pietrasiewicz list_add_tail(&buf->queue, &queue->irqqueue);
10900a2430fSAndrzej Pietrasiewicz } else {
110c5d337a3SLaurent Pinchart /*
111c5d337a3SLaurent Pinchart * If the device is disconnected return the buffer to userspace
11200a2430fSAndrzej Pietrasiewicz * directly. The next QBUF call will fail with -ENODEV.
11300a2430fSAndrzej Pietrasiewicz */
11400a2430fSAndrzej Pietrasiewicz buf->state = UVC_BUF_STATE_ERROR;
1152d700715SJunghak Sung vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
11600a2430fSAndrzej Pietrasiewicz }
11700a2430fSAndrzej Pietrasiewicz
11800a2430fSAndrzej Pietrasiewicz spin_unlock_irqrestore(&queue->irqlock, flags);
11900a2430fSAndrzej Pietrasiewicz }
12000a2430fSAndrzej Pietrasiewicz
121e8942838SJulia Lawall static const struct vb2_ops uvc_queue_qops = {
12200a2430fSAndrzej Pietrasiewicz .queue_setup = uvc_queue_setup,
12300a2430fSAndrzej Pietrasiewicz .buf_prepare = uvc_buffer_prepare,
12400a2430fSAndrzej Pietrasiewicz .buf_queue = uvc_buffer_queue,
12500a2430fSAndrzej Pietrasiewicz };
12600a2430fSAndrzej Pietrasiewicz
uvcg_queue_init(struct uvc_video_queue * queue,struct device * dev,enum v4l2_buf_type type,struct mutex * lock)127e81e7f9aSMichael Grzeschik int uvcg_queue_init(struct uvc_video_queue *queue, struct device *dev, enum v4l2_buf_type type,
128d8e96c4bSHans Verkuil struct mutex *lock)
12900a2430fSAndrzej Pietrasiewicz {
130e81e7f9aSMichael Grzeschik struct uvc_video *video = container_of(queue, struct uvc_video, queue);
131e81e7f9aSMichael Grzeschik struct usb_composite_dev *cdev = video->uvc->func.config->cdev;
13200a2430fSAndrzej Pietrasiewicz int ret;
13300a2430fSAndrzej Pietrasiewicz
13400a2430fSAndrzej Pietrasiewicz queue->queue.type = type;
135ee7ec7f6SPhilipp Zabel queue->queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_DMABUF;
13600a2430fSAndrzej Pietrasiewicz queue->queue.drv_priv = queue;
13700a2430fSAndrzej Pietrasiewicz queue->queue.buf_struct_size = sizeof(struct uvc_buffer);
13800a2430fSAndrzej Pietrasiewicz queue->queue.ops = &uvc_queue_qops;
139d8e96c4bSHans Verkuil queue->queue.lock = lock;
140e81e7f9aSMichael Grzeschik if (cdev->gadget->sg_supported) {
141e81e7f9aSMichael Grzeschik queue->queue.mem_ops = &vb2_dma_sg_memops;
142e81e7f9aSMichael Grzeschik queue->use_sg = 1;
143e81e7f9aSMichael Grzeschik } else {
14400a2430fSAndrzej Pietrasiewicz queue->queue.mem_ops = &vb2_vmalloc_memops;
145e81e7f9aSMichael Grzeschik }
146e81e7f9aSMichael Grzeschik
147fd03af27SMichael Olbrich queue->queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_COPY
14800a2430fSAndrzej Pietrasiewicz | V4L2_BUF_FLAG_TSTAMP_SRC_EOF;
149e81e7f9aSMichael Grzeschik queue->queue.dev = dev;
150e81e7f9aSMichael Grzeschik
15100a2430fSAndrzej Pietrasiewicz ret = vb2_queue_init(&queue->queue);
15200a2430fSAndrzej Pietrasiewicz if (ret)
15300a2430fSAndrzej Pietrasiewicz return ret;
15400a2430fSAndrzej Pietrasiewicz
15500a2430fSAndrzej Pietrasiewicz spin_lock_init(&queue->irqlock);
15600a2430fSAndrzej Pietrasiewicz INIT_LIST_HEAD(&queue->irqqueue);
15700a2430fSAndrzej Pietrasiewicz queue->flags = 0;
15800a2430fSAndrzej Pietrasiewicz
15900a2430fSAndrzej Pietrasiewicz return 0;
16000a2430fSAndrzej Pietrasiewicz }
16100a2430fSAndrzej Pietrasiewicz
16200a2430fSAndrzej Pietrasiewicz /*
16300a2430fSAndrzej Pietrasiewicz * Free the video buffers.
16400a2430fSAndrzej Pietrasiewicz */
uvcg_free_buffers(struct uvc_video_queue * queue)1653a83c16eSAndrzej Pietrasiewicz void uvcg_free_buffers(struct uvc_video_queue *queue)
16600a2430fSAndrzej Pietrasiewicz {
16700a2430fSAndrzej Pietrasiewicz vb2_queue_release(&queue->queue);
16800a2430fSAndrzej Pietrasiewicz }
16900a2430fSAndrzej Pietrasiewicz
17000a2430fSAndrzej Pietrasiewicz /*
17100a2430fSAndrzej Pietrasiewicz * Allocate the video buffers.
17200a2430fSAndrzej Pietrasiewicz */
uvcg_alloc_buffers(struct uvc_video_queue * queue,struct v4l2_requestbuffers * rb)1733a83c16eSAndrzej Pietrasiewicz int uvcg_alloc_buffers(struct uvc_video_queue *queue,
17400a2430fSAndrzej Pietrasiewicz struct v4l2_requestbuffers *rb)
17500a2430fSAndrzej Pietrasiewicz {
17600a2430fSAndrzej Pietrasiewicz int ret;
17700a2430fSAndrzej Pietrasiewicz
17800a2430fSAndrzej Pietrasiewicz ret = vb2_reqbufs(&queue->queue, rb);
17900a2430fSAndrzej Pietrasiewicz
18000a2430fSAndrzej Pietrasiewicz return ret ? ret : rb->count;
18100a2430fSAndrzej Pietrasiewicz }
18200a2430fSAndrzej Pietrasiewicz
uvcg_query_buffer(struct uvc_video_queue * queue,struct v4l2_buffer * buf)1833a83c16eSAndrzej Pietrasiewicz int uvcg_query_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
18400a2430fSAndrzej Pietrasiewicz {
185d8e96c4bSHans Verkuil return vb2_querybuf(&queue->queue, buf);
18600a2430fSAndrzej Pietrasiewicz }
18700a2430fSAndrzej Pietrasiewicz
uvcg_queue_buffer(struct uvc_video_queue * queue,struct v4l2_buffer * buf)1883a83c16eSAndrzej Pietrasiewicz int uvcg_queue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf)
18900a2430fSAndrzej Pietrasiewicz {
190be30e350SDan Vacura return vb2_qbuf(&queue->queue, NULL, buf);
19100a2430fSAndrzej Pietrasiewicz }
19200a2430fSAndrzej Pietrasiewicz
19300a2430fSAndrzej Pietrasiewicz /*
19400a2430fSAndrzej Pietrasiewicz * Dequeue a video buffer. If nonblocking is false, block until a buffer is
19500a2430fSAndrzej Pietrasiewicz * available.
19600a2430fSAndrzej Pietrasiewicz */
uvcg_dequeue_buffer(struct uvc_video_queue * queue,struct v4l2_buffer * buf,int nonblocking)1973a83c16eSAndrzej Pietrasiewicz int uvcg_dequeue_buffer(struct uvc_video_queue *queue, struct v4l2_buffer *buf,
1983a83c16eSAndrzej Pietrasiewicz int nonblocking)
19900a2430fSAndrzej Pietrasiewicz {
200d8e96c4bSHans Verkuil return vb2_dqbuf(&queue->queue, buf, nonblocking);
20100a2430fSAndrzej Pietrasiewicz }
20200a2430fSAndrzej Pietrasiewicz
20300a2430fSAndrzej Pietrasiewicz /*
20400a2430fSAndrzej Pietrasiewicz * Poll the video queue.
20500a2430fSAndrzej Pietrasiewicz *
20600a2430fSAndrzej Pietrasiewicz * This function implements video queue polling and is intended to be used by
20700a2430fSAndrzej Pietrasiewicz * the device poll handler.
20800a2430fSAndrzej Pietrasiewicz */
uvcg_queue_poll(struct uvc_video_queue * queue,struct file * file,poll_table * wait)209c23e0cb8SAl Viro __poll_t uvcg_queue_poll(struct uvc_video_queue *queue, struct file *file,
2103a83c16eSAndrzej Pietrasiewicz poll_table *wait)
21100a2430fSAndrzej Pietrasiewicz {
212d8e96c4bSHans Verkuil return vb2_poll(&queue->queue, file, wait);
21300a2430fSAndrzej Pietrasiewicz }
21400a2430fSAndrzej Pietrasiewicz
uvcg_queue_mmap(struct uvc_video_queue * queue,struct vm_area_struct * vma)2153a83c16eSAndrzej Pietrasiewicz int uvcg_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
21600a2430fSAndrzej Pietrasiewicz {
217d8e96c4bSHans Verkuil return vb2_mmap(&queue->queue, vma);
21800a2430fSAndrzej Pietrasiewicz }
21900a2430fSAndrzej Pietrasiewicz
22000a2430fSAndrzej Pietrasiewicz #ifndef CONFIG_MMU
22100a2430fSAndrzej Pietrasiewicz /*
22200a2430fSAndrzej Pietrasiewicz * Get unmapped area.
22300a2430fSAndrzej Pietrasiewicz *
22400a2430fSAndrzej Pietrasiewicz * NO-MMU arch need this function to make mmap() work correctly.
22500a2430fSAndrzej Pietrasiewicz */
uvcg_queue_get_unmapped_area(struct uvc_video_queue * queue,unsigned long pgoff)2263a83c16eSAndrzej Pietrasiewicz unsigned long uvcg_queue_get_unmapped_area(struct uvc_video_queue *queue,
22700a2430fSAndrzej Pietrasiewicz unsigned long pgoff)
22800a2430fSAndrzej Pietrasiewicz {
229d8e96c4bSHans Verkuil return vb2_get_unmapped_area(&queue->queue, 0, 0, pgoff, 0);
23000a2430fSAndrzej Pietrasiewicz }
23100a2430fSAndrzej Pietrasiewicz #endif
23200a2430fSAndrzej Pietrasiewicz
23300a2430fSAndrzej Pietrasiewicz /*
23400a2430fSAndrzej Pietrasiewicz * Cancel the video buffers queue.
23500a2430fSAndrzej Pietrasiewicz *
23600a2430fSAndrzej Pietrasiewicz * Cancelling the queue marks all buffers on the irq queue as erroneous,
23700a2430fSAndrzej Pietrasiewicz * wakes them up and removes them from the queue.
23800a2430fSAndrzej Pietrasiewicz *
23900a2430fSAndrzej Pietrasiewicz * If the disconnect parameter is set, further calls to uvc_queue_buffer will
24000a2430fSAndrzej Pietrasiewicz * fail with -ENODEV.
24100a2430fSAndrzej Pietrasiewicz *
24200a2430fSAndrzej Pietrasiewicz * This function acquires the irq spinlock and can be called from interrupt
24300a2430fSAndrzej Pietrasiewicz * context.
24400a2430fSAndrzej Pietrasiewicz */
uvcg_queue_cancel(struct uvc_video_queue * queue,int disconnect)2453a83c16eSAndrzej Pietrasiewicz void uvcg_queue_cancel(struct uvc_video_queue *queue, int disconnect)
24600a2430fSAndrzej Pietrasiewicz {
24700a2430fSAndrzej Pietrasiewicz struct uvc_buffer *buf;
24800a2430fSAndrzej Pietrasiewicz unsigned long flags;
24900a2430fSAndrzej Pietrasiewicz
25000a2430fSAndrzej Pietrasiewicz spin_lock_irqsave(&queue->irqlock, flags);
25100a2430fSAndrzej Pietrasiewicz while (!list_empty(&queue->irqqueue)) {
25200a2430fSAndrzej Pietrasiewicz buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
25300a2430fSAndrzej Pietrasiewicz queue);
25400a2430fSAndrzej Pietrasiewicz list_del(&buf->queue);
25500a2430fSAndrzej Pietrasiewicz buf->state = UVC_BUF_STATE_ERROR;
2562d700715SJunghak Sung vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR);
25700a2430fSAndrzej Pietrasiewicz }
25871d471e3SDan Vacura queue->buf_used = 0;
25971d471e3SDan Vacura
260c5d337a3SLaurent Pinchart /*
261c5d337a3SLaurent Pinchart * This must be protected by the irqlock spinlock to avoid race
26200a2430fSAndrzej Pietrasiewicz * conditions between uvc_queue_buffer and the disconnection event that
26300a2430fSAndrzej Pietrasiewicz * could result in an interruptible wait in uvc_dequeue_buffer. Do not
26400a2430fSAndrzej Pietrasiewicz * blindly replace this logic by checking for the UVC_DEV_DISCONNECTED
26500a2430fSAndrzej Pietrasiewicz * state outside the queue code.
26600a2430fSAndrzej Pietrasiewicz */
26700a2430fSAndrzej Pietrasiewicz if (disconnect)
26800a2430fSAndrzej Pietrasiewicz queue->flags |= UVC_QUEUE_DISCONNECTED;
26900a2430fSAndrzej Pietrasiewicz spin_unlock_irqrestore(&queue->irqlock, flags);
27000a2430fSAndrzej Pietrasiewicz }
27100a2430fSAndrzej Pietrasiewicz
27200a2430fSAndrzej Pietrasiewicz /*
27300a2430fSAndrzej Pietrasiewicz * Enable or disable the video buffers queue.
27400a2430fSAndrzej Pietrasiewicz *
27500a2430fSAndrzej Pietrasiewicz * The queue must be enabled before starting video acquisition and must be
27600a2430fSAndrzej Pietrasiewicz * disabled after stopping it. This ensures that the video buffers queue
27700a2430fSAndrzej Pietrasiewicz * state can be properly initialized before buffers are accessed from the
27800a2430fSAndrzej Pietrasiewicz * interrupt handler.
27900a2430fSAndrzej Pietrasiewicz *
28000a2430fSAndrzej Pietrasiewicz * Enabling the video queue initializes parameters (such as sequence number,
28100a2430fSAndrzej Pietrasiewicz * sync pattern, ...). If the queue is already enabled, return -EBUSY.
28200a2430fSAndrzej Pietrasiewicz *
28300a2430fSAndrzej Pietrasiewicz * Disabling the video queue cancels the queue and removes all buffers from
28400a2430fSAndrzej Pietrasiewicz * the main queue.
28500a2430fSAndrzej Pietrasiewicz *
28600a2430fSAndrzej Pietrasiewicz * This function can't be called from interrupt context. Use
2877ea95b11SAndrzej Pietrasiewicz * uvcg_queue_cancel() instead.
28800a2430fSAndrzej Pietrasiewicz */
uvcg_queue_enable(struct uvc_video_queue * queue,int enable)2893a83c16eSAndrzej Pietrasiewicz int uvcg_queue_enable(struct uvc_video_queue *queue, int enable)
29000a2430fSAndrzej Pietrasiewicz {
29100a2430fSAndrzej Pietrasiewicz unsigned long flags;
29200a2430fSAndrzej Pietrasiewicz int ret = 0;
29300a2430fSAndrzej Pietrasiewicz
29400a2430fSAndrzej Pietrasiewicz if (enable) {
29500a2430fSAndrzej Pietrasiewicz ret = vb2_streamon(&queue->queue, queue->queue.type);
29600a2430fSAndrzej Pietrasiewicz if (ret < 0)
297d8e96c4bSHans Verkuil return ret;
29800a2430fSAndrzej Pietrasiewicz
29900a2430fSAndrzej Pietrasiewicz queue->sequence = 0;
30000a2430fSAndrzej Pietrasiewicz queue->buf_used = 0;
3010a0a2760SDan Vacura queue->flags &= ~UVC_QUEUE_DROP_INCOMPLETE;
30200a2430fSAndrzej Pietrasiewicz } else {
30300a2430fSAndrzej Pietrasiewicz ret = vb2_streamoff(&queue->queue, queue->queue.type);
30400a2430fSAndrzej Pietrasiewicz if (ret < 0)
305d8e96c4bSHans Verkuil return ret;
30600a2430fSAndrzej Pietrasiewicz
30700a2430fSAndrzej Pietrasiewicz spin_lock_irqsave(&queue->irqlock, flags);
30800a2430fSAndrzej Pietrasiewicz INIT_LIST_HEAD(&queue->irqqueue);
30900a2430fSAndrzej Pietrasiewicz
31000a2430fSAndrzej Pietrasiewicz /*
31100a2430fSAndrzej Pietrasiewicz * FIXME: We need to clear the DISCONNECTED flag to ensure that
31200a2430fSAndrzej Pietrasiewicz * applications will be able to queue buffers for the next
31300a2430fSAndrzej Pietrasiewicz * streaming run. However, clearing it here doesn't guarantee
31400a2430fSAndrzej Pietrasiewicz * that the device will be reconnected in the meantime.
31500a2430fSAndrzej Pietrasiewicz */
31600a2430fSAndrzej Pietrasiewicz queue->flags &= ~UVC_QUEUE_DISCONNECTED;
31700a2430fSAndrzej Pietrasiewicz spin_unlock_irqrestore(&queue->irqlock, flags);
31800a2430fSAndrzej Pietrasiewicz }
31900a2430fSAndrzej Pietrasiewicz
32000a2430fSAndrzej Pietrasiewicz return ret;
32100a2430fSAndrzej Pietrasiewicz }
32200a2430fSAndrzej Pietrasiewicz
32300a2430fSAndrzej Pietrasiewicz /* called with &queue_irqlock held.. */
uvcg_complete_buffer(struct uvc_video_queue * queue,struct uvc_buffer * buf)32461aa709cSMichael Grzeschik void uvcg_complete_buffer(struct uvc_video_queue *queue,
32500a2430fSAndrzej Pietrasiewicz struct uvc_buffer *buf)
32600a2430fSAndrzej Pietrasiewicz {
3270a0a2760SDan Vacura if (queue->flags & UVC_QUEUE_DROP_INCOMPLETE) {
3280a0a2760SDan Vacura queue->flags &= ~UVC_QUEUE_DROP_INCOMPLETE;
3290a0a2760SDan Vacura buf->state = UVC_BUF_STATE_ERROR;
3302d700715SJunghak Sung vb2_set_plane_payload(&buf->buf.vb2_buf, 0, 0);
3310a0a2760SDan Vacura vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_ERROR);
33261aa709cSMichael Grzeschik return;
33300a2430fSAndrzej Pietrasiewicz }
33400a2430fSAndrzej Pietrasiewicz
3352d700715SJunghak Sung buf->buf.field = V4L2_FIELD_NONE;
3362d700715SJunghak Sung buf->buf.sequence = queue->sequence++;
337d6dd645eSJunghak Sung buf->buf.vb2_buf.timestamp = ktime_get_ns();
33800a2430fSAndrzej Pietrasiewicz
3392d700715SJunghak Sung vb2_set_plane_payload(&buf->buf.vb2_buf, 0, buf->bytesused);
3402d700715SJunghak Sung vb2_buffer_done(&buf->buf.vb2_buf, VB2_BUF_STATE_DONE);
34100a2430fSAndrzej Pietrasiewicz }
34200a2430fSAndrzej Pietrasiewicz
uvcg_queue_head(struct uvc_video_queue * queue)3433a83c16eSAndrzej Pietrasiewicz struct uvc_buffer *uvcg_queue_head(struct uvc_video_queue *queue)
34400a2430fSAndrzej Pietrasiewicz {
34500a2430fSAndrzej Pietrasiewicz struct uvc_buffer *buf = NULL;
34600a2430fSAndrzej Pietrasiewicz
34700a2430fSAndrzej Pietrasiewicz if (!list_empty(&queue->irqqueue))
34800a2430fSAndrzej Pietrasiewicz buf = list_first_entry(&queue->irqqueue, struct uvc_buffer,
34900a2430fSAndrzej Pietrasiewicz queue);
35000a2430fSAndrzej Pietrasiewicz
35100a2430fSAndrzej Pietrasiewicz return buf;
35200a2430fSAndrzej Pietrasiewicz }
35300a2430fSAndrzej Pietrasiewicz
354