aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorLaurent Pinchart <laurent.pinchart@ideasonboard.com>2010-11-21 13:18:08 -0500
committerMauro Carvalho Chehab <mchehab@redhat.com>2010-12-01 17:10:23 -0500
commit4aa275975beee41fd542a0f6df8cd0fee06089bf (patch)
tree67896fb85b3a89838d0d91fee89622e3ec210135 /drivers
parent8e815e1763b8d4e5adf0dc14bde8c55329cf95a8 (diff)
[media] uvcvideo: Move mmap() handler to uvc_queue.c
The mmap() implementation belongs to the video buffers queue, move it there. Signed-off-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@redhat.com>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/media/video/uvc/uvc_queue.c76
-rw-r--r--drivers/media/video/uvc/uvc_v4l2.c67
-rw-r--r--drivers/media/video/uvc/uvcvideo.h2
3 files changed, 79 insertions, 66 deletions
diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c
index 32c18229863b..f14581bd707f 100644
--- a/drivers/media/video/uvc/uvc_queue.c
+++ b/drivers/media/video/uvc/uvc_queue.c
@@ -380,6 +380,82 @@ done:
380} 380}
381 381
382/* 382/*
383 * VMA operations.
384 */
385static void uvc_vm_open(struct vm_area_struct *vma)
386{
387 struct uvc_buffer *buffer = vma->vm_private_data;
388 buffer->vma_use_count++;
389}
390
391static void uvc_vm_close(struct vm_area_struct *vma)
392{
393 struct uvc_buffer *buffer = vma->vm_private_data;
394 buffer->vma_use_count--;
395}
396
397static const struct vm_operations_struct uvc_vm_ops = {
398 .open = uvc_vm_open,
399 .close = uvc_vm_close,
400};
401
402/*
403 * Memory-map a video buffer.
404 *
405 * This function implements video buffers memory mapping and is intended to be
406 * used by the device mmap handler.
407 */
408int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma)
409{
410 struct uvc_buffer *uninitialized_var(buffer);
411 struct page *page;
412 unsigned long addr, start, size;
413 unsigned int i;
414 int ret = 0;
415
416 start = vma->vm_start;
417 size = vma->vm_end - vma->vm_start;
418
419 mutex_lock(&queue->mutex);
420
421 for (i = 0; i < queue->count; ++i) {
422 buffer = &queue->buffer[i];
423 if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
424 break;
425 }
426
427 if (i == queue->count || size != queue->buf_size) {
428 ret = -EINVAL;
429 goto done;
430 }
431
432 /*
433 * VM_IO marks the area as being an mmaped region for I/O to a
434 * device. It also prevents the region from being core dumped.
435 */
436 vma->vm_flags |= VM_IO;
437
438 addr = (unsigned long)queue->mem + buffer->buf.m.offset;
439 while (size > 0) {
440 page = vmalloc_to_page((void *)addr);
441 if ((ret = vm_insert_page(vma, start, page)) < 0)
442 goto done;
443
444 start += PAGE_SIZE;
445 addr += PAGE_SIZE;
446 size -= PAGE_SIZE;
447 }
448
449 vma->vm_ops = &uvc_vm_ops;
450 vma->vm_private_data = buffer;
451 uvc_vm_open(vma);
452
453done:
454 mutex_unlock(&queue->mutex);
455 return ret;
456}
457
458/*
383 * Poll the video queue. 459 * Poll the video queue.
384 * 460 *
385 * This function implements video queue polling and is intended to be used by 461 * This function implements video queue polling and is intended to be used by
diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c
index 0fd9848bd9d7..07dd2357fbb9 100644
--- a/drivers/media/video/uvc/uvc_v4l2.c
+++ b/drivers/media/video/uvc/uvc_v4l2.c
@@ -1032,79 +1032,14 @@ static ssize_t uvc_v4l2_read(struct file *file, char __user *data,
1032 return -EINVAL; 1032 return -EINVAL;
1033} 1033}
1034 1034
1035/*
1036 * VMA operations.
1037 */
1038static void uvc_vm_open(struct vm_area_struct *vma)
1039{
1040 struct uvc_buffer *buffer = vma->vm_private_data;
1041 buffer->vma_use_count++;
1042}
1043
1044static void uvc_vm_close(struct vm_area_struct *vma)
1045{
1046 struct uvc_buffer *buffer = vma->vm_private_data;
1047 buffer->vma_use_count--;
1048}
1049
1050static const struct vm_operations_struct uvc_vm_ops = {
1051 .open = uvc_vm_open,
1052 .close = uvc_vm_close,
1053};
1054
1055static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) 1035static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
1056{ 1036{
1057 struct uvc_fh *handle = file->private_data; 1037 struct uvc_fh *handle = file->private_data;
1058 struct uvc_streaming *stream = handle->stream; 1038 struct uvc_streaming *stream = handle->stream;
1059 struct uvc_video_queue *queue = &stream->queue;
1060 struct uvc_buffer *uninitialized_var(buffer);
1061 struct page *page;
1062 unsigned long addr, start, size;
1063 unsigned int i;
1064 int ret = 0;
1065 1039
1066 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n"); 1040 uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_mmap\n");
1067 1041
1068 start = vma->vm_start; 1042 return uvc_queue_mmap(&stream->queue, vma);
1069 size = vma->vm_end - vma->vm_start;
1070
1071 mutex_lock(&queue->mutex);
1072
1073 for (i = 0; i < queue->count; ++i) {
1074 buffer = &queue->buffer[i];
1075 if ((buffer->buf.m.offset >> PAGE_SHIFT) == vma->vm_pgoff)
1076 break;
1077 }
1078
1079 if (i == queue->count || size != queue->buf_size) {
1080 ret = -EINVAL;
1081 goto done;
1082 }
1083
1084 /*
1085 * VM_IO marks the area as being an mmaped region for I/O to a
1086 * device. It also prevents the region from being core dumped.
1087 */
1088 vma->vm_flags |= VM_IO;
1089
1090 addr = (unsigned long)queue->mem + buffer->buf.m.offset;
1091 while (size > 0) {
1092 page = vmalloc_to_page((void *)addr);
1093 if ((ret = vm_insert_page(vma, start, page)) < 0)
1094 goto done;
1095
1096 start += PAGE_SIZE;
1097 addr += PAGE_SIZE;
1098 size -= PAGE_SIZE;
1099 }
1100
1101 vma->vm_ops = &uvc_vm_ops;
1102 vma->vm_private_data = buffer;
1103 uvc_vm_open(vma);
1104
1105done:
1106 mutex_unlock(&queue->mutex);
1107 return ret;
1108} 1043}
1109 1044
1110static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) 1045static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait)
diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h
index 45209245244b..ea893bc0df07 100644
--- a/drivers/media/video/uvc/uvcvideo.h
+++ b/drivers/media/video/uvc/uvcvideo.h
@@ -574,6 +574,8 @@ extern int uvc_queue_enable(struct uvc_video_queue *queue, int enable);
574extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect); 574extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect);
575extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, 575extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue,
576 struct uvc_buffer *buf); 576 struct uvc_buffer *buf);
577extern int uvc_queue_mmap(struct uvc_video_queue *queue,
578 struct vm_area_struct *vma);
577extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, 579extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue,
578 struct file *file, poll_table *wait); 580 struct file *file, poll_table *wait);
579extern int uvc_queue_allocated(struct uvc_video_queue *queue); 581extern int uvc_queue_allocated(struct uvc_video_queue *queue);