* [PATCH 0/4] ARM: replace custom consistent dma region with vmalloc @ 2012-04-13 14:05 Marek Szyprowski 2012-04-13 14:05 ` [PATCH 1/4] mm: vmalloc: use const void * for caller argument Marek Szyprowski ` (4 more replies) 0 siblings, 5 replies; 9+ messages in thread From: Marek Szyprowski @ 2012-04-13 14:05 UTC (permalink / raw) To: linux-arm-kernel Hi! Recent changes to ioremap and unification of vmalloc regions on ARM significantly reduces the possible size of the consistent dma region and limited allowed dma coherent/writecombine allocations. This experimental patch series replaces custom consistent dma regions usage in dma-mapping framework in favour of generic vmalloc areas created on demand for each coherent and writecombine allocations. This patch is based on vanilla v3.4-rc2 release. Best regards Marek Szyprowski Samsung Poland R&D Center Patch summary: Marek Szyprowski (4): mm: vmalloc: use const void * for caller argument mm: vmalloc: export find_vm_area() function mm: vmalloc: add VM_DMA flag to indicate areas used by dma-mapping framework ARM: remove consistent dma region and use common vmalloc range for dma allocations arch/arm/include/asm/dma-mapping.h | 2 +- arch/arm/mm/dma-mapping.c | 220 +++++++----------------------------- include/linux/vmalloc.h | 10 +- mm/vmalloc.c | 31 ++++-- 4 files changed, 67 insertions(+), 196 deletions(-) -- 1.7.1.569.g6f426 ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 1/4] mm: vmalloc: use const void * for caller argument 2012-04-13 14:05 [PATCH 0/4] ARM: replace custom consistent dma region with vmalloc Marek Szyprowski @ 2012-04-13 14:05 ` Marek Szyprowski 2012-04-13 14:05 ` [PATCH 2/4] mm: vmalloc: export find_vm_area() function Marek Szyprowski ` (3 subsequent siblings) 4 siblings, 0 replies; 9+ messages in thread From: Marek Szyprowski @ 2012-04-13 14:05 UTC (permalink / raw) To: linux-arm-kernel 'const void *' is a safer type for caller function type. This patch updates all references to caller function type. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com> --- include/linux/vmalloc.h | 8 ++++---- mm/vmalloc.c | 18 +++++++++--------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index dcdfc2b..2e28f4d 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -32,7 +32,7 @@ struct vm_struct { struct page **pages; unsigned int nr_pages; phys_addr_t phys_addr; - void *caller; + const void *caller; }; /* @@ -62,7 +62,7 @@ extern void *vmalloc_32_user(unsigned long size); extern void *__vmalloc(unsigned long size, gfp_t gfp_mask, pgprot_t prot); extern void *__vmalloc_node_range(unsigned long size, unsigned long align, unsigned long start, unsigned long end, gfp_t gfp_mask, - pgprot_t prot, int node, void *caller); + pgprot_t prot, int node, const void *caller); extern void vfree(const void *addr); extern void *vmap(struct page **pages, unsigned int count, @@ -85,13 +85,13 @@ static inline size_t get_vm_area_size(const struct vm_struct *area) extern struct vm_struct *get_vm_area(unsigned long size, unsigned long flags); extern struct vm_struct *get_vm_area_caller(unsigned long size, - unsigned long flags, void *caller); + unsigned long flags, const void *caller); extern struct vm_struct *__get_vm_area(unsigned long size, unsigned long flags, unsigned long start, unsigned long end); extern struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags, unsigned long start, unsigned long end, - void *caller); + const void *caller); extern struct vm_struct *remove_vm_area(const void *addr); extern int map_vm_area(struct vm_struct *area, pgprot_t prot, diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 94dff88..8bc7f3e 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -1279,7 +1279,7 @@ DEFINE_RWLOCK(vmlist_lock); struct vm_struct *vmlist; static void setup_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va, - unsigned long flags, void *caller) + unsigned long flags, const void *caller) { vm->flags = flags; vm->addr = (void *)va->va_start; @@ -1305,7 +1305,7 @@ static void insert_vmalloc_vmlist(struct vm_struct *vm) } static void insert_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va, - unsigned long flags, void *caller) + unsigned long flags, const void *caller) { setup_vmalloc_vm(vm, va, flags, caller); insert_vmalloc_vmlist(vm); @@ -1313,7 +1313,7 @@ static void insert_vmalloc_vm(struct vm_struct *vm, struct vmap_area *va, static struct vm_struct *__get_vm_area_node(unsigned long size, unsigned long align, unsigned long flags, unsigned long start, - unsigned long end, int node, gfp_t gfp_mask, void *caller) + unsigned long end, int node, gfp_t gfp_mask, const void *caller) { struct vmap_area *va; struct vm_struct *area; @@ -1374,7 +1374,7 @@ EXPORT_SYMBOL_GPL(__get_vm_area); struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long flags, unsigned long start, unsigned long end, - void *caller) + const void *caller) { return __get_vm_area_node(size, 1, flags, start, end, -1, GFP_KERNEL, caller); @@ -1396,7 +1396,7 @@ struct vm_struct *get_vm_area(unsigned long size, unsigned long flags) } struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags, - void *caller) + const void *caller) { return __get_vm_area_node(size, 1, flags, VMALLOC_START, VMALLOC_END, -1, GFP_KERNEL, caller); @@ -1567,9 +1567,9 @@ EXPORT_SYMBOL(vmap); static void *__vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask, pgprot_t prot, - int node, void *caller); + int node, const void *caller); static void *__vmalloc_area_node(struct vm_struct *area, gfp_t gfp_mask, - pgprot_t prot, int node, void *caller) + pgprot_t prot, int node, const void *caller) { const int order = 0; struct page **pages; @@ -1642,7 +1642,7 @@ fail: */ void *__vmalloc_node_range(unsigned long size, unsigned long align, unsigned long start, unsigned long end, gfp_t gfp_mask, - pgprot_t prot, int node, void *caller) + pgprot_t prot, int node, const void *caller) { struct vm_struct *area; void *addr; @@ -1698,7 +1698,7 @@ fail: */ static void *__vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask, pgprot_t prot, - int node, void *caller) + int node, const void *caller) { return __vmalloc_node_range(size, align, VMALLOC_START, VMALLOC_END, gfp_mask, prot, node, caller); -- 1.7.1.569.g6f426 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 2/4] mm: vmalloc: export find_vm_area() function 2012-04-13 14:05 [PATCH 0/4] ARM: replace custom consistent dma region with vmalloc Marek Szyprowski 2012-04-13 14:05 ` [PATCH 1/4] mm: vmalloc: use const void * for caller argument Marek Szyprowski @ 2012-04-13 14:05 ` Marek Szyprowski 2012-04-13 14:05 ` [PATCH 3/4] mm: vmalloc: add VM_DMA flag to indicate areas used by dma-mapping framework Marek Szyprowski ` (2 subsequent siblings) 4 siblings, 0 replies; 9+ messages in thread From: Marek Szyprowski @ 2012-04-13 14:05 UTC (permalink / raw) To: linux-arm-kernel find_vm_area() function is usefull for other core subsystems (like dma-mapping) to get access to vm_area internals. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com> --- include/linux/vmalloc.h | 1 + mm/vmalloc.c | 10 +++++++++- 2 files changed, 10 insertions(+), 1 deletions(-) diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 2e28f4d..6071e91 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -93,6 +93,7 @@ extern struct vm_struct *__get_vm_area_caller(unsigned long size, unsigned long start, unsigned long end, const void *caller); extern struct vm_struct *remove_vm_area(const void *addr); +extern struct vm_struct *find_vm_area(const void *addr); extern int map_vm_area(struct vm_struct *area, pgprot_t prot, struct page ***pages); diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 8bc7f3e..8cb7f22 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -1402,7 +1402,15 @@ struct vm_struct *get_vm_area_caller(unsigned long size, unsigned long flags, -1, GFP_KERNEL, caller); } -static struct vm_struct *find_vm_area(const void *addr) +/** + * find_vm_area - find a continuous kernel virtual area + * @addr: base address + * + * Search for the kernel VM area starting at @addr, and return it. + * It is up to the caller to do all required locking to keep the returned + * pointer valid. + */ +struct vm_struct *find_vm_area(const void *addr) { struct vmap_area *va; -- 1.7.1.569.g6f426 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 3/4] mm: vmalloc: add VM_DMA flag to indicate areas used by dma-mapping framework 2012-04-13 14:05 [PATCH 0/4] ARM: replace custom consistent dma region with vmalloc Marek Szyprowski 2012-04-13 14:05 ` [PATCH 1/4] mm: vmalloc: use const void * for caller argument Marek Szyprowski 2012-04-13 14:05 ` [PATCH 2/4] mm: vmalloc: export find_vm_area() function Marek Szyprowski @ 2012-04-13 14:05 ` Marek Szyprowski 2012-04-13 14:05 ` [PATCH 4/4] ARM: remove consistent dma region and use common vmalloc range for dma allocations Marek Szyprowski [not found] ` <CALYq+qSMPoVC5OF+oBbt_i7O+_fmogLCtpqTAqHbsv1TcKrPdA@mail.gmail.com> 4 siblings, 0 replies; 9+ messages in thread From: Marek Szyprowski @ 2012-04-13 14:05 UTC (permalink / raw) To: linux-arm-kernel Add new type of vm_area intented to be used for consisten mappings created by dma-mapping framework. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com> --- include/linux/vmalloc.h | 1 + mm/vmalloc.c | 3 +++ 2 files changed, 4 insertions(+), 0 deletions(-) diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h index 6071e91..8a9555a 100644 --- a/include/linux/vmalloc.h +++ b/include/linux/vmalloc.h @@ -14,6 +14,7 @@ struct vm_area_struct; /* vma defining user mapping in mm_types.h */ #define VM_USERMAP 0x00000008 /* suitable for remap_vmalloc_range */ #define VM_VPAGES 0x00000010 /* buffer for pages was vmalloc'ed */ #define VM_UNLIST 0x00000020 /* vm_struct is not listed in vmlist */ +#define VM_DMA 0x00000040 /* used by dma-mapping framework */ /* bits [20..32] reserved for arch specific ioremap internals */ /* diff --git a/mm/vmalloc.c b/mm/vmalloc.c index 8cb7f22..9c13bab 100644 --- a/mm/vmalloc.c +++ b/mm/vmalloc.c @@ -2582,6 +2582,9 @@ static int s_show(struct seq_file *m, void *p) if (v->flags & VM_IOREMAP) seq_printf(m, " ioremap"); + if (v->flags & VM_DMA) + seq_printf(m, " dma"); + if (v->flags & VM_ALLOC) seq_printf(m, " vmalloc"); -- 1.7.1.569.g6f426 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/4] ARM: remove consistent dma region and use common vmalloc range for dma allocations 2012-04-13 14:05 [PATCH 0/4] ARM: replace custom consistent dma region with vmalloc Marek Szyprowski ` (2 preceding siblings ...) 2012-04-13 14:05 ` [PATCH 3/4] mm: vmalloc: add VM_DMA flag to indicate areas used by dma-mapping framework Marek Szyprowski @ 2012-04-13 14:05 ` Marek Szyprowski 2012-04-13 18:38 ` Russell King - ARM Linux [not found] ` <CALYq+qSMPoVC5OF+oBbt_i7O+_fmogLCtpqTAqHbsv1TcKrPdA@mail.gmail.com> 4 siblings, 1 reply; 9+ messages in thread From: Marek Szyprowski @ 2012-04-13 14:05 UTC (permalink / raw) To: linux-arm-kernel This patch changes dma-mapping subsystem to use generic vmalloc areas for all consistent dma allocations. This increases the total size limit of the consistent allocations and removes platform hacks and a lot of duplicated code. Signed-off-by: Marek Szyprowski <m.szyprowski@samsung.com> Reviewed-by: Kyungmin Park <kyungmin.park@samsung.com> --- arch/arm/include/asm/dma-mapping.h | 2 +- arch/arm/mm/dma-mapping.c | 220 +++++++----------------------------- 2 files changed, 40 insertions(+), 182 deletions(-) diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h index cb3b7c9..92b0afb 100644 --- a/arch/arm/include/asm/dma-mapping.h +++ b/arch/arm/include/asm/dma-mapping.h @@ -210,7 +210,7 @@ int dma_mmap_writecombine(struct device *, struct vm_area_struct *, * DMA region above it's default value of 2MB. It must be called before the * memory allocator is initialised, i.e. before any core_initcall. */ -extern void __init init_consistent_dma_size(unsigned long size); +static inline void init_consistent_dma_size(unsigned long size) { } #ifdef CONFIG_DMABOUNCE diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index db23ae4..74ff839 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -19,6 +19,8 @@ #include <linux/dma-mapping.h> #include <linux/highmem.h> #include <linux/slab.h> +#include <linux/vmalloc.h> +#include <linux/io.h> #include <asm/memory.h> #include <asm/highmem.h> @@ -119,204 +121,59 @@ static void __dma_free_buffer(struct page *page, size_t size) } #ifdef CONFIG_MMU - -#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - consistent_base) >> PAGE_SHIFT) -#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - consistent_base) >> PMD_SHIFT) - -/* - * These are the page tables (2MB each) covering uncached, DMA consistent allocations - */ -static pte_t **consistent_pte; - -#define DEFAULT_CONSISTENT_DMA_SIZE SZ_2M - -unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE; - -void __init init_consistent_dma_size(unsigned long size) -{ - unsigned long base = CONSISTENT_END - ALIGN(size, SZ_2M); - - BUG_ON(consistent_pte); /* Check we're called before DMA region init */ - BUG_ON(base < VMALLOC_END); - - /* Grow region to accommodate specified size */ - if (base < consistent_base) - consistent_base = base; -} - -#include "vmregion.h" - -static struct arm_vmregion_head consistent_head = { - .vm_lock = __SPIN_LOCK_UNLOCKED(&consistent_head.vm_lock), - .vm_list = LIST_HEAD_INIT(consistent_head.vm_list), - .vm_end = CONSISTENT_END, -}; - #ifdef CONFIG_HUGETLB_PAGE #error ARM Coherent DMA allocator does not (yet) support huge TLB #endif -/* - * Initialise the consistent memory allocation. - */ -static int __init consistent_init(void) -{ - int ret = 0; - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - int i = 0; - unsigned long base = consistent_base; - unsigned long num_ptes = (CONSISTENT_END - base) >> PMD_SHIFT; - - consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL); - if (!consistent_pte) { - pr_err("%s: no memory\n", __func__); - return -ENOMEM; - } - - pr_debug("DMA memory: 0x%08lx - 0x%08lx:\n", base, CONSISTENT_END); - consistent_head.vm_start = base; - - do { - pgd = pgd_offset(&init_mm, base); - - pud = pud_alloc(&init_mm, pgd, base); - if (!pud) { - printk(KERN_ERR "%s: no pud tables\n", __func__); - ret = -ENOMEM; - break; - } - - pmd = pmd_alloc(&init_mm, pud, base); - if (!pmd) { - printk(KERN_ERR "%s: no pmd tables\n", __func__); - ret = -ENOMEM; - break; - } - WARN_ON(!pmd_none(*pmd)); - - pte = pte_alloc_kernel(pmd, base); - if (!pte) { - printk(KERN_ERR "%s: no pte tables\n", __func__); - ret = -ENOMEM; - break; - } - - consistent_pte[i++] = pte; - base += PMD_SIZE; - } while (base < CONSISTENT_END); - - return ret; -} - -core_initcall(consistent_init); - static void * __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot, const void *caller) { - struct arm_vmregion *c; - size_t align; - int bit; - - if (!consistent_pte) { - printk(KERN_ERR "%s: not initialised\n", __func__); - dump_stack(); - return NULL; - } - - /* - * Align the virtual region allocation - maximum alignment is - * a section size, minimum is a page size. This helps reduce - * fragmentation of the DMA space, and also prevents allocations - * smaller than a section from crossing a section boundary. - */ - bit = fls(size - 1); - if (bit > SECTION_SHIFT) - bit = SECTION_SHIFT; - align = 1 << bit; - - /* - * Allocate a virtual address in the consistent mapping region. - */ - c = arm_vmregion_alloc(&consistent_head, align, size, - gfp & ~(__GFP_DMA | __GFP_HIGHMEM), caller); - if (c) { - pte_t *pte; - int idx = CONSISTENT_PTE_INDEX(c->vm_start); - u32 off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1); - - pte = consistent_pte[idx] + off; - c->vm_pages = page; - - do { - BUG_ON(!pte_none(*pte)); - - set_pte_ext(pte, mk_pte(page, prot), 0); - page++; - pte++; - off++; - if (off >= PTRS_PER_PTE) { - off = 0; - pte = consistent_pte[++idx]; - } - } while (size -= PAGE_SIZE); - - dsb(); + struct vm_struct *area; + unsigned long addr; - return (void *)c->vm_start; - } - return NULL; + area = get_vm_area_caller(size, VM_DMA | 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; } static void __dma_free_remap(void *cpu_addr, size_t size) { - struct arm_vmregion *c; - unsigned long addr; - pte_t *ptep; - int idx; - u32 off; + struct vm_struct *area; + + read_lock(&vmlist_lock); - c = arm_vmregion_find_remove(&consistent_head, (unsigned long)cpu_addr); - if (!c) { + area = find_vm_area(cpu_addr); + if (!area) { printk(KERN_ERR "%s: trying to free invalid coherent area: %p\n", __func__, cpu_addr); dump_stack(); + read_unlock(&vmlist_lock); return; } - if ((c->vm_end - c->vm_start) != size) { + /* + * get_vm_area_caller always use additional guard page, so skip it here + */ + if (area->size - PAGE_SIZE != size) { printk(KERN_ERR "%s: freeing wrong coherent size (%ld != %d)\n", - __func__, c->vm_end - c->vm_start, size); + __func__, area->size, size); dump_stack(); - size = c->vm_end - c->vm_start; + size = area->size; } - idx = CONSISTENT_PTE_INDEX(c->vm_start); - off = CONSISTENT_OFFSET(c->vm_start) & (PTRS_PER_PTE-1); - ptep = consistent_pte[idx] + off; - addr = c->vm_start; - do { - pte_t pte = ptep_get_and_clear(&init_mm, addr, ptep); - - ptep++; - addr += PAGE_SIZE; - off++; - if (off >= PTRS_PER_PTE) { - off = 0; - ptep = consistent_pte[++idx]; - } - - if (pte_none(pte) || !pte_present(pte)) - printk(KERN_CRIT "%s: bad page in kernel page table\n", - __func__); - } while (size -= PAGE_SIZE); + unmap_kernel_range((unsigned long)cpu_addr, size); + read_unlock(&vmlist_lock); - flush_tlb_kernel_range(c->vm_start, c->vm_end); - - arm_vmregion_free(&consistent_head, c); + vunmap(cpu_addr); } #else /* !CONFIG_MMU */ @@ -398,25 +255,29 @@ static int dma_mmap(struct device *dev, struct vm_area_struct *vma, { int ret = -ENXIO; #ifdef CONFIG_MMU + struct vm_struct *area; unsigned long user_size, kern_size; - struct arm_vmregion *c; + read_lock(&vmlist_lock); + area = find_vm_area(cpu_addr); user_size = (vma->vm_end - vma->vm_start) >> PAGE_SHIFT; - c = arm_vmregion_find(&consistent_head, (unsigned long)cpu_addr); - if (c) { + if (area) { unsigned long off = vma->vm_pgoff; + unsigned long phys = __phys_to_pfn(area->phys_addr); - kern_size = (c->vm_end - c->vm_start) >> PAGE_SHIFT; + /* skip vmalloc guard page */ + kern_size = (area->size >> PAGE_SHIFT) - 1; if (off < kern_size && user_size <= (kern_size - off)) { ret = remap_pfn_range(vma, vma->vm_start, - page_to_pfn(c->vm_pages) + off, + phys + off, user_size << PAGE_SHIFT, vma->vm_page_prot); } } + read_unlock(&vmlist_lock); #endif /* CONFIG_MMU */ return ret; @@ -726,9 +587,6 @@ EXPORT_SYMBOL(dma_set_mask); static int __init dma_debug_do_init(void) { -#ifdef CONFIG_MMU - arm_vmregion_create_proc("dma-mappings", &consistent_head); -#endif dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES); return 0; } -- 1.7.1.569.g6f426 ^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH 4/4] ARM: remove consistent dma region and use common vmalloc range for dma allocations 2012-04-13 14:05 ` [PATCH 4/4] ARM: remove consistent dma region and use common vmalloc range for dma allocations Marek Szyprowski @ 2012-04-13 18:38 ` Russell King - ARM Linux 2012-04-16 1:32 ` Minchan Kim 0 siblings, 1 reply; 9+ messages in thread From: Russell King - ARM Linux @ 2012-04-13 18:38 UTC (permalink / raw) To: linux-arm-kernel On Fri, Apr 13, 2012 at 04:05:50PM +0200, Marek Szyprowski wrote: > This patch changes dma-mapping subsystem to use generic vmalloc areas > for all consistent dma allocations. This increases the total size limit > of the consistent allocations and removes platform hacks and a lot of > duplicated code. NAK. I don't think you appreciate the contexts from which the dma coherent code can be called from, and the reason why we pre-allocate the page tables (so that IRQ-based allocations work.) The vmalloc region doesn't allow that because page tables are allocated using GFP_KERNEL not GFP_ATOMIC. Sorry. ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/4] ARM: remove consistent dma region and use common vmalloc range for dma allocations 2012-04-13 18:38 ` Russell King - ARM Linux @ 2012-04-16 1:32 ` Minchan Kim 2012-04-17 18:18 ` KOSAKI Motohiro 0 siblings, 1 reply; 9+ messages in thread From: Minchan Kim @ 2012-04-16 1:32 UTC (permalink / raw) To: linux-arm-kernel On 04/14/2012 03:38 AM, Russell King - ARM Linux wrote: > On Fri, Apr 13, 2012 at 04:05:50PM +0200, Marek Szyprowski wrote: >> This patch changes dma-mapping subsystem to use generic vmalloc areas >> for all consistent dma allocations. This increases the total size limit >> of the consistent allocations and removes platform hacks and a lot of >> duplicated code. > > NAK. I don't think you appreciate the contexts from which the dma coherent > code can be called from, and the reason why we pre-allocate the page > tables (so that IRQ-based allocations work.) > > The vmalloc region doesn't allow that because page tables are allocated > using GFP_KERNEL not GFP_ATOMIC. > > Sorry. > Off-topic. I don't know why vmalloc functions have gfp_t argument. As Russel pointed out, we allocates page tables with GFP_KERNEL regardless of gfp_t passed. It means gfp_t passed is useless. I see there are many cases calling __vmalloc with GFP_NOFS, even GFP_ATOMIC. Then, it could end up deadlocking in reclaim context or schedule bug. I'm not sure why we can't see such bugs until now. If I didn't miss something, Shouldn't we fix it? > -- > To unsubscribe, send a message with 'unsubscribe linux-mm' in > the body to majordomo at kvack.org. For more info on Linux MM, > see: http://www.linux-mm.org/ . > Fight unfair telecom internet charges in Canada: sign http://stopthemeter.ca/ > Don't email:<a href=mailto:"dont@kvack.org"> email at kvack.org</a> > ^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH 4/4] ARM: remove consistent dma region and use common vmalloc range for dma allocations 2012-04-16 1:32 ` Minchan Kim @ 2012-04-17 18:18 ` KOSAKI Motohiro 0 siblings, 0 replies; 9+ messages in thread From: KOSAKI Motohiro @ 2012-04-17 18:18 UTC (permalink / raw) To: linux-arm-kernel (4/15/12 9:32 PM), Minchan Kim wrote: > On 04/14/2012 03:38 AM, Russell King - ARM Linux wrote: >> On Fri, Apr 13, 2012 at 04:05:50PM +0200, Marek Szyprowski wrote: >>> This patch changes dma-mapping subsystem to use generic vmalloc areas >>> for all consistent dma allocations. This increases the total size limit >>> of the consistent allocations and removes platform hacks and a lot of >>> duplicated code. >> >> NAK. I don't think you appreciate the contexts from which the dma coherent >> code can be called from, and the reason why we pre-allocate the page >> tables (so that IRQ-based allocations work.) >> >> The vmalloc region doesn't allow that because page tables are allocated >> using GFP_KERNEL not GFP_ATOMIC. >> >> Sorry. >> > > Off-topic. > > I don't know why vmalloc functions have gfp_t argument. > As Russel pointed out, we allocates page tables with GFP_KERNEL regardless of gfp_t passed. > It means gfp_t passed is useless. > I see there are many cases calling __vmalloc with GFP_NOFS, even GFP_ATOMIC. Then, it could end up deadlocking in reclaim context or schedule bug. > I'm not sure why we can't see such bugs until now. > If I didn't miss something, Shouldn't we fix it? I believe it should be fixed. of course. :) ^ permalink raw reply [flat|nested] 9+ messages in thread
[parent not found: <CALYq+qSMPoVC5OF+oBbt_i7O+_fmogLCtpqTAqHbsv1TcKrPdA@mail.gmail.com>]
* [Linaro-mm-sig] [PATCH 0/4] ARM: replace custom consistent dma region with vmalloc [not found] ` <CALYq+qSMPoVC5OF+oBbt_i7O+_fmogLCtpqTAqHbsv1TcKrPdA@mail.gmail.com> @ 2012-04-23 20:58 ` Daniel Vetter 0 siblings, 0 replies; 9+ messages in thread From: Daniel Vetter @ 2012-04-23 20:58 UTC (permalink / raw) To: linux-arm-kernel On Mon, Apr 23, 2012 at 09:02:25PM +0900, Abhinav Kochhar wrote: > Hi, > > I see a bottle-neck with the current dma-mapping framework. > Issue seems to be with the Virtual memory allocation for access in kernel > address space. > > 1. In "arch/arm/mm/dma-mapping.c" there is a initialization call to > "consistent_init". It reserves size 32MB of Kernel Address space. > 2. "consistent_init" allocates memory for kernel page directory and page > tables. > > 3. "__iommu_alloc_remap" function allocates virtual memory region in kernel > address space reserved in step 1. > > 4. "__iommu_alloc_remap" function then maps the allocated pages to the > address space reserved in step 3. > > Since the virtual memory area allocated for mapping these pages in kernel > address space is only 32MB, > > eventually the calls for allocation and mapping new pages into kernel > address space are going to fail once 32 MB is exhausted. > > e.g., For Exynos 5 platform Each framebuffer for 1280x800 resolution > consumes around 4MB. > > We have a scenario where X11 DRI driver would allocate Non-contig pages for > all "Pixmaps" through arm_iommu_alloc_attrs" function which will follow the > path given above in steps 1 - 4. > > Now the problem is the size limitation of 32MB. We may want to allocate > more than 8 such buffers when X11 DRI driver is integrated. > Possible solutions: > > 1. Why do we need to create a kernel virtual address space? Are we going to > access these pages in kernel using this address? > > If we are not going to access anything in kernel then why do we need to map > these pages in kernel address space?. If we can avoid this then the problem > can be solved. > > OR > > 2 Is it used for only book-keeping to retrieve "struct pages" later on for > passing/mapping to different devices? > > If yes, then we have to find another way. > > For "dmabuf" framework one solution could be to add a new member variable > "pages" in the exporting driver's local object and use that for > passing/mapping to different devices. > > Moreover, even if we increase to say 64 MB that would not be enough for our > use, we never know how many graphic applications would be spawned by the > user. > Let me know your opinion on this. This is more or less the reason I'm so massively opposed to adding vmap to dma-buf - you _really_ burn through the vmap space ridiculously quickly on 32bit platforms with too much memory (i.e. everything with more than 1 G). You need to map/unmap everything page-by-page with all the usual kmap apis the kernel provides. -Daniel -- Daniel Vetter Mail: daniel at ffwll.ch Mobile: +41 (0)79 365 57 48 ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2012-04-23 20:58 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2012-04-13 14:05 [PATCH 0/4] ARM: replace custom consistent dma region with vmalloc Marek Szyprowski 2012-04-13 14:05 ` [PATCH 1/4] mm: vmalloc: use const void * for caller argument Marek Szyprowski 2012-04-13 14:05 ` [PATCH 2/4] mm: vmalloc: export find_vm_area() function Marek Szyprowski 2012-04-13 14:05 ` [PATCH 3/4] mm: vmalloc: add VM_DMA flag to indicate areas used by dma-mapping framework Marek Szyprowski 2012-04-13 14:05 ` [PATCH 4/4] ARM: remove consistent dma region and use common vmalloc range for dma allocations Marek Szyprowski 2012-04-13 18:38 ` Russell King - ARM Linux 2012-04-16 1:32 ` Minchan Kim 2012-04-17 18:18 ` KOSAKI Motohiro [not found] ` <CALYq+qSMPoVC5OF+oBbt_i7O+_fmogLCtpqTAqHbsv1TcKrPdA@mail.gmail.com> 2012-04-23 20:58 ` [Linaro-mm-sig] [PATCH 0/4] ARM: replace custom consistent dma region with vmalloc Daniel Vetter
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).