aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJon Medhurst <tixy@yxit.co.uk>2011-08-02 12:28:27 -0400
committerJon Medhurst <tixy@yxit.co.uk>2011-08-22 08:00:10 -0400
commit99d1717dd7fecf2b10195b0d864323b952b4eba0 (patch)
tree1c60988a0eb4837240203c2de7b48e78e7b3975a
parent93ee7a9340d64f20295aacc3fb6a22b759323280 (diff)
ARM: Add init_consistent_dma_size()
This function can be called during boot to increase the size of the consistent 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. Signed-off-by: Jon Medhurst <tixy@yxit.co.uk> Acked-by: Nicolas Pitre <nicolas.pitre@linaro.org>
-rw-r--r--arch/arm/include/asm/dma-mapping.h7
-rw-r--r--arch/arm/include/asm/memory.h9
-rw-r--r--arch/arm/mm/dma-mapping.c49
-rw-r--r--arch/arm/mm/init.c9
4 files changed, 45 insertions, 29 deletions
diff --git a/arch/arm/include/asm/dma-mapping.h b/arch/arm/include/asm/dma-mapping.h
index 7a21d0bf7134..7f27fab9d404 100644
--- a/arch/arm/include/asm/dma-mapping.h
+++ b/arch/arm/include/asm/dma-mapping.h
@@ -205,6 +205,13 @@ extern void *dma_alloc_writecombine(struct device *, size_t, dma_addr_t *,
205int dma_mmap_writecombine(struct device *, struct vm_area_struct *, 205int dma_mmap_writecombine(struct device *, struct vm_area_struct *,
206 void *, dma_addr_t, size_t); 206 void *, dma_addr_t, size_t);
207 207
208/*
209 * This can be called during boot to increase the size of the consistent
210 * DMA region above it's default value of 2MB. It must be called before the
211 * memory allocator is initialised, i.e. before any core_initcall.
212 */
213extern void __init init_consistent_dma_size(unsigned long size);
214
208 215
209#ifdef CONFIG_DMABOUNCE 216#ifdef CONFIG_DMABOUNCE
210/* 217/*
diff --git a/arch/arm/include/asm/memory.h b/arch/arm/include/asm/memory.h
index b8de516e600e..652fccca4952 100644
--- a/arch/arm/include/asm/memory.h
+++ b/arch/arm/include/asm/memory.h
@@ -77,16 +77,7 @@
77 */ 77 */
78#define IOREMAP_MAX_ORDER 24 78#define IOREMAP_MAX_ORDER 24
79 79
80/*
81 * Size of DMA-consistent memory region. Must be multiple of 2M,
82 * between 2MB and 14MB inclusive.
83 */
84#ifndef CONSISTENT_DMA_SIZE
85#define CONSISTENT_DMA_SIZE SZ_2M
86#endif
87
88#define CONSISTENT_END (0xffe00000UL) 80#define CONSISTENT_END (0xffe00000UL)
89#define CONSISTENT_BASE (CONSISTENT_END - CONSISTENT_DMA_SIZE)
90 81
91#else /* CONFIG_MMU */ 82#else /* CONFIG_MMU */
92 83
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 0a0a1e7c20d2..5b59ce572877 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -18,12 +18,14 @@
18#include <linux/device.h> 18#include <linux/device.h>
19#include <linux/dma-mapping.h> 19#include <linux/dma-mapping.h>
20#include <linux/highmem.h> 20#include <linux/highmem.h>
21#include <linux/slab.h>
21 22
22#include <asm/memory.h> 23#include <asm/memory.h>
23#include <asm/highmem.h> 24#include <asm/highmem.h>
24#include <asm/cacheflush.h> 25#include <asm/cacheflush.h>
25#include <asm/tlbflush.h> 26#include <asm/tlbflush.h>
26#include <asm/sizes.h> 27#include <asm/sizes.h>
28#include <asm/mach/arch.h>
27 29
28#include "mm.h" 30#include "mm.h"
29 31
@@ -117,26 +119,41 @@ static void __dma_free_buffer(struct page *page, size_t size)
117} 119}
118 120
119#ifdef CONFIG_MMU 121#ifdef CONFIG_MMU
120/* Sanity check size */
121#if (CONSISTENT_DMA_SIZE % SZ_2M)
122#error "CONSISTENT_DMA_SIZE must be multiple of 2MiB"
123#endif
124 122
125#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT) 123
126#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT) 124#define CONSISTENT_OFFSET(x) (((unsigned long)(x) - consistent_base) >> PAGE_SHIFT)
127#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT) 125#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - consistent_base) >> PGDIR_SHIFT)
128 126
129/* 127/*
130 * These are the page tables (2MB each) covering uncached, DMA consistent allocations 128 * These are the page tables (2MB each) covering uncached, DMA consistent allocations
131 */ 129 */
132static pte_t *consistent_pte[NUM_CONSISTENT_PTES]; 130static pte_t **consistent_pte;
131
132#ifdef CONSISTENT_DMA_SIZE
133#define DEFAULT_CONSISTENT_DMA_SIZE CONSISTENT_DMA_SIZE
134#else
135#define DEFAULT_CONSISTENT_DMA_SIZE SZ_2M
136#endif
137
138unsigned long consistent_base = CONSISTENT_END - DEFAULT_CONSISTENT_DMA_SIZE;
139
140void __init init_consistent_dma_size(unsigned long size)
141{
142 unsigned long base = CONSISTENT_END - ALIGN(size, SZ_2M);
143
144 BUG_ON(consistent_pte); /* Check we're called before DMA region init */
145 BUG_ON(base < VMALLOC_END);
146
147 /* Grow region to accommodate specified size */
148 if (base < consistent_base)
149 consistent_base = base;
150}
133 151
134#include "vmregion.h" 152#include "vmregion.h"
135 153
136static struct arm_vmregion_head consistent_head = { 154static struct arm_vmregion_head consistent_head = {
137 .vm_lock = __SPIN_LOCK_UNLOCKED(&consistent_head.vm_lock), 155 .vm_lock = __SPIN_LOCK_UNLOCKED(&consistent_head.vm_lock),
138 .vm_list = LIST_HEAD_INIT(consistent_head.vm_list), 156 .vm_list = LIST_HEAD_INIT(consistent_head.vm_list),
139 .vm_start = CONSISTENT_BASE,
140 .vm_end = CONSISTENT_END, 157 .vm_end = CONSISTENT_END,
141}; 158};
142 159
@@ -155,7 +172,17 @@ static int __init consistent_init(void)
155 pmd_t *pmd; 172 pmd_t *pmd;
156 pte_t *pte; 173 pte_t *pte;
157 int i = 0; 174 int i = 0;
158 u32 base = CONSISTENT_BASE; 175 unsigned long base = consistent_base;
176 unsigned long num_ptes = (CONSISTENT_END - base) >> PGDIR_SHIFT;
177
178 consistent_pte = kmalloc(num_ptes * sizeof(pte_t), GFP_KERNEL);
179 if (!consistent_pte) {
180 pr_err("%s: no memory\n", __func__);
181 return -ENOMEM;
182 }
183
184 pr_debug("DMA memory: 0x%08lx - 0x%08lx:\n", base, CONSISTENT_END);
185 consistent_head.vm_start = base;
159 186
160 do { 187 do {
161 pgd = pgd_offset(&init_mm, base); 188 pgd = pgd_offset(&init_mm, base);
@@ -198,7 +225,7 @@ __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot)
198 size_t align; 225 size_t align;
199 int bit; 226 int bit;
200 227
201 if (!consistent_pte[0]) { 228 if (!consistent_pte) {
202 printk(KERN_ERR "%s: not initialised\n", __func__); 229 printk(KERN_ERR "%s: not initialised\n", __func__);
203 dump_stack(); 230 dump_stack();
204 return NULL; 231 return NULL;
diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c
index 91bca355cd31..64ab41348f30 100644
--- a/arch/arm/mm/init.c
+++ b/arch/arm/mm/init.c
@@ -653,9 +653,6 @@ void __init mem_init(void)
653 " ITCM : 0x%08lx - 0x%08lx (%4ld kB)\n" 653 " ITCM : 0x%08lx - 0x%08lx (%4ld kB)\n"
654#endif 654#endif
655 " fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n" 655 " fixmap : 0x%08lx - 0x%08lx (%4ld kB)\n"
656#ifdef CONFIG_MMU
657 " DMA : 0x%08lx - 0x%08lx (%4ld MB)\n"
658#endif
659 " vmalloc : 0x%08lx - 0x%08lx (%4ld MB)\n" 656 " vmalloc : 0x%08lx - 0x%08lx (%4ld MB)\n"
660 " lowmem : 0x%08lx - 0x%08lx (%4ld MB)\n" 657 " lowmem : 0x%08lx - 0x%08lx (%4ld MB)\n"
661#ifdef CONFIG_HIGHMEM 658#ifdef CONFIG_HIGHMEM
@@ -674,9 +671,6 @@ void __init mem_init(void)
674 MLK(ITCM_OFFSET, (unsigned long) itcm_end), 671 MLK(ITCM_OFFSET, (unsigned long) itcm_end),
675#endif 672#endif
676 MLK(FIXADDR_START, FIXADDR_TOP), 673 MLK(FIXADDR_START, FIXADDR_TOP),
677#ifdef CONFIG_MMU
678 MLM(CONSISTENT_BASE, CONSISTENT_END),
679#endif
680 MLM(VMALLOC_START, VMALLOC_END), 674 MLM(VMALLOC_START, VMALLOC_END),
681 MLM(PAGE_OFFSET, (unsigned long)high_memory), 675 MLM(PAGE_OFFSET, (unsigned long)high_memory),
682#ifdef CONFIG_HIGHMEM 676#ifdef CONFIG_HIGHMEM
@@ -699,9 +693,6 @@ void __init mem_init(void)
699 * be detected at build time already. 693 * be detected at build time already.
700 */ 694 */
701#ifdef CONFIG_MMU 695#ifdef CONFIG_MMU
702 BUILD_BUG_ON(VMALLOC_END > CONSISTENT_BASE);
703 BUG_ON(VMALLOC_END > CONSISTENT_BASE);
704
705 BUILD_BUG_ON(TASK_SIZE > MODULES_VADDR); 696 BUILD_BUG_ON(TASK_SIZE > MODULES_VADDR);
706 BUG_ON(TASK_SIZE > MODULES_VADDR); 697 BUG_ON(TASK_SIZE > MODULES_VADDR);
707#endif 698#endif