DMA Atomic pool for arm64
Subsystems (7)
v7 cover DMA Atomic pool for arm64
Hi,
This is v7 of the series to add an atomic pool for arm64 and refactor some of the dma atomic code. You know the drill.
Thanks,
Laura
v7: Added correct power aligned algorithm patch. Addressed comments from Andrew.
Laura Abbott (5):
lib/genalloc.c: Add power aligned algorithm lib/genalloc.c: Add genpool range check function
common: dma-mapping: Introduce common remapping functions
arm: use genalloc for the atomic pool
arm64: Add atomic pool for non-coherent and CMA allocations.
arch/arm/Kconfig | 1 + arch/arm/mm/dma-mapping.c | 210 +++++++++---------------------- arch/arm64/Kconfig | 1 + arch/arm64/mm/dma-mapping.c | 164 +++++++++++++++++++++--- drivers/base/dma-mapping.c | 68 ++++++++++ include/asm-generic/dma-mapping-common.h | 9 ++ include/linux/genalloc.h | 7 ++ lib/genalloc.c | 49 ++++++++ 8 files changed, 338 insertions(+), 171 deletions(-)
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v7 1/5 lib/genalloc.c: Add power aligned algorithm
One of the more common algorithms used for allocation is to align the start address of the allocation to the order of size requested. Add this as an algorithm option for genalloc.
--- include/linux/genalloc.h | 4 ++++ lib/genalloc.c | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+)
include/linux/genalloc.h +4 -0
@@ -110,6 +110,10 @@ extern void gen_pool_set_algo(struct gen_pool *pool, genpool_algo_t algo,extern unsigned long gen_pool_first_fit (unsigned long *map,unsigned long size,unsigned long start,unsigned int nr,void *data); +extern unsigned long gen_pool_first_fit_order_align (unsigned long *map, +unsigned long size,unsigned long start,unsigned int nr, +void *data); +extern unsigned long gen_pool_best_fit (unsigned long *map,unsigned long size,unsigned long start,unsigned int nr,void *data);
lib/genalloc.c +20 -0
@@ -481,6 +481,26 @@ unsigned long gen_pool_first_fit(unsigned long *map, unsigned long size,EXPORT_SYMBOL (gen_pool_first_fit);/** +* gen_pool_first_fit_order_align - find the first available region +* of memory matching the size requirement. The region will be aligned +* to the order of the size specified. +* @map: The address to base the search on +* @size: The bitmap size in bits +* @start: The bitnumber to start searching at +* @nr: The number of zeroed bits we're looking for +* @data: additional data - unused +*/ +unsigned long gen_pool_first_fit_order_align (unsigned long *map, +unsigned long size,unsigned long start, +unsigned int nr,void *data) +{ +unsigned long align_mask =roundup_pow_of_two (nr) -1 ; + +return bitmap_find_next_zero_area (map, size, start, nr, align_mask); +} +EXPORT_SYMBOL (gen_pool_first_fit_order_align); + +/** * gen_pool_best_fit - find the best fitting region of memory * macthing the size requirement (no alignment constraint) * @map: The address to base the search on
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v7 2/5 lib/genalloc.c: Add genpool range check function
In reply to Laura AbbottAfter allocating an address from a particular genpool, there is no good way to verify if that address actually belongs to a genpool. Introduce addr_in_gen_pool which will return if an address plus size falls completely within the genpool range.
--- include/linux/genalloc.h | 3 +++ lib/genalloc.c | 29 +++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+)
include/linux/genalloc.h +3 -0
@@ -121,6 +121,9 @@ extern struct gen_pool *devm_gen_pool_create(struct device *dev, int min_alloc_order, int nid);extern struct gen_pool *dev_get_gen_pool (struct device *dev); +bool addr_in_gen_pool (struct gen_pool *pool,unsigned long start, +size_t size); +#ifdef CONFIG_OF extern struct gen_pool *of_get_named_gen_pool (struct device_node *np,const char *propname,int index);
lib/genalloc.c +29 -0
@@ -403,6 +403,35 @@ void gen_pool_for_each_chunk(struct gen_pool *pool,EXPORT_SYMBOL (gen_pool_for_each_chunk);/** +* addr_in_gen_pool - checks if an address falls within the range of a pool +* @pool: the generic memory pool +* @start: start address +* @size: size of the region +* +* Check if the range of addresses falls within the specified pool. Returns +* true if the entire range is contained in the pool and false otherwise. +*/ +bool addr_in_gen_pool (struct gen_pool *pool,unsigned long start, +size_t size) +{ +bool found = false; +unsigned long end = start + size; +struct gen_pool_chunk *chunk; + +rcu_read_lock (); +list_for_each_entry_rcu (chunk, &(pool)->chunks, next_chunk) { +if (start >= chunk->start_addr && start <= chunk->end_addr) { +if (end <= chunk->end_addr) { + found = true; +break ; + } + } + } +rcu_read_unlock (); +return found; +} + +/** * gen_pool_avail - get available free space of the pool * @pool: pool to get available free space *
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v7 3/5 common: dma-mapping: Introduce common remapping functions
In reply to Laura AbbottFor 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.
--- 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(-)
arch/arm/mm/dma-mapping.c +9 -48
@@ -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);
drivers/base/dma-mapping.c +68 -0
77 lines not on this page · raw message
include/asm-generic/dma-mapping-common.h +9 -0
@@ -179,6 +179,15 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,extern int dma_common_mmap (struct device *dev,struct vm_area_struct *vma,void *cpu_addr,dma_addr_t dma_addr,size_t size); +void *dma_common_contiguous_remap (struct page *page,size_t size, +unsigned long vm_flags, +pgprot_t prot,const void *caller); + +void *dma_common_pages_remap (struct page **pages,size_t size, +unsigned long vm_flags,pgprot_t prot, +const void *caller); +void dma_common_free_remap (void *cpu_addr,size_t size,unsigned long vm_flags); +/** * dma_mmap_attrs - map a coherent DMA allocation into user space * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCHv7 3/5] common: dma-mapping: Introduce common remapping functions
Quoted 6 lines · 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.
Quoted 8 lines
As part of this, the arm APIs are now migrated away from
ioremap_page_rangeto the common APIs which usemap_vm_areafor remapping. This should be an equivalent change and usingmap_vm_areais more correct asioremap_page_rangeis intended to bring in io addresses into the cpu space and not regular kernel managed memory.Reviewed-by Catalin Marinas <[email protected]>Signed-off-by Laura Abbott <[email protected]>
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 castdrivers/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
Quoted 208 lines
--- 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(-)arch/arm/mm/dma-mapping.c +9
-48@@ -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);drivers/base/dma-mapping.c +68
-0@@ -10,6 +10,8 @@#include <linux/dma-mapping.h> #include <linux/export.h> #include <linux/gfp.h> +#include <linux/slab.h> +#include <linux/vmalloc.h> #include <asm-generic/dma-coherent.h> /* @@ -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) +return NULL ; + +for (i =0 , pfn =page_to_pfn (page); i < (size >>PAGE_SHIFT ); i++) + pages[i] =pfn_to_page (pfn + i); + + ptr =dma_common_pages_remap (pages, size, vm_flags, prot, caller); + +kfree (pages); + +return ptr; +} + +/* +* 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 *cpu_addr,size_t size,unsigned long vm_flags) +{ +struct vm_struct *area =find_vm_area (cpu_addr); + +if (!area || (area->flags & vm_flags) != vm_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); +}include/asm-generic/dma-mapping-common.h +9
-1@@ -179,6 +179,15 @@ dma_sync_sg_for_device(struct device *dev, struct scatterlist *sg,extern int dma_common_mmap (struct device *dev,struct vm_area_struct *vma,void *cpu_addr,dma_addr_t dma_addr,size_t size); +void *dma_common_contiguous_remap (struct page *page,size_t size, +unsigned long vm_flags, +pgprot_t prot,const void *caller); + +void *dma_common_pages_remap (struct page **pages,size_t size, +unsigned long vm_flags,pgprot_t prot, +const void *caller); +void dma_common_free_remap (void *cpu_addr,size_t size,unsigned long vm_flags); +/** * dma_mmap_attrs - map a coherent DMA allocation into user space * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices -- The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo at 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
Quoted 44 lines · James Hogan
Quoted 6 lines · 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.
Quoted 8 lines
As part of this, the arm APIs are now migrated away from
ioremap_page_rangeto the common APIs which usemap_vm_areafor remapping. This should be an equivalent change and usingmap_vm_areais more correct asioremap_page_rangeis intended to bring in io addresses into the cpu space and not regular kernel managed memory.Reviewed-by Catalin Marinas <[email protected]>Signed-off-by Laura Abbott <[email protected]>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 castdrivers/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 hereLooks 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
Quoted 6 lines
I've checked a couple of these arches (blackfin, xtensa) which don't include
dma-mapping-common.hand 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<------
Quoted 1 line
From
81c9a5504cbc1d72ff1df084d48502b248cd79d0Mon Sep 17 00:00:00 2001
From: Laura Abbott <[email protected]>
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 castdrivers/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
--- drivers/base/dma-mapping.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-)
drivers/base/dma-mapping.c +22 -22
@@ -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 *cpu_addr,size_t size,unsigned long vm_flags)
Signature · 6 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation -- Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum, hosted by The Linux Foundation
Re: [PATCHv7 3/5] common: dma-mapping: Introduce common remapping functions
Quoted 48 lines · Laura Abbott
Quoted 47 lines · James Hogan
Quoted 6 lines · 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.
Quoted 8 lines
As part of this, the arm APIs are now migrated away from
ioremap_page_rangeto the common APIs which usemap_vm_areafor remapping. This should be an equivalent change and usingmap_vm_areais more correct asioremap_page_rangeis intended to bring in io addresses into the cpu space and not regular kernel managed memory.Reviewed-by Catalin Marinas <[email protected]>Signed-off-by Laura Abbott <[email protected]>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 castdrivers/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 hereLooks 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.hI've checked a couple of these arches (blackfin, xtensa) which don't include
dma-mapping-common.hand their builds seem to be broken too.
Quoted 6 lines
Quoted 3 lines
Cheers
JamesThanks 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
Quoted 93 lines
-----8<------
From
81c9a5504cbc1d72ff1df084d48502b248cd79d0Mon Sep 17 00:00:00 2001
From: Laura Abbott <[email protected]>
Date: Tue, 26 Aug 2014 09:50:49 -0700
Subject: [PATCH] common: dma-mapping: Swap function orderFix the order of
dma_common_contiguous_remapanddma_common_pages_remapto 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 castdrivers/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 hereChange-Id I65db739114e8f5816a24a279a2ff1a6dc92e2b83Reported-by James Hogan <[email protected]>Reported-by kbuild test robot <[email protected]>Signed-off-by Laura Abbott <[email protected]>--- drivers/base/dma-mapping.c | 44 ++++++++++++++++++++++---------------------- 1 file changed, 22 insertions(+), 22 deletions(-)drivers/base/dma-mapping.c +22
-22@@ -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 *cpu_addr,size_t size,unsigned long vm_flags)
Re: [PATCHv7 3/5] common: dma-mapping: Introduce common remapping functions
In reply to Laura AbbottQuoted 48 lines · Laura Abbott
Quoted 47 lines · James Hogan
Quoted 6 lines · 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.
Quoted 8 lines
As part of this, the arm APIs are now migrated away from
ioremap_page_rangeto the common APIs which usemap_vm_areafor remapping. This should be an equivalent change and usingmap_vm_areais more correct asioremap_page_rangeis intended to bring in io addresses into the cpu space and not regular kernel managed memory.Reviewed-by Catalin Marinas <[email protected]>Signed-off-by Laura Abbott <[email protected]>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 castdrivers/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 hereLooks 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.hI've checked a couple of these arches (blackfin, xtensa) which don't include
dma-mapping-common.hand their builds seem to be broken too.
Quoted 6 lines
Quoted 3 lines
Cheers
JamesThanks 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'
PATCH v7 4/5 arm: use genalloc for the atomic pool
In reply to Laura AbbottARM currently uses a bitmap for tracking atomic allocations. genalloc already handles this type of memory pool allocation so switch to using that instead.
--- arch/arm/Kconfig | 1 + arch/arm/mm/dma-mapping.c | 153 +++++++++++++++------------------------------- 2 files changed, 50 insertions(+), 104 deletions(-)
arch/arm/Kconfig +1 -0
@@ -14,6 +14,7 @@ config ARM select CLONE_BACKWARDS select CPU_PM if (SUSPEND || CPU_IDLE) select DCACHE_WORD_ACCESS if HAVE_EFFICIENT_UNALIGNED_ACCESS + select GENERIC_ALLOCATOR select GENERIC_ATOMIC64 if (CPU_V7M || CPU_V6 || !CPU_32v6K || !AEABI) select GENERIC_CLOCKEVENTS_BROADCAST if SMP select GENERIC_IDLE_POLL_SETUP
arch/arm/mm/dma-mapping.c +49 -104
231 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation
PATCH v7 5/5 arm64: Add atomic pool for non-coherent and CMA allocations.
In reply to Laura AbbottNeither CMA nor noncoherent allocations support atomic allocations. Add a dedicated atomic pool to support this.
--- arch/arm64/Kconfig | 1 + arch/arm64/mm/dma-mapping.c | 164 +++++++++++++++++++++++++++++++++++++++----- 2 files changed, 146 insertions(+), 19 deletions(-)
arch/arm64/Kconfig +1 -0
@@ -16,6 +16,7 @@ config ARM64 select COMMON_CLK select CPU_PM if (SUSPEND || CPU_IDLE) select DCACHE_WORD_ACCESS + select GENERIC_ALLOCATOR select GENERIC_CLOCKEVENTS select GENERIC_CLOCKEVENTS_BROADCAST if SMP select GENERIC_CPU_AUTOPROBE
arch/arm64/mm/dma-mapping.c +145 -19
233 lines not on this page · raw message
Signature · 2 lines
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, hosted by The Linux Foundation