videobuf_dma_sg: a new implementation for mmap
PATCH 1/1 videobuf_dma_sg: a new implementation for mmap
a mmap issue for videobuf-dma-sg: it will alloc a new page for mmaping when it encounter page fault at video_vm_ops->fault().
a new implementation for mmap, it translate the vmalloc to page at video_vm_ops->fault().
---drivers/media/video/videobuf-dma-sg.c | 38
++++++++++++++++++++++++++++----
1 files changed, 33 insertions(+), 5 deletions(-)
(quoted diff) +0 -0
b/drivers/media/video/videobuf-dma-sg.c
index 8359e6b..c9a8817 100644
drivers/media/video/videobuf-dma-sg.c +0 -0
@@ -397,16 +397,44 @@ static void videobuf_vm_close(struct
vm_area_struct *vma)
*/
static int videobuf_vm_fault(struct vm_area_struct *vma, structvm_fault *vmf)
{
- struct page *page;
+ struct page *page = NULL;
+ struct videobuf_mapping *map = vma->vm_private_data;
+ struct videobuf_queue *q = map->q;
+ struct videobuf_dma_sg_memory *mem = NULL;
+
+ unsigned long offset;
+ unsigned long page_nr;
+ int first;
dprintk(3, "fault: fault @ %08lx [vma %08lx-%08lx]\n",
(unsigned long)vmf->virtual_address, vma->vm_start, vma->vm_end);
- page = alloc_page(GFP_USER | __GFP_DMA32);
- if (!page)
- return VM_FAULT_OOM;
- clear_user_highpage(page, (unsigned long)vmf->virtual_address);
+ mutex_lock(&q->vb_lock);
+
+ offset = (unsigned long)vmf->virtual_address - vma->vm_start;
+ page_nr = offset >> PAGE_SHIFT;
+
+ for (first = 0; first < VIDEO_MAX_FRAME; first++) {
+ if (NULL == q->bufs[first])
+ continue;
+
+ MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
+
+ if (q->bufs[first]->map == map)
+ break;
+ }
+
+ mem = q->bufs[first]->priv;
+ if (!mem)
+ return VM_FAULT_SIGBUS;
+ if (mem->dma.vmalloc)
+ page = vmalloc_to_page(mem->dma.vmalloc+
+ (offset & (~PAGE_MASK)));
+ if (mem->dma.pages)
+ page = mem->dma.pages[page_nr];
+ mutex_unlock(&q->vb_lock);
+
vmf->page = page;
return 0;
Hi,
Quoted 5 lines · On Tuesday 27 July 2010 14:21:40 Figo.zhang wrote:
a mmap issue for videobuf-dma-sg: it will alloc a new page for mmaping when it encounter page fault at
video_vm_ops->fault().a new implementation for mmap, it translate the vmalloc to page at
video_vm_ops->fault().
How is that supposed to work ? mem->dma.vmalloc is NULL in the vm_fault handler for V4L2_MEMORY_MMAP buffers. Have you tested the code at all ?
Quoted 63 lines
Signed-off-by Figo.zhang <[email protected]>---
drivers/media/video/videobuf-dma-sg.c| 38
++++++++++++++++++++++++++++----1 files changed, 33 insertions(+), 5 deletions(-)drivers/media/video/videobuf-dma-sg.c +33
-5@@ -397,16 +397,44 @@ static void videobuf_vm_close(structvm_area_struct *vma) */ static int videobuf_vm_fault (struct vm_area_struct *vma,struct vm_fault *vmf) { -struct page *page; +struct page *page =NULL ; +struct videobuf_mapping *map = vma->vm_private_data; +struct videobuf_queue *q = map->q; +struct videobuf_dma_sg_memory *mem =NULL ; + +unsigned long offset; +unsigned long page_nr; +int first;dprintk (3 ,"fault: fault @ %08lx [vma %08lx-%08lx]\n" , (unsigned long )vmf->virtual_address, vma->vm_start, vma->vm_end); - page =alloc_page (GFP_USER | __GFP_DMA32); -if (!page) -return VM_FAULT_OOM ; -clear_user_highpage (page, (unsigned long )vmf->virtual_address); +mutex_lock (&q->vb_lock); + + offset = (unsigned long )vmf->virtual_address - vma->vm_start; + page_nr = offset >>PAGE_SHIFT ; + +for (first =0 ; first <VIDEO_MAX_FRAME ; first++) { +if (NULL == q->bufs[first]) +continue ; + +MAGIC_CHECK (mem->magic,MAGIC_SG_MEM ); + +if (q->bufs[first]->map == map) +break ; + } + + mem = q->bufs[first]->priv; +if (!mem) +return VM_FAULT_SIGBUS ; +if (mem->dma.vmalloc) + page =vmalloc_to_page (mem->dma.vmalloc+ + (offset & (~PAGE_MASK ))); +if (mem->dma.pages) + page = mem->dma.pages[page_nr]; +mutex_unlock (&q->vb_lock); + vmf->page = page;return 0;
Signature · 3 lines
Regards, Laurent Pinchart
PATCH v2 1/1 videobuf_dma_sg: a new implementation for mmap
In reply to Figo.zhanga mmap issue for videobuf-dma-sg: it will alloc a new page for mmaping when it encounter page fault at video_vm_ops->fault().
a new implementation for mmap, it translate the vmalloc to page at video_vm_ops->fault().
in v2, if mem->dma.vmalloc is NULL at video_vm_ops->fault(), it will alloc memory by vmalloc_32().
--- drivers/media/video/videobuf-dma-sg.c | 51 +++++++++++++++++++++++++++------ 1 files changed, 42 insertions(+), 9 deletions(-)
(quoted diff) +0 -0
b/drivers/media/video/videobuf-dma-sg.c
index 8359e6b..767483d 100644
drivers/media/video/videobuf-dma-sg.c +0 -0
@@ -201,10 +201,11 @@ int videobuf_dma_init_kernel(struct
videobuf_dmabuf *dma, int direction,
dprintk(1, "init kernel [%d pages]\n", nr_pages);
dma->direction = direction;
- dma->vmalloc = vmalloc_32(nr_pages << PAGE_SHIFT);
- if (NULL == dma->vmalloc) {
- dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages);
- return -ENOMEM;
+ if (!dma->vmalloc)
+ dma->vmalloc = vmalloc_32(nr_pages << PAGE_SHIFT);
+ if (NULL == dma->vmalloc) {
+ dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages);
+ return -ENOMEM;
}
dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n",
@@ -397,16 +398,48 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
*/
static int videobuf_vm_fault(struct vm_area_struct *vma, structvm_fault *vmf)
{
- struct page *page;
+ struct page *page = NULL;
+ struct videobuf_mapping *map = vma->vm_private_data;
+ struct videobuf_queue *q = map->q;
+ struct videobuf_dma_sg_memory *mem = NULL;
+
+ unsigned long offset;
+ unsigned long page_nr;
+ int first;
dprintk(3, "fault: fault @ %08lx [vma %08lx-%08lx]\n",
(unsigned long)vmf->virtual_address, vma->vm_start, vma->vm_end);
- page = alloc_page(GFP_USER | __GFP_DMA32);
- if (!page)
- return VM_FAULT_OOM;
- clear_user_highpage(page, (unsigned long)vmf->virtual_address);
+ mutex_lock(&q->vb_lock);
+
+ offset = (unsigned long)vmf->virtual_address - vma->vm_start;
+ page_nr = offset >> PAGE_SHIFT;
+
+ for (first = 0; first < VIDEO_MAX_FRAME; first++) {
+ if (NULL == q->bufs[first])
+ continue;
+
+ MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
+
+ if (q->bufs[first]->map == map)
+ break;
+ }
+
+ mem = q->bufs[first]->priv;
+ if (!mem)
+ return VM_FAULT_SIGBUS;
+ if (!mem->dma.vmalloc) {
+ mem->dma.vmalloc = vmalloc_32(PAGE_ALIGN(q->bufs[first]->size));
+ if (NULL == mem->dma.vmalloc) {
+ dprintk(1, "%s: vmalloc_32() failed\n", __func__);
+ return VM_FAULT_OOM;
+ }
+ } else
+ page = vmalloc_to_page(mem->dma.vmalloc+
+ (offset & (~PAGE_MASK)));
+ mutex_unlock(&q->vb_lock);
+
vmf->page = page;
return 0;
PATCH v2 1/1 videobuf_dma_sg: a new implementation for mmap
a mmap issue for videobuf-dma-sg: it will alloc a new page for mmaping when it encounter page fault at video_vm_ops->fault().
a new implementation for mmap, it translate the vmalloc to page at video_vm_ops->fault().
in v2, if mem->dma.vmalloc is NULL at video_vm_ops->fault(), it will alloc memory by vmalloc_32().
---drivers/media/video/videobuf-dma-sg.c | 51
+++++++++++++++++++++++++++------
1 files changed, 42 insertions(+), 9 deletions(-)
(quoted diff) +0 -0
b/drivers/media/video/videobuf-dma-sg.c
index 8359e6b..767483d 100644
drivers/media/video/videobuf-dma-sg.c +0 -0
@@ -201,10 +201,11 @@ int videobuf_dma_init_kernel(struct
videobuf_dmabuf *dma, int direction,
dprintk(1, "init kernel [%d pages]\n", nr_pages);
dma->direction = direction;
- dma->vmalloc = vmalloc_32(nr_pages << PAGE_SHIFT);
- if (NULL == dma->vmalloc) {
- dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages);
- return -ENOMEM;
+ if (!dma->vmalloc)
+ dma->vmalloc = vmalloc_32(nr_pages << PAGE_SHIFT);
+ if (NULL == dma->vmalloc) {
+ dprintk(1, "vmalloc_32(%d pages) failed\n", nr_pages);
+ return -ENOMEM;
}
dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n",
@@ -397,16 +398,48 @@ static void videobuf_vm_close(struct vm_area_struct *vma)
*/
static int videobuf_vm_fault(struct vm_area_struct *vma, structvm_fault *vmf)
{
- struct page *page;
+ struct page *page = NULL;
+ struct videobuf_mapping *map = vma->vm_private_data;
+ struct videobuf_queue *q = map->q;
+ struct videobuf_dma_sg_memory *mem = NULL;
+
+ unsigned long offset;
+ unsigned long page_nr;
+ int first;
dprintk(3, "fault: fault @ %08lx [vma %08lx-%08lx]\n",
(unsigned long)vmf->virtual_address, vma->vm_start, vma->vm_end);
- page = alloc_page(GFP_USER | __GFP_DMA32);
- if (!page)
- return VM_FAULT_OOM;
- clear_user_highpage(page, (unsigned long)vmf->virtual_address);
+ mutex_lock(&q->vb_lock);
+
+ offset = (unsigned long)vmf->virtual_address - vma->vm_start;
+ page_nr = offset >> PAGE_SHIFT;
+
+ for (first = 0; first < VIDEO_MAX_FRAME; first++) {
+ if (NULL == q->bufs[first])
+ continue;
+
+ MAGIC_CHECK(mem->magic, MAGIC_SG_MEM);
+
+ if (q->bufs[first]->map == map)
+ break;
+ }
+
+ mem = q->bufs[first]->priv;
+ if (!mem)
+ return VM_FAULT_SIGBUS;
+ if (!mem->dma.vmalloc) {
+ mem->dma.vmalloc = vmalloc_32(PAGE_ALIGN(q->bufs[first]->size));
+ if (NULL == mem->dma.vmalloc) {
+ dprintk(1, "%s: vmalloc_32() failed\n", __func__);
+ return VM_FAULT_OOM;
+ }
+ } else
+ page = vmalloc_to_page(mem->dma.vmalloc+
+ (offset & (~PAGE_MASK)));
+ mutex_unlock(&q->vb_lock);
+
vmf->page = page;
return 0;
hi Laurent,
would you like to test this patch?
btw, why i send the patch , patchwork websit display a part of my patch?
https://patchwork.kernel.org/patch/114760/
Best,
Figo.zhang
Quoted 94 lines · Figo.zhang
a mmap issue for videobuf-dma-sg: it will alloc a new page for mmaping when it encounter page fault at
video_vm_ops->fault().a new implementation for mmap, it translate the vmalloc to page at
video_vm_ops->fault().in v2, if
mem->dma.vmallocis NULL atvideo_vm_ops->fault(), it will alloc memory byvmalloc_32().Signed-off-by Figo.zhang <[email protected]>---
drivers/media/video/videobuf-dma-sg.c| 51
+++++++++++++++++++++++++++------1 files changed, 42 insertions(+), 9 deletions(-)drivers/media/video/videobuf-dma-sg.c +5
-4@@ -201,10 +201,11 @@ int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, dprintk(1, "init kernel [%d pages]\n", nr_pages); dma->direction = direction; - dma->vmalloc =vmalloc_32 (nr_pages <<PAGE_SHIFT ); -if (NULL == dma->vmalloc) { -dprintk (1 ,"vmalloc_32(%d pages) failed\n" , nr_pages); -return -ENOMEM ; +if (!dma->vmalloc) + dma->vmalloc =vmalloc_32 (nr_pages <<PAGE_SHIFT ); +if (NULL == dma->vmalloc) { +dprintk (1 ,"vmalloc_32(%d pages) failed\n" , nr_pages); +return -ENOMEM ; }drivers/media/video/videobuf-dma-sg.c +37
-5dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n",@@ -397,16 +398,48 @@ static void videobuf_vm_close(structvm_area_struct *vma) */ static int videobuf_vm_fault (struct vm_area_struct *vma,struct vm_fault *vmf) { -struct page *page; +struct page *page =NULL ; +struct videobuf_mapping *map = vma->vm_private_data; +struct videobuf_queue *q = map->q; +struct videobuf_dma_sg_memory *mem =NULL ; + +unsigned long offset; +unsigned long page_nr; +int first;dprintk (3 ,"fault: fault @ %08lx [vma %08lx-%08lx]\n" , (unsigned long )vmf->virtual_address, vma->vm_start, vma->vm_end); - page =alloc_page (GFP_USER | __GFP_DMA32); -if (!page) -return VM_FAULT_OOM ; -clear_user_highpage (page, (unsigned long )vmf->virtual_address); +mutex_lock (&q->vb_lock); + + offset = (unsigned long )vmf->virtual_address - vma->vm_start; + page_nr = offset >>PAGE_SHIFT ; + +for (first =0 ; first <VIDEO_MAX_FRAME ; first++) { +if (NULL == q->bufs[first]) +continue ; + +MAGIC_CHECK (mem->magic,MAGIC_SG_MEM ); + +if (q->bufs[first]->map == map) +break ; + } + + mem = q->bufs[first]->priv; +if (!mem) +return VM_FAULT_SIGBUS ; +if (!mem->dma.vmalloc) { + mem->dma.vmalloc =vmalloc_32 (PAGE_ALIGN (q->bufs[first]->size)); +if (NULL == mem->dma.vmalloc) { +dprintk (1 ,"%s: vmalloc_32() failed\n" , __func__); +return VM_FAULT_OOM ; + } + }else + page =vmalloc_to_page (mem->dma.vmalloc+ + (offset & (~PAGE_MASK ))); +mutex_unlock (&q->vb_lock); + vmf->page = page;return 0;
Em 29-07-2010 10:38, Figo.zhang escreveu:
Quoted 2 lines
btw, why i send the patch , patchwork websit display a part of my patch?
https://patchwork.kernel.org/patch/114760/
Because your emailer broke long lines, mangling part of your patch. The way you sent, it will fail to apply.
Please, re-send it, being sure that your emailer won't break long lines.
Cheers,
Mauro.
Hi,
Quoted 8 lines · On Wednesday 28 July 2010 15:08:24 Figo.zhang wrote:
a mmap issue for videobuf-dma-sg: it will alloc a new page for mmaping when it encounter page fault at
video_vm_ops->fault().a new implementation for mmap, it translate the vmalloc to page at
video_vm_ops->fault().in v2, if
mem->dma.vmallocis NULL atvideo_vm_ops->fault(), it will alloc memory byvmalloc_32().
Can you please elaborate on what you're trying to do ? What problem is this patch supposed to fix ?
Quoted 84 lines
Signed-off-by Figo.zhang <[email protected]>---
drivers/media/video/videobuf-dma-sg.c| 51
+++++++++++++++++++++++++++------1 files changed, 42 insertions(+), 9 deletions(-)drivers/media/video/videobuf-dma-sg.c +5
-4@@ -201,10 +201,11 @@ int videobuf_dma_init_kernel(struct videobuf_dmabuf *dma, int direction, dprintk(1, "init kernel [%d pages]\n", nr_pages); dma->direction = direction; - dma->vmalloc =vmalloc_32 (nr_pages <<PAGE_SHIFT ); -if (NULL == dma->vmalloc) { -dprintk (1 ,"vmalloc_32(%d pages) failed\n" , nr_pages); -return -ENOMEM ; +if (!dma->vmalloc) + dma->vmalloc =vmalloc_32 (nr_pages <<PAGE_SHIFT ); +if (NULL == dma->vmalloc) { +dprintk (1 ,"vmalloc_32(%d pages) failed\n" , nr_pages); +return -ENOMEM ; }drivers/media/video/videobuf-dma-sg.c +37
-5dprintk(1, "vmalloc is at addr 0x%08lx, size=%d\n",@@ -397,16 +398,48 @@ static void videobuf_vm_close(structvm_area_struct *vma) */ static int videobuf_vm_fault (struct vm_area_struct *vma,struct vm_fault *vmf) { -struct page *page; +struct page *page =NULL ; +struct videobuf_mapping *map = vma->vm_private_data; +struct videobuf_queue *q = map->q; +struct videobuf_dma_sg_memory *mem =NULL ; + +unsigned long offset; +unsigned long page_nr; +int first;dprintk (3 ,"fault: fault @ %08lx [vma %08lx-%08lx]\n" , (unsigned long )vmf->virtual_address, vma->vm_start, vma->vm_end); - page =alloc_page (GFP_USER | __GFP_DMA32); -if (!page) -return VM_FAULT_OOM ; -clear_user_highpage (page, (unsigned long )vmf->virtual_address); +mutex_lock (&q->vb_lock); + + offset = (unsigned long )vmf->virtual_address - vma->vm_start; + page_nr = offset >>PAGE_SHIFT ; + +for (first =0 ; first <VIDEO_MAX_FRAME ; first++) { +if (NULL == q->bufs[first]) +continue ; + +MAGIC_CHECK (mem->magic,MAGIC_SG_MEM ); + +if (q->bufs[first]->map == map) +break ; + } + + mem = q->bufs[first]->priv; +if (!mem) +return VM_FAULT_SIGBUS ; +if (!mem->dma.vmalloc) { + mem->dma.vmalloc =vmalloc_32 (PAGE_ALIGN (q->bufs[first]->size)); +if (NULL == mem->dma.vmalloc) { +dprintk (1 ,"%s: vmalloc_32() failed\n" , __func__); +return VM_FAULT_OOM ; + } + }else + page =vmalloc_to_page (mem->dma.vmalloc+ + (offset & (~PAGE_MASK ))); +mutex_unlock (&q->vb_lock); + vmf->page = page;return 0;
Signature · 3 lines
Regards, Laurent Pinchart