/* * Allocate the video buffers. * * Pages are reserved to make sure they will not be swaped, as they will be * filled in URB completion handler. * * Buffers will be individually mapped, so they must all be page aligned. */ int uvc_alloc_buffers(struct uvc_video_queue *queue, unsigned int nbuffers, unsigned int buflength) { unsigned int bufsize = PAGE_ALIGN(buflength); unsigned int i; void *mem = NULL; int ret; if (nbuffers > UVC_MAX_VIDEO_BUFFERS) nbuffers = UVC_MAX_VIDEO_BUFFERS; mutex_lock(&queue->mutex); if ((ret = uvc_free_buffers(queue)) < 0) goto done; /* Bail out if no buffers should be allocated. */ if (nbuffers == 0) goto done; /* Decrement the number of buffers until allocation succeeds. */ for (; nbuffers > 0; --nbuffers) { mem = vmalloc_32(nbuffers * bufsize); if (mem != NULL) break; } if (mem == NULL) { ret = -ENOMEM; goto done; } for (i = 0; i < nbuffers; ++i) { memset(&queue->buffer[i], 0, sizeof queue->buffer[i]); queue->buffer[i].buf.index = i; queue->buffer[i].buf.m.offset = i * bufsize; queue->buffer[i].buf.length = buflength; queue->buffer[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; queue->buffer[i].buf.sequence = 0; queue->buffer[i].buf.field = V4L2_FIELD_NONE; queue->buffer[i].buf.memory = V4L2_MEMORY_MMAP; queue->buffer[i].buf.flags = 0; init_waitqueue_head(&queue->buffer[i].wait); } queue->mem = mem; queue->count = nbuffers; queue->buf_size = bufsize; ret = nbuffers; done: mutex_unlock(&queue->mutex); return ret; }
static int uvc_v4l2_release(struct file *file) { struct video_device *vdev = video_devdata(file); struct uvc_device *uvc = video_get_drvdata(vdev); struct uvc_file_handle *handle = to_uvc_file_handle(file->private_data); struct uvc_video *video = handle->device; uvc_function_disconnect(uvc); uvc_video_enable(video, 0); mutex_lock(&video->queue.mutex); if (uvc_free_buffers(&video->queue) < 0) printk(KERN_ERR "uvc_v4l2_release: Unable to free " "buffers.\n"); mutex_unlock(&video->queue.mutex); file->private_data = NULL; v4l2_fh_del(&handle->vfh); v4l2_fh_exit(&handle->vfh); kfree(handle); return 0; }