* [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
* [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).