* [PATCH] videobuf-dma-contig: zero copy USERPTR support V2
@ 2009-04-28 9:01 Magnus Damm
2009-05-01 3:26 ` Magnus Damm
0 siblings, 1 reply; 15+ messages in thread
From: Magnus Damm @ 2009-04-28 9:01 UTC (permalink / raw)
To: linux-media; +Cc: hverkuil, linux-mm, Magnus Damm, lethal, hannes
From: Magnus Damm <damm@igel.co.jp>
This is V2 of the V4L2 videobuf-dma-contig USERPTR zero copy patch.
Since videobuf-dma-contig is designed to handle physically contiguous
memory, this patch modifies the videobuf-dma-contig code to only accept
a pointer to physically contiguous memory. For now only VM_PFNMAP vmas
are supported, so forget hotplug.
On SuperH Mobile we use this approach for our sh_mobile_ceu_camera driver
together with various multimedia accelerator blocks that are exported to
user space using UIO. The UIO kernel code exports physically contiugous
memory to user space and lets the user space application mmap() this memory
and pass a pointer using the USERPTR interface for V4L2 zero copy operation.
With this approach we support zero copy capture, hardware scaling and
various forms of hardware encoding and decoding.
Signed-off-by: Magnus Damm <damm@igel.co.jp>
---
Many thanks to Hannes for the feedback!
Tested on SH7722 Migo-R with a hacked up capture.c
Changes since V1:
- minor cleanups and formatting changes
- use follow_phys() in videobuf-dma-contig instead of duplicating code
- since videobuf-dma-contig can be a module: EXPORT_SYMBOL(follow_phys)
- move CONFIG_HAVE_IOREMAP_PROT to always build follow_phys()
drivers/media/video/videobuf-dma-contig.c | 82 +++++++++++++++++++++++++++--
mm/memory.c | 3 -
2 files changed, 79 insertions(+), 6 deletions(-)
--- 0005/drivers/media/video/videobuf-dma-contig.c
+++ work/drivers/media/video/videobuf-dma-contig.c 2009-04-28 14:59:23.000000000 +0900
@@ -17,6 +17,7 @@
#include <linux/init.h>
#include <linux/module.h>
#include <linux/mm.h>
+#include <linux/pagemap.h>
#include <linux/dma-mapping.h>
#include <media/videobuf-dma-contig.h>
@@ -25,6 +26,7 @@ struct videobuf_dma_contig_memory {
void *vaddr;
dma_addr_t dma_handle;
unsigned long size;
+ int is_userptr;
};
#define MAGIC_DC_MEM 0x0733ac61
@@ -108,6 +110,70 @@ static struct vm_operations_struct video
.close = videobuf_vm_close,
};
+static void videobuf_dma_contig_user_put(struct videobuf_dma_contig_memory *mem)
+{
+ mem->is_userptr = 0;
+ mem->dma_handle = 0;
+ mem->size = 0;
+}
+
+static int videobuf_dma_contig_user_get(struct videobuf_dma_contig_memory *mem,
+ struct videobuf_buffer *vb)
+{
+ struct mm_struct *mm = current->mm;
+ struct vm_area_struct *vma;
+ unsigned long prev_pfn, this_pfn;
+ unsigned long pages_done, user_address;
+ unsigned long prot;
+ resource_size_t phys;
+ int ret;
+
+ mem->size = PAGE_ALIGN(vb->size);
+ mem->is_userptr = 0;
+ ret = -EINVAL;
+
+ down_read(&mm->mmap_sem);
+
+ vma = find_vma(mm, vb->baddr);
+ if (!vma)
+ goto out_up;
+
+ if ((vb->baddr + mem->size) > vma->vm_end)
+ goto out_up;
+
+ pages_done = 0;
+ prev_pfn = 0; /* kill warning */
+ user_address = vb->baddr;
+
+ while (pages_done < (mem->size >> PAGE_SHIFT)) {
+ ret = follow_phys(vma, user_address, 0, &prot, &phys);
+ if (ret)
+ break;
+
+ this_pfn = phys >> PAGE_SHIFT;
+
+ if (pages_done == 0)
+ mem->dma_handle = phys;
+ else if (this_pfn != (prev_pfn + 1))
+ ret = -EFAULT;
+
+ if (ret)
+ break;
+
+ prev_pfn = this_pfn;
+ user_address += PAGE_SIZE;
+ pages_done++;
+ }
+
+ if (!ret)
+ mem->is_userptr = 1;
+
+ out_up:
+ up_read(¤t->mm->mmap_sem);
+
+ return ret;
+}
+
static void *__videobuf_alloc(size_t size)
{
struct videobuf_dma_contig_memory *mem;
@@ -154,12 +220,11 @@ static int __videobuf_iolock(struct vide
case V4L2_MEMORY_USERPTR:
dev_dbg(q->dev, "%s memory method USERPTR\n", __func__);
- /* The only USERPTR currently supported is the one needed for
- read() method.
- */
+ /* handle pointer from user space */
if (vb->baddr)
- return -EINVAL;
+ return videobuf_dma_contig_user_get(mem, vb);
+ /* allocate memory for the read() method */
mem->size = PAGE_ALIGN(vb->size);
mem->vaddr = dma_alloc_coherent(q->dev, mem->size,
&mem->dma_handle, GFP_KERNEL);
@@ -386,7 +451,7 @@ void videobuf_dma_contig_free(struct vid
So, it should free memory only if the memory were allocated for
read() operation.
*/
- if ((buf->memory != V4L2_MEMORY_USERPTR) || buf->baddr)
+ if (buf->memory != V4L2_MEMORY_USERPTR)
return;
if (!mem)
@@ -394,6 +459,13 @@ void videobuf_dma_contig_free(struct vid
MAGIC_CHECK(mem->magic, MAGIC_DC_MEM);
+ /* handle user space pointer case */
+ if (buf->baddr) {
+ videobuf_dma_contig_user_put(mem);
+ return;
+ }
+
+ /* read() method */
dma_free_coherent(q->dev, mem->size, mem->vaddr, mem->dma_handle);
mem->vaddr = NULL;
}
--- 0001/mm/memory.c
+++ work/mm/memory.c 2009-04-28 14:56:43.000000000 +0900
@@ -3009,7 +3009,6 @@ int in_gate_area_no_task(unsigned long a
#endif /* __HAVE_ARCH_GATE_AREA */
-#ifdef CONFIG_HAVE_IOREMAP_PROT
int follow_phys(struct vm_area_struct *vma,
unsigned long address, unsigned int flags,
unsigned long *prot, resource_size_t *phys)
@@ -3063,7 +3062,9 @@ unlock:
out:
return ret;
}
+EXPORT_SYMBOL(follow_phys);
+#ifdef CONFIG_HAVE_IOREMAP_PROT
int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
void *buf, int len, int write)
{
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH] videobuf-dma-contig: zero copy USERPTR support V2
2009-04-28 9:01 [PATCH] videobuf-dma-contig: zero copy USERPTR support V2 Magnus Damm
@ 2009-05-01 3:26 ` Magnus Damm
2009-05-01 18:14 ` Johannes Weiner
0 siblings, 1 reply; 15+ messages in thread
From: Magnus Damm @ 2009-05-01 3:26 UTC (permalink / raw)
To: linux-media; +Cc: hverkuil, linux-mm, Magnus Damm, lethal, hannes
On Tue, Apr 28, 2009 at 6:01 PM, Magnus Damm <magnus.damm@gmail.com> wrote:
> This is V2 of the V4L2 videobuf-dma-contig USERPTR zero copy patch.
I guess the V4L2 specific bits are pretty simple.
As for the minor mm modifications below,
> --- 0001/mm/memory.c
> +++ work/mm/memory.c 2009-04-28 14:56:43.000000000 +0900
> @@ -3009,7 +3009,6 @@ int in_gate_area_no_task(unsigned long a
>
> #endif /* __HAVE_ARCH_GATE_AREA */
>
> -#ifdef CONFIG_HAVE_IOREMAP_PROT
> int follow_phys(struct vm_area_struct *vma,
> unsigned long address, unsigned int flags,
> unsigned long *prot, resource_size_t *phys)
Is it ok with the memory management guys to always build follow_phys()?
> @@ -3063,7 +3062,9 @@ unlock:
> out:
> return ret;
> }
> +EXPORT_SYMBOL(follow_phys);
>
> +#ifdef CONFIG_HAVE_IOREMAP_PROT
> int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
> void *buf, int len, int write)
> {
How about exporting follow_phys()? This because the user
videobuf-dma-contig.c can be built as a module.
Should I use EXPORT_SYMBOL_GPL() instead of EXPORT_SYMBOL()?
Any comments?
Thanks,
/ magnus
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 15+ messages in thread* Re: [PATCH] videobuf-dma-contig: zero copy USERPTR support V2
2009-05-01 3:26 ` Magnus Damm
@ 2009-05-01 18:14 ` Johannes Weiner
2009-05-04 9:54 ` [patch 1/3] mm: introduce follow_pte() Johannes Weiner
` (2 more replies)
0 siblings, 3 replies; 15+ messages in thread
From: Johannes Weiner @ 2009-05-01 18:14 UTC (permalink / raw)
To: Magnus Damm; +Cc: linux-media, hverkuil, linux-mm, lethal
On Fri, May 01, 2009 at 12:26:38PM +0900, Magnus Damm wrote:
> On Tue, Apr 28, 2009 at 6:01 PM, Magnus Damm <magnus.damm@gmail.com> wrote:
> > This is V2 of the V4L2 videobuf-dma-contig USERPTR zero copy patch.
>
> I guess the V4L2 specific bits are pretty simple.
>
> As for the minor mm modifications below,
>
> > --- 0001/mm/memory.c
> > +++ work/mm/memory.c 2009-04-28 14:56:43.000000000 +0900
> > @@ -3009,7 +3009,6 @@ int in_gate_area_no_task(unsigned long a
> >
> > #endif /* __HAVE_ARCH_GATE_AREA */
> >
> > -#ifdef CONFIG_HAVE_IOREMAP_PROT
> > int follow_phys(struct vm_area_struct *vma,
> > unsigned long address, unsigned int flags,
> > unsigned long *prot, resource_size_t *phys)
>
> Is it ok with the memory management guys to always build follow_phys()?
AFAICS, pte_pgprot is only defined on three architectures that have
the config symbol above set. It shouldn't compile on the others.
I have a patch that factors out follow_pte and builds follow_pfn and
follow_phys on top of that. I can send it monday, no access to it
from here right now.
Then we can keep follow_phys private to this configuration.
Hannes
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 15+ messages in thread* [patch 1/3] mm: introduce follow_pte()
2009-05-01 18:14 ` Johannes Weiner
@ 2009-05-04 9:54 ` Johannes Weiner
2009-05-05 19:24 ` Andrew Morton
2009-05-04 9:54 ` [patch 2/3] mm: use generic follow_pte() in follow_phys() Johannes Weiner
2009-05-04 9:54 ` [patch 3/3] mm: introduce follow_pfn() Johannes Weiner
2 siblings, 1 reply; 15+ messages in thread
From: Johannes Weiner @ 2009-05-04 9:54 UTC (permalink / raw)
To: Andrew Morton
Cc: Magnus Damm, linux-media, Hans Verkuil, Paul Mundt, linux-mm,
linux-kernel
A generic readonly page table lookup helper to map an address space
and an address from it to a pte.
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
mm/memory.c | 37 +++++++++++++++++++++++++++++++++++++
1 files changed, 37 insertions(+), 0 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c
index cf6873e..a621319 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3009,6 +3009,43 @@ int in_gate_area_no_task(unsigned long addr)
#endif /* __HAVE_ARCH_GATE_AREA */
+static int follow_pte(struct mm_struct *mm, unsigned long address,
+ pte_t **ptepp, spinlock_t **ptlp)
+{
+ pgd_t *pgd;
+ pud_t *pud;
+ pmd_t *pmd;
+ pte_t *ptep;
+
+ pgd = pgd_offset(mm, address);
+ if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
+ goto out;
+
+ pud = pud_offset(pgd, address);
+ if (pud_none(*pud) || unlikely(pud_bad(*pud)))
+ goto out;
+
+ pmd = pmd_offset(pud, address);
+ if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
+ goto out;
+
+ /* We cannot handle huge page PFN maps. Luckily they don't exist. */
+ if (pmd_huge(*pmd))
+ goto out;
+
+ ptep = pte_offset_map_lock(mm, pmd, address, ptlp);
+ if (!ptep)
+ goto out;
+ if (!pte_present(*ptep))
+ goto unlock;
+ *ptepp = ptep;
+ return 0;
+unlock:
+ pte_unmap_unlock(ptep, *ptlp);
+out:
+ return -EINVAL;
+}
+
#ifdef CONFIG_HAVE_IOREMAP_PROT
int follow_phys(struct vm_area_struct *vma,
unsigned long address, unsigned int flags,
--
1.6.2.1.135.gde769
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [patch 1/3] mm: introduce follow_pte()
2009-05-04 9:54 ` [patch 1/3] mm: introduce follow_pte() Johannes Weiner
@ 2009-05-05 19:24 ` Andrew Morton
2009-05-05 20:38 ` Johannes Weiner
0 siblings, 1 reply; 15+ messages in thread
From: Andrew Morton @ 2009-05-05 19:24 UTC (permalink / raw)
To: Johannes Weiner
Cc: magnus.damm, linux-media, hverkuil, lethal, linux-mm,
linux-kernel
On Mon, 4 May 2009 11:54:32 +0200
Johannes Weiner <hannes@cmpxchg.org> wrote:
> A generic readonly page table lookup helper to map an address space
> and an address from it to a pte.
umm, OK.
Is there actually some point to these three patches? If so, what is it?
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch 1/3] mm: introduce follow_pte()
2009-05-05 19:24 ` Andrew Morton
@ 2009-05-05 20:38 ` Johannes Weiner
2009-05-05 21:05 ` Andrew Morton
0 siblings, 1 reply; 15+ messages in thread
From: Johannes Weiner @ 2009-05-05 20:38 UTC (permalink / raw)
To: Andrew Morton
Cc: magnus.damm, linux-media, hverkuil, lethal, linux-mm,
linux-kernel
On Tue, May 05, 2009 at 12:24:42PM -0700, Andrew Morton wrote:
> On Mon, 4 May 2009 11:54:32 +0200
> Johannes Weiner <hannes@cmpxchg.org> wrote:
>
> > A generic readonly page table lookup helper to map an address space
> > and an address from it to a pte.
>
> umm, OK.
>
> Is there actually some point to these three patches? If so, what is it?
Magnus needs to check for physical contiguity of a VMAs backing pages
to support zero-copy exportation of video data to userspace.
This series implements follow_pfn() so he can walk the VMA backing
pages and ensure their PFNs are in linear order.
[ This patch can be collapsed with 2/3, I just thought it would be
easier to read the diffs when having them separate. ]
1/3 and 2/3: factor out the page table walk from follow_phys() into
follow_pte().
3/3: implement follow_pfn() on top of follow_pte().
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch 1/3] mm: introduce follow_pte()
2009-05-05 20:38 ` Johannes Weiner
@ 2009-05-05 21:05 ` Andrew Morton
2009-05-05 21:21 ` Johannes Weiner
0 siblings, 1 reply; 15+ messages in thread
From: Andrew Morton @ 2009-05-05 21:05 UTC (permalink / raw)
To: Johannes Weiner
Cc: magnus.damm, linux-media, hverkuil, lethal, linux-mm,
linux-kernel
On Tue, 5 May 2009 22:38:07 +0200
Johannes Weiner <hannes@cmpxchg.org> wrote:
> On Tue, May 05, 2009 at 12:24:42PM -0700, Andrew Morton wrote:
> > On Mon, 4 May 2009 11:54:32 +0200
> > Johannes Weiner <hannes@cmpxchg.org> wrote:
> >
> > > A generic readonly page table lookup helper to map an address space
> > > and an address from it to a pte.
> >
> > umm, OK.
> >
> > Is there actually some point to these three patches? If so, what is it?
>
> Magnus needs to check for physical contiguity of a VMAs backing pages
> to support zero-copy exportation of video data to userspace.
>
> This series implements follow_pfn() so he can walk the VMA backing
> pages and ensure their PFNs are in linear order.
>
> [ This patch can be collapsed with 2/3, I just thought it would be
> easier to read the diffs when having them separate. ]
>
> 1/3 and 2/3: factor out the page table walk from follow_phys() into
> follow_pte().
>
> 3/3: implement follow_pfn() on top of follow_pte().
So we could bundle these patches with Magnus's patchset, or we could
consider these three patches as a cleanup or something.
Given that 3/3 introduces an unused function, I'm inclined to sit tight
and await Magnus's work.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch 1/3] mm: introduce follow_pte()
2009-05-05 21:05 ` Andrew Morton
@ 2009-05-05 21:21 ` Johannes Weiner
2009-05-08 8:51 ` Magnus Damm
0 siblings, 1 reply; 15+ messages in thread
From: Johannes Weiner @ 2009-05-05 21:21 UTC (permalink / raw)
To: Andrew Morton
Cc: magnus.damm, linux-media, hverkuil, lethal, linux-mm,
linux-kernel
On Tue, May 05, 2009 at 02:05:17PM -0700, Andrew Morton wrote:
> On Tue, 5 May 2009 22:38:07 +0200
> Johannes Weiner <hannes@cmpxchg.org> wrote:
>
> > On Tue, May 05, 2009 at 12:24:42PM -0700, Andrew Morton wrote:
> > > On Mon, 4 May 2009 11:54:32 +0200
> > > Johannes Weiner <hannes@cmpxchg.org> wrote:
> > >
> > > > A generic readonly page table lookup helper to map an address space
> > > > and an address from it to a pte.
> > >
> > > umm, OK.
> > >
> > > Is there actually some point to these three patches? If so, what is it?
> >
> > Magnus needs to check for physical contiguity of a VMAs backing pages
> > to support zero-copy exportation of video data to userspace.
> >
> > This series implements follow_pfn() so he can walk the VMA backing
> > pages and ensure their PFNs are in linear order.
> >
> > [ This patch can be collapsed with 2/3, I just thought it would be
> > easier to read the diffs when having them separate. ]
> >
> > 1/3 and 2/3: factor out the page table walk from follow_phys() into
> > follow_pte().
> >
> > 3/3: implement follow_pfn() on top of follow_pte().
>
> So we could bundle these patches with Magnus's patchset, or we could
> consider these three patches as a cleanup or something.
>
> Given that 3/3 introduces an unused function, I'm inclined to sit tight
> and await Magnus's work.
Yeah, I didn't see the video guys responding on Magnus' patch yet, so
let's wait for them.
Magnus, the actual conversion of your code should be trivial, could
you respin it on top of these three patches using follow_pfn() then?
Thanks, Hannes
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 15+ messages in thread
* Re: [patch 1/3] mm: introduce follow_pte()
2009-05-05 21:21 ` Johannes Weiner
@ 2009-05-08 8:51 ` Magnus Damm
0 siblings, 0 replies; 15+ messages in thread
From: Magnus Damm @ 2009-05-08 8:51 UTC (permalink / raw)
To: Johannes Weiner
Cc: Andrew Morton, linux-media, hverkuil, lethal, linux-mm,
linux-kernel
On Wed, May 6, 2009 at 6:21 AM, Johannes Weiner <hannes@cmpxchg.org> wrote:
> On Tue, May 05, 2009 at 02:05:17PM -0700, Andrew Morton wrote:
>> On Tue, 5 May 2009 22:38:07 +0200
>> Johannes Weiner <hannes@cmpxchg.org> wrote:
>> > On Tue, May 05, 2009 at 12:24:42PM -0700, Andrew Morton wrote:
>> > > On Mon, 4 May 2009 11:54:32 +0200
>> > > Johannes Weiner <hannes@cmpxchg.org> wrote:
>> > >
>> > > > A generic readonly page table lookup helper to map an address space
>> > > > and an address from it to a pte.
>> > >
>> > > umm, OK.
>> > >
>> > > Is there actually some point to these three patches? If so, what is it?
>> >
>> > Magnus needs to check for physical contiguity of a VMAs backing pages
>> > to support zero-copy exportation of video data to userspace.
>> >
>> > This series implements follow_pfn() so he can walk the VMA backing
>> > pages and ensure their PFNs are in linear order.
>> >
>> > [ This patch can be collapsed with 2/3, I just thought it would be
>> > easier to read the diffs when having them separate. ]
>> >
>> > 1/3 and 2/3: factor out the page table walk from follow_phys() into
>> > follow_pte().
>> >
>> > 3/3: implement follow_pfn() on top of follow_pte().
>>
>> So we could bundle these patches with Magnus's patchset, or we could
>> consider these three patches as a cleanup or something.
>>
>> Given that 3/3 introduces an unused function, I'm inclined to sit tight
>> and await Magnus's work.
>
> Yeah, I didn't see the video guys responding on Magnus' patch yet, so
> let's wait for them.
>
> Magnus, the actual conversion of your code should be trivial, could
> you respin it on top of these three patches using follow_pfn() then?
So I tested the patches in -mm (1/3, 2/3, 3/3) together with the zero
copy patch and everything seems fine. Feel free to add acks from me,
least for patch 1/3 and 3/3 - i know too little about the generic case
to say anything about 2/3.
Acked-by: Magnus Damm <damm@igel.co.jp>
I'll send V3 of my zero copy patch in a little while. Thanks a lot for the help!
Cheers,
/ magnus
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [patch 2/3] mm: use generic follow_pte() in follow_phys()
2009-05-01 18:14 ` Johannes Weiner
2009-05-04 9:54 ` [patch 1/3] mm: introduce follow_pte() Johannes Weiner
@ 2009-05-04 9:54 ` Johannes Weiner
2009-05-04 10:08 ` Johannes Weiner
2009-05-04 9:54 ` [patch 3/3] mm: introduce follow_pfn() Johannes Weiner
2 siblings, 1 reply; 15+ messages in thread
From: Johannes Weiner @ 2009-05-04 9:54 UTC (permalink / raw)
To: Andrew Morton
Cc: Magnus Damm, linux-media, Hans Verkuil, Paul Mundt, linux-mm,
linux-kernel
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
mm/memory.c | 37 ++++++-------------------------------
1 files changed, 6 insertions(+), 31 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c
index a621319..aee167d 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3051,50 +3051,25 @@ int follow_phys(struct vm_area_struct *vma,
unsigned long address, unsigned int flags,
unsigned long *prot, resource_size_t *phys)
{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
+ int ret = -EINVAL;
pte_t *ptep, pte;
spinlock_t *ptl;
- resource_size_t phys_addr = 0;
- struct mm_struct *mm = vma->vm_mm;
- int ret = -EINVAL;
if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
goto out;
- pgd = pgd_offset(mm, address);
- if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
- goto out;
-
- pud = pud_offset(pgd, address);
- if (pud_none(*pud) || unlikely(pud_bad(*pud)))
- goto out;
-
- pmd = pmd_offset(pud, address);
- if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
- goto out;
-
- /* We cannot handle huge page PFN maps. Luckily they don't exist. */
- if (pmd_huge(*pmd))
+ if (follow_pte(vma->vm_mm, address, &ptep, &ptl))
goto out;
-
- ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
- if (!ptep)
- goto out;
-
pte = *ptep;
- if (!pte_present(pte))
- goto unlock;
+
if ((flags & FOLL_WRITE) && !pte_write(pte))
goto unlock;
- phys_addr = pte_pfn(pte);
- phys_addr <<= PAGE_SHIFT; /* Shift here to avoid overflow on PAE */
*prot = pgprot_val(pte_pgprot(pte));
- *phys = phys_addr;
- ret = 0;
+ /* Shift here to avoid overflow on PAE */
+ *phys = pte_pfn(pte) << PAGE_SHIFT;
+ ret = 0;
unlock:
pte_unmap_unlock(ptep, ptl);
out:
--
1.6.2.1.135.gde769
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [patch 2/3] mm: use generic follow_pte() in follow_phys()
2009-05-04 9:54 ` [patch 2/3] mm: use generic follow_pte() in follow_phys() Johannes Weiner
@ 2009-05-04 10:08 ` Johannes Weiner
0 siblings, 0 replies; 15+ messages in thread
From: Johannes Weiner @ 2009-05-04 10:08 UTC (permalink / raw)
To: Andrew Morton
Cc: Magnus Damm, linux-media, Hans Verkuil, Paul Mundt, linux-mm,
linux-kernel
On Mon, May 04, 2009 at 11:54:33AM +0200, Johannes Weiner wrote:
> Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
> ---
> mm/memory.c | 37 ++++++-------------------------------
> 1 files changed, 6 insertions(+), 31 deletions(-)
>
> diff --git a/mm/memory.c b/mm/memory.c
> index a621319..aee167d 100644
> --- a/mm/memory.c
> +++ b/mm/memory.c
> @@ -3051,50 +3051,25 @@ int follow_phys(struct vm_area_struct *vma,
> unsigned long address, unsigned int flags,
> unsigned long *prot, resource_size_t *phys)
> {
> - pgd_t *pgd;
> - pud_t *pud;
> - pmd_t *pmd;
> + int ret = -EINVAL;
> pte_t *ptep, pte;
> spinlock_t *ptl;
> - resource_size_t phys_addr = 0;
> - struct mm_struct *mm = vma->vm_mm;
> - int ret = -EINVAL;
>
> if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
> goto out;
>
> - pgd = pgd_offset(mm, address);
> - if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
> - goto out;
> -
> - pud = pud_offset(pgd, address);
> - if (pud_none(*pud) || unlikely(pud_bad(*pud)))
> - goto out;
> -
> - pmd = pmd_offset(pud, address);
> - if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
> - goto out;
> -
> - /* We cannot handle huge page PFN maps. Luckily they don't exist. */
> - if (pmd_huge(*pmd))
> + if (follow_pte(vma->vm_mm, address, &ptep, &ptl))
> goto out;
> -
> - ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
> - if (!ptep)
> - goto out;
> -
> pte = *ptep;
> - if (!pte_present(pte))
> - goto unlock;
> +
> if ((flags & FOLL_WRITE) && !pte_write(pte))
> goto unlock;
> - phys_addr = pte_pfn(pte);
> - phys_addr <<= PAGE_SHIFT; /* Shift here to avoid overflow on PAE */
>
> *prot = pgprot_val(pte_pgprot(pte));
> - *phys = phys_addr;
> - ret = 0;
> + /* Shift here to avoid overflow on PAE */
> + *phys = pte_pfn(pte) << PAGE_SHIFT;
Yuk, had my head in the butt here. Changed to
*phys = (resource_size_t)pte_pfn(pte) << PAGE_SHIFT;
---
From: Johannes Weiner <hannes@cmpxchg.org>
Subject: mm: use generic follow_pte() in follow_phys()
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
mm/memory.c | 36 +++++-------------------------------
1 files changed, 5 insertions(+), 31 deletions(-)
diff --git a/mm/memory.c b/mm/memory.c
index a621319..c047950 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3051,50 +3051,24 @@ int follow_phys(struct vm_area_struct *vma,
unsigned long address, unsigned int flags,
unsigned long *prot, resource_size_t *phys)
{
- pgd_t *pgd;
- pud_t *pud;
- pmd_t *pmd;
+ int ret = -EINVAL;
pte_t *ptep, pte;
spinlock_t *ptl;
- resource_size_t phys_addr = 0;
- struct mm_struct *mm = vma->vm_mm;
- int ret = -EINVAL;
if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
goto out;
- pgd = pgd_offset(mm, address);
- if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
- goto out;
-
- pud = pud_offset(pgd, address);
- if (pud_none(*pud) || unlikely(pud_bad(*pud)))
- goto out;
-
- pmd = pmd_offset(pud, address);
- if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
- goto out;
-
- /* We cannot handle huge page PFN maps. Luckily they don't exist. */
- if (pmd_huge(*pmd))
+ if (follow_pte(vma->vm_mm, address, &ptep, &ptl))
goto out;
-
- ptep = pte_offset_map_lock(mm, pmd, address, &ptl);
- if (!ptep)
- goto out;
-
pte = *ptep;
- if (!pte_present(pte))
- goto unlock;
+
if ((flags & FOLL_WRITE) && !pte_write(pte))
goto unlock;
- phys_addr = pte_pfn(pte);
- phys_addr <<= PAGE_SHIFT; /* Shift here to avoid overflow on PAE */
*prot = pgprot_val(pte_pgprot(pte));
- *phys = phys_addr;
- ret = 0;
+ *phys = (resource_size_t)pte_pfn(pte) << PAGE_SHIFT;
+ ret = 0;
unlock:
pte_unmap_unlock(ptep, ptl);
out:
--
1.6.2.1.135.gde769
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related [flat|nested] 15+ messages in thread
* [patch 3/3] mm: introduce follow_pfn()
2009-05-01 18:14 ` Johannes Weiner
2009-05-04 9:54 ` [patch 1/3] mm: introduce follow_pte() Johannes Weiner
2009-05-04 9:54 ` [patch 2/3] mm: use generic follow_pte() in follow_phys() Johannes Weiner
@ 2009-05-04 9:54 ` Johannes Weiner
2009-05-04 11:08 ` Christoph Hellwig
2 siblings, 1 reply; 15+ messages in thread
From: Johannes Weiner @ 2009-05-04 9:54 UTC (permalink / raw)
To: Andrew Morton
Cc: Magnus Damm, linux-media, Hans Verkuil, Paul Mundt, linux-mm,
linux-kernel
Analoguous to follow_phys(), add a helper that looks up the PFN
instead. It also only allows IO mappings or PFN mappings.
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
include/linux/mm.h | 2 ++
mm/memory.c | 19 +++++++++++++++++++
2 files changed, 21 insertions(+), 0 deletions(-)
diff --git a/include/linux/mm.h b/include/linux/mm.h
index bff1f0d..1cca8b6 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -794,6 +794,8 @@ int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
struct vm_area_struct *vma);
void unmap_mapping_range(struct address_space *mapping,
loff_t const holebegin, loff_t const holelen, int even_cows);
+int follow_pfn(struct vm_area_struct *vma, unsigned long address,
+ unsigned long *pfn);
int follow_phys(struct vm_area_struct *vma, unsigned long address,
unsigned int flags, unsigned long *prot, resource_size_t *phys);
int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
diff --git a/mm/memory.c b/mm/memory.c
index aee167d..05fc8e5 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3046,6 +3046,25 @@ out:
return -EINVAL;
}
+int follow_pfn(struct vm_area_struct *vma, unsigned long address,
+ unsigned long *pfn)
+{
+ int ret = -EINVAL;
+ spinlock_t *ptl;
+ pte_t *ptep;
+
+ if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
+ return ret;
+
+ ret = follow_pte(vma->vm_mm, address, &ptep, &ptl);
+ if (ret)
+ return ret;
+ *pfn = pte_pfn(*ptep);
+ pte_unmap_unlock(ptep, ptl);
+ return 0;
+}
+EXPORT_SYMBOL(follow_pfn);
+
#ifdef CONFIG_HAVE_IOREMAP_PROT
int follow_phys(struct vm_area_struct *vma,
unsigned long address, unsigned int flags,
--
1.6.2.1.135.gde769
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [patch 3/3] mm: introduce follow_pfn()
2009-05-04 9:54 ` [patch 3/3] mm: introduce follow_pfn() Johannes Weiner
@ 2009-05-04 11:08 ` Christoph Hellwig
2009-05-04 13:13 ` [patch 3/3 v2] " Johannes Weiner
0 siblings, 1 reply; 15+ messages in thread
From: Christoph Hellwig @ 2009-05-04 11:08 UTC (permalink / raw)
To: Johannes Weiner
Cc: Andrew Morton, Magnus Damm, linux-media, Hans Verkuil, Paul Mundt,
linux-mm, linux-kernel
On Mon, May 04, 2009 at 11:54:34AM +0200, Johannes Weiner wrote:
> Analoguous to follow_phys(), add a helper that looks up the PFN
> instead. It also only allows IO mappings or PFN mappings.
A kerneldoc describing what it does and the limitations would be
extremly helpful.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 15+ messages in thread
* [patch 3/3 v2] mm: introduce follow_pfn()
2009-05-04 11:08 ` Christoph Hellwig
@ 2009-05-04 13:13 ` Johannes Weiner
2009-05-04 14:31 ` Christoph Hellwig
0 siblings, 1 reply; 15+ messages in thread
From: Johannes Weiner @ 2009-05-04 13:13 UTC (permalink / raw)
To: Christoph Hellwig
Cc: Andrew Morton, Magnus Damm, linux-media, Hans Verkuil, Paul Mundt,
linux-mm, linux-kernel
Analoguous to follow_phys(), add a helper that looks up the PFN at a
user virtual address in an IO mapping or a raw PFN mapping.
Signed-off-by: Johannes Weiner <hannes@cmpxchg.org>
---
include/linux/mm.h | 2 ++
mm/memory.c | 29 +++++++++++++++++++++++++++++
2 files changed, 31 insertions(+), 0 deletions(-)
On Mon, May 04, 2009 at 07:08:41AM -0400, Christoph Hellwig wrote:
> On Mon, May 04, 2009 at 11:54:34AM +0200, Johannes Weiner wrote:
> > Analoguous to follow_phys(), add a helper that looks up the PFN
> > instead. It also only allows IO mappings or PFN mappings.
>
> A kerneldoc describing what it does and the limitations would be
> extremly helpful.
Agreed. How is this?
diff --git a/include/linux/mm.h b/include/linux/mm.h
index bff1f0d..1cca8b6 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -794,6 +794,8 @@ int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
struct vm_area_struct *vma);
void unmap_mapping_range(struct address_space *mapping,
loff_t const holebegin, loff_t const holelen, int even_cows);
+int follow_pfn(struct vm_area_struct *vma, unsigned long address,
+ unsigned long *pfn);
int follow_phys(struct vm_area_struct *vma, unsigned long address,
unsigned int flags, unsigned long *prot, resource_size_t *phys);
int generic_access_phys(struct vm_area_struct *vma, unsigned long addr,
diff --git a/mm/memory.c b/mm/memory.c
index c047950..f86aee1 100644
--- a/mm/memory.c
+++ b/mm/memory.c
@@ -3046,6 +3046,35 @@ out:
return -EINVAL;
}
+/**
+ * follow_pfn - look up PFN at a user virtual address
+ * @vma: memory mapping
+ * @address: user virtual address
+ * @pfn: location to store found PFN
+ *
+ * Only IO mappings and raw PFN mappings are allowed.
+ *
+ * Returns zero and the pfn at @pfn on success, -ve otherwise.
+ */
+int follow_pfn(struct vm_area_struct *vma, unsigned long address,
+ unsigned long *pfn)
+{
+ int ret = -EINVAL;
+ spinlock_t *ptl;
+ pte_t *ptep;
+
+ if (!(vma->vm_flags & (VM_IO | VM_PFNMAP)))
+ return ret;
+
+ ret = follow_pte(vma->vm_mm, address, &ptep, &ptl);
+ if (ret)
+ return ret;
+ *pfn = pte_pfn(*ptep);
+ pte_unmap_unlock(ptep, ptl);
+ return 0;
+}
+EXPORT_SYMBOL(follow_pfn);
+
#ifdef CONFIG_HAVE_IOREMAP_PROT
int follow_phys(struct vm_area_struct *vma,
unsigned long address, unsigned int flags,
--
1.6.2.1.135.gde769
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply related [flat|nested] 15+ messages in thread* Re: [patch 3/3 v2] mm: introduce follow_pfn()
2009-05-04 13:13 ` [patch 3/3 v2] " Johannes Weiner
@ 2009-05-04 14:31 ` Christoph Hellwig
0 siblings, 0 replies; 15+ messages in thread
From: Christoph Hellwig @ 2009-05-04 14:31 UTC (permalink / raw)
To: Johannes Weiner
Cc: Christoph Hellwig, Andrew Morton, Magnus Damm, linux-media,
Hans Verkuil, Paul Mundt, linux-mm, linux-kernel
Looks good to me.
--
To unsubscribe, send a message with 'unsubscribe linux-mm' in
the body to majordomo@kvack.org. For more info on Linux MM,
see: http://www.linux-mm.org/ .
Don't email: <a href=mailto:"dont@kvack.org"> email@kvack.org </a>
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2009-05-08 8:50 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2009-04-28 9:01 [PATCH] videobuf-dma-contig: zero copy USERPTR support V2 Magnus Damm
2009-05-01 3:26 ` Magnus Damm
2009-05-01 18:14 ` Johannes Weiner
2009-05-04 9:54 ` [patch 1/3] mm: introduce follow_pte() Johannes Weiner
2009-05-05 19:24 ` Andrew Morton
2009-05-05 20:38 ` Johannes Weiner
2009-05-05 21:05 ` Andrew Morton
2009-05-05 21:21 ` Johannes Weiner
2009-05-08 8:51 ` Magnus Damm
2009-05-04 9:54 ` [patch 2/3] mm: use generic follow_pte() in follow_phys() Johannes Weiner
2009-05-04 10:08 ` Johannes Weiner
2009-05-04 9:54 ` [patch 3/3] mm: introduce follow_pfn() Johannes Weiner
2009-05-04 11:08 ` Christoph Hellwig
2009-05-04 13:13 ` [patch 3/3 v2] " Johannes Weiner
2009-05-04 14:31 ` Christoph Hellwig
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).