diff options
author | Laurent Pinchart <laurent.pinchart@ideasonboard.com> | 2010-11-21 13:18:08 -0500 |
---|---|---|
committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2010-12-01 17:10:23 -0500 |
commit | 4aa275975beee41fd542a0f6df8cd0fee06089bf (patch) | |
tree | 67896fb85b3a89838d0d91fee89622e3ec210135 /drivers/media | |
parent | 8e815e1763b8d4e5adf0dc14bde8c55329cf95a8 (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/media')
-rw-r--r-- | drivers/media/video/uvc/uvc_queue.c | 76 | ||||
-rw-r--r-- | drivers/media/video/uvc/uvc_v4l2.c | 67 | ||||
-rw-r--r-- | drivers/media/video/uvc/uvcvideo.h | 2 |
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 | */ | ||
385 | static 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 | |||
391 | static 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 | |||
397 | static 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 | */ | ||
408 | int 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 | |||
453 | done: | ||
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 | */ | ||
1038 | static 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 | |||
1044 | static 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 | |||
1050 | static const struct vm_operations_struct uvc_vm_ops = { | ||
1051 | .open = uvc_vm_open, | ||
1052 | .close = uvc_vm_close, | ||
1053 | }; | ||
1054 | |||
1055 | static int uvc_v4l2_mmap(struct file *file, struct vm_area_struct *vma) | 1035 | static 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 | |||
1105 | done: | ||
1106 | mutex_unlock(&queue->mutex); | ||
1107 | return ret; | ||
1108 | } | 1043 | } |
1109 | 1044 | ||
1110 | static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) | 1045 | static 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); | |||
574 | extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect); | 574 | extern void uvc_queue_cancel(struct uvc_video_queue *queue, int disconnect); |
575 | extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, | 575 | extern struct uvc_buffer *uvc_queue_next_buffer(struct uvc_video_queue *queue, |
576 | struct uvc_buffer *buf); | 576 | struct uvc_buffer *buf); |
577 | extern int uvc_queue_mmap(struct uvc_video_queue *queue, | ||
578 | struct vm_area_struct *vma); | ||
577 | extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, | 579 | extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, |
578 | struct file *file, poll_table *wait); | 580 | struct file *file, poll_table *wait); |
579 | extern int uvc_queue_allocated(struct uvc_video_queue *queue); | 581 | extern int uvc_queue_allocated(struct uvc_video_queue *queue); |