[PATCH] nommu: remap_pfn_range: fix addr parameter check
The addr parameter may not page aligned eg. when it's come from vfb_mmap():vma->vm_start in video driver. This patch fix the check in remap_pfn_range() else some driver like v4l2 will fail in this function while calling mmap() on nommu arch like blackfin and st. Reported-by: Bhupesh SHARMA Reported-by: Scott Jiang Signed-off-by: Bob Liu --- mm/nommu.c |2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/nommu.c b/mm/nommu.c index d4b0c10..5d6068b 100644 --- a/mm/nommu.c +++ b/mm/nommu.c @@ -1819,7 +1819,7 @@ struct page *follow_page(struct vm_area_struct *vma, unsigned long address, int remap_pfn_range(struct vm_area_struct *vma, unsigned long addr, unsigned long pfn, unsigned long size, pgprot_t prot) { - if (addr != (pfn << PAGE_SHIFT)) + if ((addr & PAGE_MASK) != (pfn << PAGE_SHIFT)) return -EINVAL; vma->vm_flags |= VM_IO | VM_RESERVED | VM_PFNMAP; -- 1.7.9.5 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] drivers:media:video:uvc: fix uvc_v4l2_get_unmapped_area for NOMMU
Hi Laurent, On Tue, May 15, 2012 at 9:01 AM, Bob Liu wrote: > Hi Laurent, > > On Mon, May 14, 2012 at 7:31 PM, Laurent Pinchart > wrote: >> Hi Bob, >> >> On Monday 14 May 2012 18:23:59 Bob Liu wrote: >>> Fix uvc_v4l2_get_unmapped_area() for NOMMU arch like blackfin after >>> framework updated to use videobuf2. >> >> Thank you for the patch, but I'm afraid you're too late. The fix is already >> queued for v3.5 :-) > > It doesn't matter. Sorry for my misunderstanding. I've seen the fix in the queue for v3.5. Please ignore my noise. > >> >>> Signed-off-by: Bob Liu >>> --- >>> drivers/media/video/uvc/uvc_queue.c | 30 -- >>> drivers/media/video/uvc/uvc_v4l2.c | 2 +- >>> 2 files changed, 1 insertions(+), 31 deletions(-) >>> >>> diff --git a/drivers/media/video/uvc/uvc_queue.c >>> b/drivers/media/video/uvc/uvc_queue.c index 518f77d..30be060 100644 >>> --- a/drivers/media/video/uvc/uvc_queue.c >>> +++ b/drivers/media/video/uvc/uvc_queue.c >>> @@ -237,36 +237,6 @@ int uvc_queue_allocated(struct uvc_video_queue *queue) >>> return allocated; >>> } >>> >>> -#ifndef CONFIG_MMU >>> -/* >>> - * Get unmapped area. >>> - * >>> - * NO-MMU arch need this function to make mmap() work correctly. >>> - */ >>> -unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, >>> - unsigned long pgoff) >>> -{ >>> - struct uvc_buffer *buffer; >>> - unsigned int i; >>> - unsigned long ret; >>> - >>> - mutex_lock(&queue->mutex); >>> - for (i = 0; i < queue->count; ++i) { >>> - buffer = &queue->buffer[i]; >>> - if ((buffer->buf.m.offset >> PAGE_SHIFT) == pgoff) >>> - break; >>> - } >>> - if (i == queue->count) { >>> - ret = -EINVAL; >>> - goto done; >>> - } >>> - ret = (unsigned long)buf->mem; >>> -done: >>> - mutex_unlock(&queue->mutex); >>> - return ret; >>> -} >>> -#endif >>> - >>> /* >>> * Enable or disable the video buffers queue. >>> * >>> diff --git a/drivers/media/video/uvc/uvc_v4l2.c >>> b/drivers/media/video/uvc/uvc_v4l2.c index 2ae4f88..506d3d6 100644 >>> --- a/drivers/media/video/uvc/uvc_v4l2.c >>> +++ b/drivers/media/video/uvc/uvc_v4l2.c >>> @@ -1067,7 +1067,7 @@ static unsigned long uvc_v4l2_get_unmapped_area(struct >>> file *file, >>> >>> uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n"); >>> >>> - return uvc_queue_get_unmapped_area(&stream->queue, pgoff); >>> + return vb2_get_unmapped_area(&stream->queue, addr, len, pgoff, flags); >> >> Just for the record you would have needed to take the queue->mutex around the >> vb2_get_unmapped_area() call here. >> > > okay, i'll send out v2 soon, please queue it for next window. > Thank you. > >>> } >>> #endif >> >> -- >> Regards, >> >> Laurent Pinchart >> > > -- > Regards, > --Bob -- Regards, --Bob -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] drivers:media:video:uvc: fix uvc_v4l2_get_unmapped_area for NOMMU
Hi Laurent, On Mon, May 14, 2012 at 7:31 PM, Laurent Pinchart wrote: > Hi Bob, > > On Monday 14 May 2012 18:23:59 Bob Liu wrote: >> Fix uvc_v4l2_get_unmapped_area() for NOMMU arch like blackfin after >> framework updated to use videobuf2. > > Thank you for the patch, but I'm afraid you're too late. The fix is already > queued for v3.5 :-) It doesn't matter. > >> Signed-off-by: Bob Liu >> --- >> drivers/media/video/uvc/uvc_queue.c | 30 -- >> drivers/media/video/uvc/uvc_v4l2.c | 2 +- >> 2 files changed, 1 insertions(+), 31 deletions(-) >> >> diff --git a/drivers/media/video/uvc/uvc_queue.c >> b/drivers/media/video/uvc/uvc_queue.c index 518f77d..30be060 100644 >> --- a/drivers/media/video/uvc/uvc_queue.c >> +++ b/drivers/media/video/uvc/uvc_queue.c >> @@ -237,36 +237,6 @@ int uvc_queue_allocated(struct uvc_video_queue *queue) >> return allocated; >> } >> >> -#ifndef CONFIG_MMU >> -/* >> - * Get unmapped area. >> - * >> - * NO-MMU arch need this function to make mmap() work correctly. >> - */ >> -unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, >> - unsigned long pgoff) >> -{ >> - struct uvc_buffer *buffer; >> - unsigned int i; >> - unsigned long ret; >> - >> - mutex_lock(&queue->mutex); >> - for (i = 0; i < queue->count; ++i) { >> - buffer = &queue->buffer[i]; >> - if ((buffer->buf.m.offset >> PAGE_SHIFT) == pgoff) >> - break; >> - } >> - if (i == queue->count) { >> - ret = -EINVAL; >> - goto done; >> - } >> - ret = (unsigned long)buf->mem; >> -done: >> - mutex_unlock(&queue->mutex); >> - return ret; >> -} >> -#endif >> - >> /* >> * Enable or disable the video buffers queue. >> * >> diff --git a/drivers/media/video/uvc/uvc_v4l2.c >> b/drivers/media/video/uvc/uvc_v4l2.c index 2ae4f88..506d3d6 100644 >> --- a/drivers/media/video/uvc/uvc_v4l2.c >> +++ b/drivers/media/video/uvc/uvc_v4l2.c >> @@ -1067,7 +1067,7 @@ static unsigned long uvc_v4l2_get_unmapped_area(struct >> file *file, >> >> uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n"); >> >> - return uvc_queue_get_unmapped_area(&stream->queue, pgoff); >> + return vb2_get_unmapped_area(&stream->queue, addr, len, pgoff, flags); > > Just for the record you would have needed to take the queue->mutex around the > vb2_get_unmapped_area() call here. > okay, i'll send out v2 soon, please queue it for next window. Thank you. >> } >> #endif > > -- > Regards, > > Laurent Pinchart > -- Regards, --Bob -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] drivers:media:video:uvc: fix uvc_v4l2_get_unmapped_area for NOMMU
Fix uvc_v4l2_get_unmapped_area() for NOMMU arch like blackfin after framework updated to use videobuf2. Signed-off-by: Bob Liu --- drivers/media/video/uvc/uvc_queue.c | 30 -- drivers/media/video/uvc/uvc_v4l2.c |2 +- 2 files changed, 1 insertions(+), 31 deletions(-) diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index 518f77d..30be060 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -237,36 +237,6 @@ int uvc_queue_allocated(struct uvc_video_queue *queue) return allocated; } -#ifndef CONFIG_MMU -/* - * Get unmapped area. - * - * NO-MMU arch need this function to make mmap() work correctly. - */ -unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, - unsigned long pgoff) -{ - struct uvc_buffer *buffer; - unsigned int i; - unsigned long ret; - - mutex_lock(&queue->mutex); - for (i = 0; i < queue->count; ++i) { - buffer = &queue->buffer[i]; - if ((buffer->buf.m.offset >> PAGE_SHIFT) == pgoff) - break; - } - if (i == queue->count) { - ret = -EINVAL; - goto done; - } - ret = (unsigned long)buf->mem; -done: - mutex_unlock(&queue->mutex); - return ret; -} -#endif - /* * Enable or disable the video buffers queue. * diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 2ae4f88..506d3d6 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -1067,7 +1067,7 @@ static unsigned long uvc_v4l2_get_unmapped_area(struct file *file, uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n"); - return uvc_queue_get_unmapped_area(&stream->queue, pgoff); + return vb2_get_unmapped_area(&stream->queue, addr, len, pgoff, flags); } #endif -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] V4L/DVB: v4l2-dev: revert commit c29fcff3daafbf46d64a543c1950bbd206ad8c1c
On Fri, May 6, 2011 at 4:22 PM, Laurent Pinchart wrote: > Hi Bob, > > On Friday 29 April 2011 12:11:34 Bob Liu wrote: >> Revert commit: >> V4L/DVB: v4l2-dev: remove get_unmapped_area(c29fcff3daafbf46d64a543c1950bb) >> to restore NOMMU arch supporting. >> >> Signed-off-by: Bob Liu > > git provides a 'git revert' command to revert patches. It formats the commit Sorry, I haven't use 'git revert' before. > message in a standard way. I'll use it instead of applying this patch to my > tree and I'll keep your SoB line (unless you object to that). > Okay, Thanks a lot. >> --- >> drivers/media/video/v4l2-dev.c | 18 ++ >> include/media/v4l2-dev.h | 2 ++ >> 2 files changed, 20 insertions(+), 0 deletions(-) >> >> diff --git a/drivers/media/video/v4l2-dev.c >> b/drivers/media/video/v4l2-dev.c index 6dc7196..19d5ae2 100644 >> --- a/drivers/media/video/v4l2-dev.c >> +++ b/drivers/media/video/v4l2-dev.c >> @@ -352,6 +352,23 @@ static long v4l2_ioctl(struct file *filp, unsigned int >> cmd, unsigned long arg) return ret; >> } >> >> +#ifdef CONFIG_MMU >> +#define v4l2_get_unmapped_area NULL >> +#else >> +static unsigned long v4l2_get_unmapped_area(struct file *filp, >> + unsigned long addr, unsigned long len, unsigned long pgoff, >> + unsigned long flags) >> +{ >> + struct video_device *vdev = video_devdata(filp); >> + >> + if (!vdev->fops->get_unmapped_area) >> + return -ENOSYS; >> + if (!video_is_registered(vdev)) >> + return -ENODEV; >> + return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); >> +} >> +#endif >> + >> static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) >> { >> struct video_device *vdev = video_devdata(filp); >> @@ -454,6 +471,7 @@ static const struct file_operations v4l2_fops = { >> .read = v4l2_read, >> .write = v4l2_write, >> .open = v4l2_open, >> + .get_unmapped_area = v4l2_get_unmapped_area, >> .mmap = v4l2_mmap, >> .unlocked_ioctl = v4l2_ioctl, >> #ifdef CONFIG_COMPAT >> diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h >> index 8266d5a..93e96fb 100644 >> --- a/include/media/v4l2-dev.h >> +++ b/include/media/v4l2-dev.h >> @@ -62,6 +62,8 @@ struct v4l2_file_operations { >> unsigned int (*poll) (struct file *, struct poll_table_struct *); >> long (*ioctl) (struct file *, unsigned int, unsigned long); >> long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); >> + unsigned long (*get_unmapped_area) (struct file *, unsigned long, >> + unsigned long, unsigned long, unsigned long); >> int (*mmap) (struct file *, struct vm_area_struct *); >> int (*open) (struct file *); >> int (*release) (struct file *); > > -- > Regards, > > Laurent Pinchart > -- Regards, --Bob -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/2] V4L/DVB: v4l2-dev: revert commit c29fcff3daafbf46d64a543c1950bbd206ad8c1c
Revert commit: V4L/DVB: v4l2-dev: remove get_unmapped_area(c29fcff3daafbf46d64a543c1950bb) to restore NOMMU arch supporting. Signed-off-by: Bob Liu --- drivers/media/video/v4l2-dev.c | 18 ++ include/media/v4l2-dev.h |2 ++ 2 files changed, 20 insertions(+), 0 deletions(-) diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 6dc7196..19d5ae2 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -352,6 +352,23 @@ static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg) return ret; } +#ifdef CONFIG_MMU +#define v4l2_get_unmapped_area NULL +#else +static unsigned long v4l2_get_unmapped_area(struct file *filp, + unsigned long addr, unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + struct video_device *vdev = video_devdata(filp); + + if (!vdev->fops->get_unmapped_area) + return -ENOSYS; + if (!video_is_registered(vdev)) + return -ENODEV; + return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); +} +#endif + static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm) { struct video_device *vdev = video_devdata(filp); @@ -454,6 +471,7 @@ static const struct file_operations v4l2_fops = { .read = v4l2_read, .write = v4l2_write, .open = v4l2_open, + .get_unmapped_area = v4l2_get_unmapped_area, .mmap = v4l2_mmap, .unlocked_ioctl = v4l2_ioctl, #ifdef CONFIG_COMPAT diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h index 8266d5a..93e96fb 100644 --- a/include/media/v4l2-dev.h +++ b/include/media/v4l2-dev.h @@ -62,6 +62,8 @@ struct v4l2_file_operations { unsigned int (*poll) (struct file *, struct poll_table_struct *); long (*ioctl) (struct file *, unsigned int, unsigned long); long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); + unsigned long (*get_unmapped_area) (struct file *, unsigned long, + unsigned long, unsigned long, unsigned long); int (*mmap) (struct file *, struct vm_area_struct *); int (*open) (struct file *); int (*release) (struct file *); -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/2] media:uvc_driver: Add support for NOMMU arch
Add support to uvc driver for NOMMU arch including add function uvc_queue_get_unmapped_area() and make some changes in uvc_queue_mmap(). So that uvc camera can be used on nommu arch like blackfin. Signed-off-by: Bob Liu --- drivers/media/video/uvc/uvc_queue.c | 34 +- drivers/media/video/uvc/uvc_v4l2.c | 17 + drivers/media/video/uvc/uvcvideo.h |4 3 files changed, 54 insertions(+), 1 deletions(-) diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index f14581b..109a063 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -424,7 +424,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) break; } - if (i == queue->count || size != queue->buf_size) { + if (i == queue->count || PAGE_ALIGN(size) != queue->buf_size) { ret = -EINVAL; goto done; } @@ -436,6 +436,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) vma->vm_flags |= VM_IO; addr = (unsigned long)queue->mem + buffer->buf.m.offset; +#ifdef CONFIG_MMU while (size > 0) { page = vmalloc_to_page((void *)addr); if ((ret = vm_insert_page(vma, start, page)) < 0) @@ -445,6 +446,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) addr += PAGE_SIZE; size -= PAGE_SIZE; } +#endif vma->vm_ops = &uvc_vm_ops; vma->vm_private_data = buffer; @@ -488,6 +490,36 @@ done: return mask; } +#ifndef CONFIG_MMU +/* + * Get unmapped area. + * + * NO-MMU arch need this function to make mmap() work correctly. + */ +unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, + unsigned long pgoff) +{ + struct uvc_buffer *buffer; + unsigned int i; + unsigned long ret; + + mutex_lock(&queue->mutex); + for (i = 0; i < queue->count; ++i) { + buffer = &queue->buffer[i]; + if ((buffer->buf.m.offset >> PAGE_SHIFT) == pgoff) + break; + } + if (i == queue->count) { + ret = -EINVAL; + goto done; + } + ret = (unsigned long)queue->mem + buffer->buf.m.offset; +done: + mutex_unlock(&queue->mutex); + return ret; +} +#endif + /* * Enable or disable the video buffers queue. * diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 9005a8d..d0da5d0 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -1081,6 +1081,20 @@ static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) return uvc_queue_poll(&stream->queue, file, wait); } +#ifndef CONFIG_MMU +static unsigned long uvc_v4l2_get_unmapped_area(struct file *file, + unsigned long addr, unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + struct uvc_fh *handle = file->private_data; + struct uvc_streaming *stream = handle->stream; + + uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n"); + + return uvc_queue_get_unmapped_area(&stream->queue, pgoff); +} +#endif + const struct v4l2_file_operations uvc_fops = { .owner = THIS_MODULE, .open = uvc_v4l2_open, @@ -1089,5 +1103,8 @@ const struct v4l2_file_operations uvc_fops = { .read = uvc_v4l2_read, .mmap = uvc_v4l2_mmap, .poll = uvc_v4l2_poll, +#ifndef CONFIG_MMU + .get_unmapped_area = uvc_v4l2_get_unmapped_area, +#endif }; diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 45f01e7..6aa63c0 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -580,6 +580,10 @@ extern int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma); extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, poll_table *wait); +#ifndef CONFIG_MMU +extern unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, + unsigned long pgoff); +#endif extern int uvc_queue_allocated(struct uvc_video_queue *queue); static inline int uvc_queue_streaming(struct uvc_video_queue *queue) { -- 1.6.3.3 -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v4] media:uvc_driver: add uvc support on no-mmu arch
UVC driver used to have partial no-mmu arch support, but it's removed by commit c29fcff3daafbf46d64a543c1950bbd206ad8c1c. This patch added them back and expanded to fully support no-mmu arch, so that uvc cameras can be used on no-mmu platforms like Blackfin. Signed-off-by: Bob Liu --- drivers/media/video/uvc/uvc_queue.c | 26 +- drivers/media/video/uvc/uvc_v4l2.c | 13 + drivers/media/video/uvc/uvcvideo.h |6 ++ drivers/media/video/v4l2-dev.c | 18 ++ include/media/v4l2-dev.h|2 ++ 5 files changed, 64 insertions(+), 1 deletions(-) diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index f14581b..caf8f6f 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -424,7 +424,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) break; } - if (i == queue->count || size != queue->buf_size) { + if (i == queue->count || PAGE_ALIGN(size) != queue->buf_size) { ret = -EINVAL; goto done; } @@ -436,6 +436,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) vma->vm_flags |= VM_IO; addr = (unsigned long)queue->mem + buffer->buf.m.offset; +#ifdef CONFIG_MMU while (size > 0) { page = vmalloc_to_page((void *)addr); if ((ret = vm_insert_page(vma, start, page)) < 0) @@ -445,6 +446,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) addr += PAGE_SIZE; size -= PAGE_SIZE; } +#endif vma->vm_ops = &uvc_vm_ops; vma->vm_private_data = buffer; @@ -489,6 +491,28 @@ done: } /* + * Get unmapped area. + * + * NO-MMU arch need this function to make mmap() work correctly. + */ +unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, + unsigned long addr, unsigned long len, unsigned long pgoff) +{ + struct uvc_buffer *buffer; + unsigned int i; + + mutex_lock(&queue->mutex); + for (i = 0; i < queue->count; ++i) { + buffer = &queue->buffer[i]; + if ((buffer->buf.m.offset >> PAGE_SHIFT) == pgoff) + break; + } + addr = (unsigned long)queue->mem + buffer->buf.m.offset; + mutex_unlock(&queue->mutex); + return addr; +} + +/* * Enable or disable the video buffers queue. * * The queue must be enabled before starting video acquisition and must be diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 9005a8d..9efab61 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -1081,6 +1081,18 @@ static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) return uvc_queue_poll(&stream->queue, file, wait); } +static unsigned long uvc_v4l2_get_unmapped_area(struct file *file, + unsigned long addr, unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + struct uvc_fh *handle = file->private_data; + struct uvc_streaming *stream = handle->stream; + + uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n"); + + return uvc_queue_get_unmapped_area(&stream->queue, addr, len, pgoff); +} + const struct v4l2_file_operations uvc_fops = { .owner = THIS_MODULE, .open = uvc_v4l2_open, @@ -1089,5 +1101,6 @@ const struct v4l2_file_operations uvc_fops = { .read = uvc_v4l2_read, .mmap = uvc_v4l2_mmap, .poll = uvc_v4l2_poll, + .get_unmapped_area = uvc_v4l2_get_unmapped_area, }; diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 45f01e7..48a2378 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -580,6 +580,12 @@ extern int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma); extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, poll_table *wait); +#ifdef CONFIG_MMU +#define uvc_queue_get_unmapped_area NULL +#else +extern unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, + unsigned long addr, unsigned long len, unsigned long pgoff); +#endif extern int uvc_queue_allocated(struct uvc_video_queue *queue); static inline int uvc_queue_streaming(struct uvc_video_queue *queue) { diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 498e674..221e73f 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/drivers/media/video/v4l2-dev.c @@ -368,6 +368,23 @@ static int v4l2_mmap(struct file *filp, s
Re: [PATCH v3] media:uvc_driver: add uvc support on no-mmu arch
On Thu, Apr 21, 2011 at 5:47 PM, Daniel Glöckner wrote: > On Thu, Apr 21, 2011 at 04:20:36PM +0800, Bob Liu wrote: >> > on mmu systems do_mmap_pgoff contains a len = PAGE_ALIGN(len); line. >> > If we depend on this behavior, why not do it here as well and get rid >> > of the #ifdef? >> > >> >> If do it in do_mmap_pgoff() the whole system will be effected, I am >> not sure whether >> it's correct and needed for other subsystem. > > With "here" I was referring to uvc_queue_mmap. > I am sorry, I didn't get your idea. You mean using PAGE_ALIGN() here for both mmu and no-mmu arch ? >> >> + addr = (unsigned long)queue->mem + buffer->buf.m.offset; >> >> + ret = addr; >> > >> > Why the intermediate step using addr? >> > >> >> If don't return addr, do_mmap_pgoff() will return failure and we can't >> setup vma correctly. >> See mm/nommu.c line 1386(add = file->f_op->get_unmmapped_area() ). > > I know, but why not do > ret = (unsigned long)queue->mem + buffer->buf.m.offset; > instead? > Okay. Thanks -- Regards, --Bob -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH v3] media:uvc_driver: add uvc support on no-mmu arch
On Thu, Apr 21, 2011 at 3:59 PM, Daniel Glöckner wrote: > Hi Bob, > > On Thu, Apr 21, 2011 at 11:17:42AM +0800, Bob Liu wrote: >> +#ifdef CONFIG_MMU >> if (i == queue->count || size != queue->buf_size) { >> +#else >> + if (i == queue->count || PAGE_ALIGN(size) != queue->buf_size) { >> +#endif > > on mmu systems do_mmap_pgoff contains a len = PAGE_ALIGN(len); line. > If we depend on this behavior, why not do it here as well and get rid > of the #ifdef? > If do it in do_mmap_pgoff() the whole system will be effected, I am not sure whether it's correct and needed for other subsystem. >> +unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, >> + unsigned long addr, unsigned long len, unsigned long pgoff) >> +{ >> + struct uvc_buffer *buffer; >> + unsigned int i; >> + int ret = 0; > > You still didn't change ret to unsigned long. > Oh, Sorry. My fault. >> + addr = (unsigned long)queue->mem + buffer->buf.m.offset; >> + ret = addr; > > Why the intermediate step using addr? > If don't return addr, do_mmap_pgoff() will return failure and we can't setup vma correctly. See mm/nommu.c line 1386(add = file->f_op->get_unmmapped_area() ). >> diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c >> index 498e674..221e73f 100644 >> --- a/drivers/media/video/v4l2-dev.c >> +++ b/drivers/media/video/v4l2-dev.c >> @@ -368,6 +368,23 @@ static int v4l2_mmap(struct file *filp, struct >> vm_area_struct *vm) >> return ret; >> } >> >> +#ifdef CONFIG_MMU >> +#define v4l2_get_unmapped_area NULL >> +#else >> +static unsigned long v4l2_get_unmapped_area(struct file *filp, >> + unsigned long addr, unsigned long len, unsigned long pgoff, >> + unsigned long flags) >> +{ >> + struct video_device *vdev = video_devdata(filp); >> + >> + if (!vdev->fops->get_unmapped_area) >> + return -ENOSYS; >> + if (!video_is_registered(vdev)) >> + return -ENODEV; >> + return vdev->fops->get_unmapped_area(filp, addr, len, pgoff, flags); >> +} >> +#endif >> + >> /* Override for the open function */ >> static int v4l2_open(struct inode *inode, struct file *filp) >> { >> @@ -452,6 +469,7 @@ static const struct file_operations v4l2_fops = { >> .write = v4l2_write, >> .open = v4l2_open, >> .mmap = v4l2_mmap, >> + .get_unmapped_area = v4l2_get_unmapped_area, >> .unlocked_ioctl = v4l2_ioctl, >> #ifdef CONFIG_COMPAT >> .compat_ioctl = v4l2_compat_ioctl32, >> diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h >> index 8266d5a..0616a43 100644 >> --- a/include/media/v4l2-dev.h >> +++ b/include/media/v4l2-dev.h >> @@ -63,6 +63,8 @@ struct v4l2_file_operations { >> long (*ioctl) (struct file *, unsigned int, unsigned long); >> long (*unlocked_ioctl) (struct file *, unsigned int, unsigned long); >> int (*mmap) (struct file *, struct vm_area_struct *); >> + unsigned long (*get_unmapped_area) (struct file *, unsigned long, >> + unsigned long, unsigned long, unsigned long); >> int (*open) (struct file *); >> int (*release) (struct file *); >> }; > > I'd prefer a git revert c29fcff3daafbf46d64a543c1950bbd206ad8c1c for > this block instead of reverting it together with the UVC changes. > Okay, I will confirm that and do it. Thanks a lot for your review. -- Regards, --Bob -- To unsubscribe from this list: send the line "unsubscribe linux-media" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3] media:uvc_driver: add uvc support on no-mmu arch
UVC driver used to have partial no-mmu arch support, but it's removed by commit c29fcff3daafbf46d64a543c1950bbd206ad8c1c. This patch added them back and expanded to fully support no-mmu arch, so that uvc cameras can be used on no-mmu platforms like Blackfin. Signed-off-by: Bob Liu --- drivers/media/video/uvc/uvc_queue.c | 30 ++ drivers/media/video/uvc/uvc_v4l2.c | 13 + drivers/media/video/uvc/uvcvideo.h |6 ++ drivers/media/video/v4l2-dev.c | 18 ++ include/media/v4l2-dev.h|2 ++ 5 files changed, 69 insertions(+), 0 deletions(-) diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index f14581b..448a753 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -424,7 +424,11 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) break; } +#ifdef CONFIG_MMU if (i == queue->count || size != queue->buf_size) { +#else + if (i == queue->count || PAGE_ALIGN(size) != queue->buf_size) { +#endif ret = -EINVAL; goto done; } @@ -436,6 +440,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) vma->vm_flags |= VM_IO; addr = (unsigned long)queue->mem + buffer->buf.m.offset; +#ifdef CONFIG_MMU while (size > 0) { page = vmalloc_to_page((void *)addr); if ((ret = vm_insert_page(vma, start, page)) < 0) @@ -445,6 +450,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) addr += PAGE_SIZE; size -= PAGE_SIZE; } +#endif vma->vm_ops = &uvc_vm_ops; vma->vm_private_data = buffer; @@ -489,6 +495,30 @@ done: } /* + * Get unmapped area. + * + * NO-MMU arch need this function to make mmap() work correctly. + */ +unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, + unsigned long addr, unsigned long len, unsigned long pgoff) +{ + struct uvc_buffer *buffer; + unsigned int i; + int ret = 0; + + mutex_lock(&queue->mutex); + for (i = 0; i < queue->count; ++i) { + buffer = &queue->buffer[i]; + if ((buffer->buf.m.offset >> PAGE_SHIFT) == pgoff) + break; + } + addr = (unsigned long)queue->mem + buffer->buf.m.offset; + ret = addr; + mutex_unlock(&queue->mutex); + return ret; +} + +/* * Enable or disable the video buffers queue. * * The queue must be enabled before starting video acquisition and must be diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 9005a8d..9efab61 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -1081,6 +1081,18 @@ static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) return uvc_queue_poll(&stream->queue, file, wait); } +static unsigned long uvc_v4l2_get_unmapped_area(struct file *file, + unsigned long addr, unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + struct uvc_fh *handle = file->private_data; + struct uvc_streaming *stream = handle->stream; + + uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n"); + + return uvc_queue_get_unmapped_area(&stream->queue, addr, len, pgoff); +} + const struct v4l2_file_operations uvc_fops = { .owner = THIS_MODULE, .open = uvc_v4l2_open, @@ -1089,5 +1101,6 @@ const struct v4l2_file_operations uvc_fops = { .read = uvc_v4l2_read, .mmap = uvc_v4l2_mmap, .poll = uvc_v4l2_poll, + .get_unmapped_area = uvc_v4l2_get_unmapped_area, }; diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 45f01e7..48a2378 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -580,6 +580,12 @@ extern int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma); extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, poll_table *wait); +#ifdef CONFIG_MMU +#define uvc_queue_get_unmapped_area NULL +#else +extern unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, + unsigned long addr, unsigned long len, unsigned long pgoff); +#endif extern int uvc_queue_allocated(struct uvc_video_queue *queue); static inline int uvc_queue_streaming(struct uvc_video_queue *queue) { diff --git a/drivers/media/video/v4l2-dev.c b/drivers/media/video/v4l2-dev.c index 498e674..221e73f 100644 --- a/drivers/media/video/v4l2-dev.c +++ b/driv
Re: Fwd: [PATCH v2] media: uvc_driver: add NO-MMU arch support
On Wed, Apr 20, 2011 at 4:59 PM, Daniel Glöckner wrote: > On Wed, Apr 20, 2011 at 02:02:41PM +0800, Bob Liu wrote: >> -- Forwarded message -- > > Forwarding broke tabs. > Hi, Daniel Thanks for your review, I will make a new patch later. >> @@ -445,6 +446,20 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, >> struct vm_area_struct *vma) >> addr += PAGE_SIZE; >> size -= PAGE_SIZE; >> } >> +#else >> + if (i == queue->count || >> + PAGE_ALIGN(size) != queue->buf_size) { > > Why do you need to round up size on nommu? > If didn't round up, it always return -EINVAL. I don't know why config-mmu doesn't have this problem. I use luvcview for testing and added some print, you can see that size always != queue->buf_size. So we need round up. root:/> luvcview -f yuv -s 320x240 -i 30 luvcview 0.2.4 SDL information: Video driver: fbcon Hardware surfaces are available (382k video memory) Device information: Device path: /dev/video0 Stream settings: Frame format: YUYV Frame size: 320x240 Fsaiz e tis 03x2f5800, align size is 0x26000, bufsize is 0x26000 size is 0x25800, align size is 0x26000, bufsize is 0x26000 Unable to map buffer: Invalid argument Init v4L2 failed !! exit fatal root:/> >> + ret = -EINVAL; >> + goto done; >> + } >> + >> + /* documentation/nommu-mmap.txt */ > > I don't see where Documentation/nommu-mmap.txt provides any information > on the following line(s). > I will rm it, sorry for that. >> + vma->vm_flags |= VM_IO | VM_MAYSHARE; >> + >> + addr = (unsigned long)queue->mem + buffer->buf.m.offset; >> + vma->vm_start = addr; >> + vma->vm_end = addr + queue->buf_size; > > You don't need to do this here. vm_start and vm_end have already been > modified like this by do_mmap_pgoff after get_unmapped_area had been > called. > will rm also. >> +#endif >> >> vma->vm_ops = &uvc_vm_ops; >> vma->vm_private_data = buffer; >> @@ -489,6 +504,38 @@ done: >> } >> >> /* >> + * Get unmapped area. >> + * >> + * NO-MMU arch need this function to make mmap() work correctly. >> + */ >> +unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, >> + unsigned long addr, unsigned long len, unsigned long pgoff) >> +{ >> + struct uvc_buffer *buffer; >> + unsigned int i; >> + int ret = 0; > > ret should be an unsigned long. You later try to store a pointer in > there. > okay. >> + >> + mutex_lock(&queue->mutex); >> + for (i = 0; i < queue->count; ++i) { >> + buffer = &queue->buffer[i]; >> + if ((buffer->buf.m.offset >> PAGE_SHIFT) == pgoff) >> + break; >> + } >> + >> + if (i == queue->count || >> + PAGE_ALIGN(len) != queue->buf_size) { >> + ret = -EINVAL; >> + goto done; >> + } >> + >> + addr = (unsigned long)queue->mem + buffer->buf.m.offset; >> + ret = addr; >> +done: >> + mutex_unlock(&queue->mutex); >> + return ret; >> +} >> + >> +/* >> * Enable or disable the video buffers queue. >> * >> * The queue must be enabled before starting video acquisition and must be >> diff --git a/drivers/media/video/uvc/uvc_v4l2.c >> b/drivers/media/video/uvc/uvc_v4l2.c >> index 9005a8d..9efab61 100644 >> --- a/drivers/media/video/uvc/uvc_v4l2.c >> +++ b/drivers/media/video/uvc/uvc_v4l2.c >> @@ -1081,6 +1081,18 @@ static unsigned int uvc_v4l2_poll(struct file >> *file, poll_table *wait) >> return uvc_queue_poll(&stream->queue, file, wait); >> } >> >> +static unsigned long uvc_v4l2_get_unmapped_area(struct file *file, >> + unsigned long addr, unsigned long len, unsigned long pgoff, >> + unsigned long flags) >> +{ >> + struct uvc_fh *handle = file->private_data; >> + struct uvc_streaming *stream = handle->stream; >> + >> + uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n"); >> + >> + return uvc_queue_get_unmapped_area(&stream->queue, addr, len, pgoff); >> +} >> + >> const struct v4l2_file_operations uvc_fops = { >> .owner = THIS_MODULE, >> .open
Fwd: [PATCH v2] media: uvc_driver: add NO-MMU arch support
-- Forwarded message -- From: Bob Liu Date: Fri, Apr 8, 2011 at 7:16 PM Subject: [PATCH v2] media: uvc_driver: add NO-MMU arch support To: linux-ker...@vger.kernel.org Cc: mche...@redhat.com, hverk...@xs4all.nl, laurent.pinch...@ideasonboard.com, sakari.ai...@maxwell.research.nokia.com, martin_ru...@logitech.com, ja...@redhat.com, t...@kernel.org, a...@arndb.de, fweis...@gmail.com, ag...@denx.de, gre...@suse.de, Bob Liu UVC driver used to have partial no-mmu arch support, but it's removed by commit c29fcff3daafbf46d64a543c1950bbd206ad8c1c. This patch added them back and expanded to fully support no-mmu arch, so that uvc cameras can be used on no-mmu platforms like Blackfin. Signed-off-by: Bob Liu --- drivers/media/video/uvc/uvc_queue.c | 47 +++ drivers/media/video/uvc/uvc_v4l2.c | 13 + drivers/media/video/uvc/uvcvideo.h | 6 drivers/media/video/v4l2-dev.c | 18 + include/media/v4l2-dev.h | 2 + 5 files changed, 86 insertions(+), 0 deletions(-) diff --git a/drivers/media/video/uvc/uvc_queue.c b/drivers/media/video/uvc/uvc_queue.c index f14581b..e505afe 100644 --- a/drivers/media/video/uvc/uvc_queue.c +++ b/drivers/media/video/uvc/uvc_queue.c @@ -424,6 +424,7 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) break; } +#ifdef CONFIG_MMU if (i == queue->count || size != queue->buf_size) { ret = -EINVAL; goto done; @@ -445,6 +446,20 @@ int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma) addr += PAGE_SIZE; size -= PAGE_SIZE; } +#else + if (i == queue->count || + PAGE_ALIGN(size) != queue->buf_size) { + ret = -EINVAL; + goto done; + } + + /* documentation/nommu-mmap.txt */ + vma->vm_flags |= VM_IO | VM_MAYSHARE; + + addr = (unsigned long)queue->mem + buffer->buf.m.offset; + vma->vm_start = addr; + vma->vm_end = addr + queue->buf_size; +#endif vma->vm_ops = &uvc_vm_ops; vma->vm_private_data = buffer; @@ -489,6 +504,38 @@ done: } /* + * Get unmapped area. + * + * NO-MMU arch need this function to make mmap() work correctly. + */ +unsigned long uvc_queue_get_unmapped_area(struct uvc_video_queue *queue, + unsigned long addr, unsigned long len, unsigned long pgoff) +{ + struct uvc_buffer *buffer; + unsigned int i; + int ret = 0; + + mutex_lock(&queue->mutex); + for (i = 0; i < queue->count; ++i) { + buffer = &queue->buffer[i]; + if ((buffer->buf.m.offset >> PAGE_SHIFT) == pgoff) + break; + } + + if (i == queue->count || + PAGE_ALIGN(len) != queue->buf_size) { + ret = -EINVAL; + goto done; + } + + addr = (unsigned long)queue->mem + buffer->buf.m.offset; + ret = addr; +done: + mutex_unlock(&queue->mutex); + return ret; +} + +/* * Enable or disable the video buffers queue. * * The queue must be enabled before starting video acquisition and must be diff --git a/drivers/media/video/uvc/uvc_v4l2.c b/drivers/media/video/uvc/uvc_v4l2.c index 9005a8d..9efab61 100644 --- a/drivers/media/video/uvc/uvc_v4l2.c +++ b/drivers/media/video/uvc/uvc_v4l2.c @@ -1081,6 +1081,18 @@ static unsigned int uvc_v4l2_poll(struct file *file, poll_table *wait) return uvc_queue_poll(&stream->queue, file, wait); } +static unsigned long uvc_v4l2_get_unmapped_area(struct file *file, + unsigned long addr, unsigned long len, unsigned long pgoff, + unsigned long flags) +{ + struct uvc_fh *handle = file->private_data; + struct uvc_streaming *stream = handle->stream; + + uvc_trace(UVC_TRACE_CALLS, "uvc_v4l2_get_unmapped_area\n"); + + return uvc_queue_get_unmapped_area(&stream->queue, addr, len, pgoff); +} + const struct v4l2_file_operations uvc_fops = { .owner = THIS_MODULE, .open = uvc_v4l2_open, @@ -1089,5 +1101,6 @@ const struct v4l2_file_operations uvc_fops = { .read = uvc_v4l2_read, .mmap = uvc_v4l2_mmap, .poll = uvc_v4l2_poll, + .get_unmapped_area = uvc_v4l2_get_unmapped_area, }; diff --git a/drivers/media/video/uvc/uvcvideo.h b/drivers/media/video/uvc/uvcvideo.h index 45f01e7..48a2378 100644 --- a/drivers/media/video/uvc/uvcvideo.h +++ b/drivers/media/video/uvc/uvcvideo.h @@ -580,6 +580,12 @@ extern int uvc_queue_mmap(struct uvc_video_queue *queue, struct vm_area_struct *vma); extern unsigned int uvc_queue_poll(struct uvc_video_queue *queue, struct file *file, poll_table *wait); +