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