Re: [PATCHv7 3/5] common: dma-mapping: Introduce common remapping functions

2014-08-27 Thread Mark Salter
On Tue, 2014-08-26 at 09:58 -0700, Laura Abbott wrote:
> On 8/26/2014 3:05 AM, James Hogan wrote:
> > On 12 August 2014 00:40, Laura Abbott  wrote:
> >>
> >> For architectures without coherent DMA, memory for DMA may
> >> need to be remapped with coherent attributes. Factor out
> >> the the remapping code from arm and put it in a
> >> common location to reduce code duplication.
> >>
> >> As part of this, the arm APIs are now migrated away from
> >> ioremap_page_range to the common APIs which use map_vm_area for remapping.
> >> This should be an equivalent change and using map_vm_area is more
> >> correct as ioremap_page_range is intended to bring in io addresses
> >> into the cpu space and not regular kernel managed memory.
> >>
> >> Reviewed-by: Catalin Marinas 
> >> Signed-off-by: Laura Abbott 
> > 
> > This commit in linux-next () breaks the build for metag:
> > 
> > drivers/base/dma-mapping.c: In function ‘dma_common_contiguous_remap’:
> > drivers/base/dma-mapping.c:294: error: implicit declaration of
> > function ‘dma_common_pages_remap’
> > drivers/base/dma-mapping.c:294: warning: assignment makes pointer from
> > integer without a cast
> > drivers/base/dma-mapping.c: At top level:
> > drivers/base/dma-mapping.c:308: error: conflicting types for
> > ‘dma_common_pages_remap’
> > drivers/base/dma-mapping.c:294: error: previous implicit declaration
> > of ‘dma_common_pages_remap’ was here
> > 
> > Looks like metag isn't alone either:
> > 
> > $ git grep -L dma-mapping-common arch/*/include/asm/dma-mapping.h
> > arch/arc/include/asm/dma-mapping.h
> > arch/avr32/include/asm/dma-mapping.h
> > arch/blackfin/include/asm/dma-mapping.h
> > arch/c6x/include/asm/dma-mapping.h
> > arch/cris/include/asm/dma-mapping.h
> > arch/frv/include/asm/dma-mapping.h
> > arch/m68k/include/asm/dma-mapping.h
> > arch/metag/include/asm/dma-mapping.h
> > arch/mn10300/include/asm/dma-mapping.h
> > arch/parisc/include/asm/dma-mapping.h
> > arch/xtensa/include/asm/dma-mapping.h
> > 
> > I've checked a couple of these arches (blackfin, xtensa) which don't
> > include dma-mapping-common.h and their builds seem to be broken too.
> > 
> > Cheers
> > James
> > 
> 
> Thanks for the report. Would you mind giving the following patch
> a test (this is theoretical only but I think it should work)

There's a further problem with c6x (no  MMU):

drivers/built-in.o: In function `dma_common_pages_remap':
(.text+0x220c4): undefined reference to `get_vm_area_caller'
drivers/built-in.o: In function `dma_common_pages_remap':
(.text+0x22108): undefined reference to `map_vm_area'
drivers/built-in.o: In function `dma_common_free_remap':
(.text+0x22278): undefined reference to `find_vm_area'



--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/


Re: [PATCHv7 3/5] common: dma-mapping: Introduce common remapping functions

2014-08-27 Thread James Hogan
On 26/08/14 17:58, Laura Abbott wrote:
> On 8/26/2014 3:05 AM, James Hogan wrote:
>> On 12 August 2014 00:40, Laura Abbott  wrote:
>>>
>>> For architectures without coherent DMA, memory for DMA may
>>> need to be remapped with coherent attributes. Factor out
>>> the the remapping code from arm and put it in a
>>> common location to reduce code duplication.
>>>
>>> As part of this, the arm APIs are now migrated away from
>>> ioremap_page_range to the common APIs which use map_vm_area for remapping.
>>> This should be an equivalent change and using map_vm_area is more
>>> correct as ioremap_page_range is intended to bring in io addresses
>>> into the cpu space and not regular kernel managed memory.
>>>
>>> Reviewed-by: Catalin Marinas 
>>> Signed-off-by: Laura Abbott 
>>
>> This commit in linux-next () breaks the build for metag:
>>
>> drivers/base/dma-mapping.c: In function ‘dma_common_contiguous_remap’:
>> drivers/base/dma-mapping.c:294: error: implicit declaration of
>> function ‘dma_common_pages_remap’
>> drivers/base/dma-mapping.c:294: warning: assignment makes pointer from
>> integer without a cast
>> drivers/base/dma-mapping.c: At top level:
>> drivers/base/dma-mapping.c:308: error: conflicting types for
>> ‘dma_common_pages_remap’
>> drivers/base/dma-mapping.c:294: error: previous implicit declaration
>> of ‘dma_common_pages_remap’ was here
>>
>> Looks like metag isn't alone either:
>>
>> $ git grep -L dma-mapping-common arch/*/include/asm/dma-mapping.h
>> arch/arc/include/asm/dma-mapping.h
>> arch/avr32/include/asm/dma-mapping.h
>> arch/blackfin/include/asm/dma-mapping.h
>> arch/c6x/include/asm/dma-mapping.h
>> arch/cris/include/asm/dma-mapping.h
>> arch/frv/include/asm/dma-mapping.h
>> arch/m68k/include/asm/dma-mapping.h
>> arch/metag/include/asm/dma-mapping.h
>> arch/mn10300/include/asm/dma-mapping.h
>> arch/parisc/include/asm/dma-mapping.h
>> arch/xtensa/include/asm/dma-mapping.h
>>
>> I've checked a couple of these arches (blackfin, xtensa) which don't
>> include dma-mapping-common.h and their builds seem to be broken too.
>>
>> Cheers
>> James
>>
> 
> Thanks for the report. Would you mind giving the following patch
> a test (this is theoretical only but I think it should work)

It certainly fixes the build for metag.

Thanks
James

> 
> -8<--
> 
> From 81c9a5504cbc1d72ff1df084d48502b248cd79d0 Mon Sep 17 00:00:00 2001
> From: Laura Abbott 
> Date: Tue, 26 Aug 2014 09:50:49 -0700
> Subject: [PATCH] common: dma-mapping: Swap function order
> 
> Fix the order of dma_common_contiguous_remap and
> dma_common_pages_remap to avoid function declaration errors:
> 
> drivers/base/dma-mapping.c: In function 'dma_common_contiguous_remap':
> drivers/base/dma-mapping.c:294: error: implicit declaration of
> function 'dma_common_pages_remap'
> drivers/base/dma-mapping.c:294: warning: assignment makes pointer from
> integer without a cast
> drivers/base/dma-mapping.c: At top level:
> drivers/base/dma-mapping.c:308: error: conflicting types for
> 'dma_common_pages_remap'
> drivers/base/dma-mapping.c:294: error: previous implicit declaration
> of 'dma_common_pages_remap' was here
> 
> Change-Id: I65db739114e8f5816a24a279a2ff1a6dc92e2b83
> Reported-by: James Hogan 
> Reported-by: kbuild test robot 
> Signed-off-by: Laura Abbott 
> ---
>  drivers/base/dma-mapping.c | 44 ++--
>  1 file changed, 22 insertions(+), 22 deletions(-)
> 
> diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
> index 1bc46df..056fd46 100644
> --- a/drivers/base/dma-mapping.c
> +++ b/drivers/base/dma-mapping.c
> @@ -271,6 +271,28 @@ int dma_common_mmap(struct device *dev, struct 
> vm_area_struct *vma,
>  EXPORT_SYMBOL(dma_common_mmap);
>  
>  /*
> + * remaps an array of PAGE_SIZE pages into another vm_area
> + * Cannot be used in non-sleeping contexts
> + */
> +void *dma_common_pages_remap(struct page **pages, size_t size,
> + unsigned long vm_flags, pgprot_t prot,
> + const void *caller)
> +{
> + struct vm_struct *area;
> +
> + area = get_vm_area_caller(size, vm_flags, caller);
> + if (!area)
> + return NULL;
> +
> + if (map_vm_area(area, prot, pages)) {
> + vunmap(area->addr);
> + return NULL;
> + }
> +
> + return area->addr;
> +}
> +
> +/*
>   * remaps an allocated contiguous region into another vm_area.
>   * Cannot be used in non-sleeping contexts
>   */
> @@ -299,28 +321,6 @@ void *dma_common_contiguous_remap(struct page *page, 
> size_t size,
>  }
>  
>  /*
> - * remaps an array of PAGE_SIZE pages into another vm_area
> - * Cannot be used in non-sleeping contexts
> - */
> -void *dma_common_pages_remap(struct page **pages, size_t size,
> - unsigned long vm_flags, pgprot_t prot,
> - const void *caller)
> -{
> - struct vm_struct *area;
> -
> - area = get_vm_area_caller(size, vm_flags, caller);
> - if (!area)
> - r

Re: [PATCHv7 3/5] common: dma-mapping: Introduce common remapping functions

2014-08-26 Thread Laura Abbott
On 8/26/2014 3:05 AM, James Hogan wrote:
> On 12 August 2014 00:40, Laura Abbott  wrote:
>>
>> For architectures without coherent DMA, memory for DMA may
>> need to be remapped with coherent attributes. Factor out
>> the the remapping code from arm and put it in a
>> common location to reduce code duplication.
>>
>> As part of this, the arm APIs are now migrated away from
>> ioremap_page_range to the common APIs which use map_vm_area for remapping.
>> This should be an equivalent change and using map_vm_area is more
>> correct as ioremap_page_range is intended to bring in io addresses
>> into the cpu space and not regular kernel managed memory.
>>
>> Reviewed-by: Catalin Marinas 
>> Signed-off-by: Laura Abbott 
> 
> This commit in linux-next () breaks the build for metag:
> 
> drivers/base/dma-mapping.c: In function ‘dma_common_contiguous_remap’:
> drivers/base/dma-mapping.c:294: error: implicit declaration of
> function ‘dma_common_pages_remap’
> drivers/base/dma-mapping.c:294: warning: assignment makes pointer from
> integer without a cast
> drivers/base/dma-mapping.c: At top level:
> drivers/base/dma-mapping.c:308: error: conflicting types for
> ‘dma_common_pages_remap’
> drivers/base/dma-mapping.c:294: error: previous implicit declaration
> of ‘dma_common_pages_remap’ was here
> 
> Looks like metag isn't alone either:
> 
> $ git grep -L dma-mapping-common arch/*/include/asm/dma-mapping.h
> arch/arc/include/asm/dma-mapping.h
> arch/avr32/include/asm/dma-mapping.h
> arch/blackfin/include/asm/dma-mapping.h
> arch/c6x/include/asm/dma-mapping.h
> arch/cris/include/asm/dma-mapping.h
> arch/frv/include/asm/dma-mapping.h
> arch/m68k/include/asm/dma-mapping.h
> arch/metag/include/asm/dma-mapping.h
> arch/mn10300/include/asm/dma-mapping.h
> arch/parisc/include/asm/dma-mapping.h
> arch/xtensa/include/asm/dma-mapping.h
> 
> I've checked a couple of these arches (blackfin, xtensa) which don't
> include dma-mapping-common.h and their builds seem to be broken too.
> 
> Cheers
> James
> 

Thanks for the report. Would you mind giving the following patch
a test (this is theoretical only but I think it should work)

-8<--

>From 81c9a5504cbc1d72ff1df084d48502b248cd79d0 Mon Sep 17 00:00:00 2001
From: Laura Abbott 
Date: Tue, 26 Aug 2014 09:50:49 -0700
Subject: [PATCH] common: dma-mapping: Swap function order

Fix the order of dma_common_contiguous_remap and
dma_common_pages_remap to avoid function declaration errors:

drivers/base/dma-mapping.c: In function 'dma_common_contiguous_remap':
drivers/base/dma-mapping.c:294: error: implicit declaration of
function 'dma_common_pages_remap'
drivers/base/dma-mapping.c:294: warning: assignment makes pointer from
integer without a cast
drivers/base/dma-mapping.c: At top level:
drivers/base/dma-mapping.c:308: error: conflicting types for
'dma_common_pages_remap'
drivers/base/dma-mapping.c:294: error: previous implicit declaration
of 'dma_common_pages_remap' was here

Change-Id: I65db739114e8f5816a24a279a2ff1a6dc92e2b83
Reported-by: James Hogan 
Reported-by: kbuild test robot 
Signed-off-by: Laura Abbott 
---
 drivers/base/dma-mapping.c | 44 ++--
 1 file changed, 22 insertions(+), 22 deletions(-)

diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index 1bc46df..056fd46 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -271,6 +271,28 @@ int dma_common_mmap(struct device *dev, struct 
vm_area_struct *vma,
 EXPORT_SYMBOL(dma_common_mmap);
 
 /*
+ * remaps an array of PAGE_SIZE pages into another vm_area
+ * Cannot be used in non-sleeping contexts
+ */
+void *dma_common_pages_remap(struct page **pages, size_t size,
+   unsigned long vm_flags, pgprot_t prot,
+   const void *caller)
+{
+   struct vm_struct *area;
+
+   area = get_vm_area_caller(size, vm_flags, caller);
+   if (!area)
+   return NULL;
+
+   if (map_vm_area(area, prot, pages)) {
+   vunmap(area->addr);
+   return NULL;
+   }
+
+   return area->addr;
+}
+
+/*
  * remaps an allocated contiguous region into another vm_area.
  * Cannot be used in non-sleeping contexts
  */
@@ -299,28 +321,6 @@ void *dma_common_contiguous_remap(struct page *page, 
size_t size,
 }
 
 /*
- * remaps an array of PAGE_SIZE pages into another vm_area
- * Cannot be used in non-sleeping contexts
- */
-void *dma_common_pages_remap(struct page **pages, size_t size,
-   unsigned long vm_flags, pgprot_t prot,
-   const void *caller)
-{
-   struct vm_struct *area;
-
-   area = get_vm_area_caller(size, vm_flags, caller);
-   if (!area)
-   return NULL;
-
-   if (map_vm_area(area, prot, pages)) {
-   vunmap(area->addr);
-   return NULL;
-   }
-
-   return area->addr;
-}
-
-/*
  * unmaps a range previously mapped by dma_common_*_remap
  */
 void dma_common_free_remap(void *cp

Re: [PATCHv7 3/5] common: dma-mapping: Introduce common remapping functions

2014-08-26 Thread James Hogan
On 12 August 2014 00:40, Laura Abbott  wrote:
>
> For architectures without coherent DMA, memory for DMA may
> need to be remapped with coherent attributes. Factor out
> the the remapping code from arm and put it in a
> common location to reduce code duplication.
>
> As part of this, the arm APIs are now migrated away from
> ioremap_page_range to the common APIs which use map_vm_area for remapping.
> This should be an equivalent change and using map_vm_area is more
> correct as ioremap_page_range is intended to bring in io addresses
> into the cpu space and not regular kernel managed memory.
>
> Reviewed-by: Catalin Marinas 
> Signed-off-by: Laura Abbott 

This commit in linux-next () breaks the build for metag:

drivers/base/dma-mapping.c: In function ‘dma_common_contiguous_remap’:
drivers/base/dma-mapping.c:294: error: implicit declaration of
function ‘dma_common_pages_remap’
drivers/base/dma-mapping.c:294: warning: assignment makes pointer from
integer without a cast
drivers/base/dma-mapping.c: At top level:
drivers/base/dma-mapping.c:308: error: conflicting types for
‘dma_common_pages_remap’
drivers/base/dma-mapping.c:294: error: previous implicit declaration
of ‘dma_common_pages_remap’ was here

Looks like metag isn't alone either:

$ git grep -L dma-mapping-common arch/*/include/asm/dma-mapping.h
arch/arc/include/asm/dma-mapping.h
arch/avr32/include/asm/dma-mapping.h
arch/blackfin/include/asm/dma-mapping.h
arch/c6x/include/asm/dma-mapping.h
arch/cris/include/asm/dma-mapping.h
arch/frv/include/asm/dma-mapping.h
arch/m68k/include/asm/dma-mapping.h
arch/metag/include/asm/dma-mapping.h
arch/mn10300/include/asm/dma-mapping.h
arch/parisc/include/asm/dma-mapping.h
arch/xtensa/include/asm/dma-mapping.h

I've checked a couple of these arches (blackfin, xtensa) which don't
include dma-mapping-common.h and their builds seem to be broken too.

Cheers
James

> ---
>  arch/arm/mm/dma-mapping.c| 57 +-
>  drivers/base/dma-mapping.c   | 68 
> 
>  include/asm-generic/dma-mapping-common.h |  9 +
>  3 files changed, 86 insertions(+), 48 deletions(-)
>
> diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
> index 4c88935..f5190ac 100644
> --- a/arch/arm/mm/dma-mapping.c
> +++ b/arch/arm/mm/dma-mapping.c
> @@ -297,37 +297,19 @@ static void *
>  __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot,
> const void *caller)
>  {
> -   struct vm_struct *area;
> -   unsigned long addr;
> -
> /*
>  * DMA allocation can be mapped to user space, so lets
>  * set VM_USERMAP flags too.
>  */
> -   area = get_vm_area_caller(size, VM_ARM_DMA_CONSISTENT | VM_USERMAP,
> - caller);
> -   if (!area)
> -   return NULL;
> -   addr = (unsigned long)area->addr;
> -   area->phys_addr = __pfn_to_phys(page_to_pfn(page));
> -
> -   if (ioremap_page_range(addr, addr + size, area->phys_addr, prot)) {
> -   vunmap((void *)addr);
> -   return NULL;
> -   }
> -   return (void *)addr;
> +   return dma_common_contiguous_remap(page, size,
> +   VM_ARM_DMA_CONSISTENT | VM_USERMAP,
> +   prot, caller);
>  }
>
>  static void __dma_free_remap(void *cpu_addr, size_t size)
>  {
> -   unsigned int flags = VM_ARM_DMA_CONSISTENT | VM_USERMAP;
> -   struct vm_struct *area = find_vm_area(cpu_addr);
> -   if (!area || (area->flags & flags) != flags) {
> -   WARN(1, "trying to free invalid coherent area: %p\n", 
> cpu_addr);
> -   return;
> -   }
> -   unmap_kernel_range((unsigned long)cpu_addr, size);
> -   vunmap(cpu_addr);
> +   dma_common_free_remap(cpu_addr, size,
> +   VM_ARM_DMA_CONSISTENT | VM_USERMAP);
>  }
>
>  #define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K
> @@ -1261,29 +1243,8 @@ static void *
>  __iommu_alloc_remap(struct page **pages, size_t size, gfp_t gfp, pgprot_t 
> prot,
> const void *caller)
>  {
> -   unsigned int i, nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
> -   struct vm_struct *area;
> -   unsigned long p;
> -
> -   area = get_vm_area_caller(size, VM_ARM_DMA_CONSISTENT | VM_USERMAP,
> - caller);
> -   if (!area)
> -   return NULL;
> -
> -   area->pages = pages;
> -   area->nr_pages = nr_pages;
> -   p = (unsigned long)area->addr;
> -
> -   for (i = 0; i < nr_pages; i++) {
> -   phys_addr_t phys = __pfn_to_phys(page_to_pfn(pages[i]));
> -   if (ioremap_page_range(p, p + PAGE_SIZE, phys, prot))
> -   goto err;
> -   p += PAGE_SIZE;
> -   }
> -   return area->addr;
> -err:
> -   unmap_kernel_range((unsigned long)area->addr, size);
> -   vunmap(area->addr);
> +   return dma_common_pages_remap(pag

[PATCHv7 3/5] common: dma-mapping: Introduce common remapping functions

2014-08-11 Thread Laura Abbott

For architectures without coherent DMA, memory for DMA may
need to be remapped with coherent attributes. Factor out
the the remapping code from arm and put it in a
common location to reduce code duplication.

As part of this, the arm APIs are now migrated away from
ioremap_page_range to the common APIs which use map_vm_area for remapping.
This should be an equivalent change and using map_vm_area is more
correct as ioremap_page_range is intended to bring in io addresses
into the cpu space and not regular kernel managed memory.

Reviewed-by: Catalin Marinas 
Signed-off-by: Laura Abbott 
---
 arch/arm/mm/dma-mapping.c| 57 +-
 drivers/base/dma-mapping.c   | 68 
 include/asm-generic/dma-mapping-common.h |  9 +
 3 files changed, 86 insertions(+), 48 deletions(-)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 4c88935..f5190ac 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -297,37 +297,19 @@ static void *
 __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot,
const void *caller)
 {
-   struct vm_struct *area;
-   unsigned long addr;
-
/*
 * DMA allocation can be mapped to user space, so lets
 * set VM_USERMAP flags too.
 */
-   area = get_vm_area_caller(size, VM_ARM_DMA_CONSISTENT | VM_USERMAP,
- caller);
-   if (!area)
-   return NULL;
-   addr = (unsigned long)area->addr;
-   area->phys_addr = __pfn_to_phys(page_to_pfn(page));
-
-   if (ioremap_page_range(addr, addr + size, area->phys_addr, prot)) {
-   vunmap((void *)addr);
-   return NULL;
-   }
-   return (void *)addr;
+   return dma_common_contiguous_remap(page, size,
+   VM_ARM_DMA_CONSISTENT | VM_USERMAP,
+   prot, caller);
 }
 
 static void __dma_free_remap(void *cpu_addr, size_t size)
 {
-   unsigned int flags = VM_ARM_DMA_CONSISTENT | VM_USERMAP;
-   struct vm_struct *area = find_vm_area(cpu_addr);
-   if (!area || (area->flags & flags) != flags) {
-   WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr);
-   return;
-   }
-   unmap_kernel_range((unsigned long)cpu_addr, size);
-   vunmap(cpu_addr);
+   dma_common_free_remap(cpu_addr, size,
+   VM_ARM_DMA_CONSISTENT | VM_USERMAP);
 }
 
 #define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K
@@ -1261,29 +1243,8 @@ static void *
 __iommu_alloc_remap(struct page **pages, size_t size, gfp_t gfp, pgprot_t prot,
const void *caller)
 {
-   unsigned int i, nr_pages = PAGE_ALIGN(size) >> PAGE_SHIFT;
-   struct vm_struct *area;
-   unsigned long p;
-
-   area = get_vm_area_caller(size, VM_ARM_DMA_CONSISTENT | VM_USERMAP,
- caller);
-   if (!area)
-   return NULL;
-
-   area->pages = pages;
-   area->nr_pages = nr_pages;
-   p = (unsigned long)area->addr;
-
-   for (i = 0; i < nr_pages; i++) {
-   phys_addr_t phys = __pfn_to_phys(page_to_pfn(pages[i]));
-   if (ioremap_page_range(p, p + PAGE_SIZE, phys, prot))
-   goto err;
-   p += PAGE_SIZE;
-   }
-   return area->addr;
-err:
-   unmap_kernel_range((unsigned long)area->addr, size);
-   vunmap(area->addr);
+   return dma_common_pages_remap(pages, size,
+   VM_ARM_DMA_CONSISTENT | VM_USERMAP, prot, caller);
return NULL;
 }
 
@@ -1491,8 +1452,8 @@ void arm_iommu_free_attrs(struct device *dev, size_t 
size, void *cpu_addr,
}
 
if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) {
-   unmap_kernel_range((unsigned long)cpu_addr, size);
-   vunmap(cpu_addr);
+   dma_common_free_remap(cpu_addr, size,
+   VM_ARM_DMA_CONSISTENT | VM_USERMAP);
}
 
__iommu_remove_mapping(dev, handle, size);
diff --git a/drivers/base/dma-mapping.c b/drivers/base/dma-mapping.c
index 6cd08e1..1bc46df 100644
--- a/drivers/base/dma-mapping.c
+++ b/drivers/base/dma-mapping.c
@@ -10,6 +10,8 @@
 #include 
 #include 
 #include 
+#include 
+#include 
 #include 
 
 /*
@@ -267,3 +269,69 @@ int dma_common_mmap(struct device *dev, struct 
vm_area_struct *vma,
return ret;
 }
 EXPORT_SYMBOL(dma_common_mmap);
+
+/*
+ * remaps an allocated contiguous region into another vm_area.
+ * Cannot be used in non-sleeping contexts
+ */
+
+void *dma_common_contiguous_remap(struct page *page, size_t size,
+   unsigned long vm_flags,
+   pgprot_t prot, const void *caller)
+{
+   int i;
+   struct page **pages;
+   void *ptr;
+   unsigned long pfn;
+
+   pages = kmalloc(sizeof(struct page *) << get_order(size), GFP_KERNEL);
+   if (!pages)
+