diff options
| author | Arnd Bergmann <arnd@arndb.de> | 2011-10-08 21:07:42 +0200 | 
|---|---|---|
| committer | Arnd Bergmann <arnd@arndb.de> | 2011-10-08 21:07:42 +0200 | 
| commit | 71f2c153755442c05d15cd025484f676a5f3541f (patch) | |
| tree | fe48af6ddc33da7a0aaf1a16ed9feeafa4a8e1e1 /arch/arm/mm/dma-mapping.c | |
| parent | 8efc59ad6764ade520012cb192cd484e5191cd9c (diff) | |
| parent | c825dda905bac330c2da7fabdf5c0ac28758b3cd (diff) | |
| download | olio-linux-3.10-71f2c153755442c05d15cd025484f676a5f3541f.tar.xz olio-linux-3.10-71f2c153755442c05d15cd025484f676a5f3541f.zip  | |
Merge branch 'depends/rmk/devel-stable' into next/cleanup
Diffstat (limited to 'arch/arm/mm/dma-mapping.c')
| -rw-r--r-- | arch/arm/mm/dma-mapping.c | 45 | 
1 files changed, 34 insertions, 11 deletions
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c index 0a0a1e7c20d..50be842e89f 100644 --- a/arch/arm/mm/dma-mapping.c +++ b/arch/arm/mm/dma-mapping.c @@ -18,12 +18,14 @@  #include <linux/device.h>  #include <linux/dma-mapping.h>  #include <linux/highmem.h> +#include <linux/slab.h>  #include <asm/memory.h>  #include <asm/highmem.h>  #include <asm/cacheflush.h>  #include <asm/tlbflush.h>  #include <asm/sizes.h> +#include <asm/mach/arch.h>  #include "mm.h" @@ -117,26 +119,37 @@ static void __dma_free_buffer(struct page *page, size_t size)  }  #ifdef CONFIG_MMU -/* Sanity check size */ -#if (CONSISTENT_DMA_SIZE % SZ_2M) -#error "CONSISTENT_DMA_SIZE must be multiple of 2MiB" -#endif -#define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - CONSISTENT_BASE) >> PAGE_SHIFT) -#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - CONSISTENT_BASE) >> PGDIR_SHIFT) -#define NUM_CONSISTENT_PTES (CONSISTENT_DMA_SIZE >> PGDIR_SHIFT) + +#define CONSISTENT_OFFSET(x)	(((unsigned long)(x) - consistent_base) >> PAGE_SHIFT) +#define CONSISTENT_PTE_INDEX(x) (((unsigned long)(x) - consistent_base) >> PGDIR_SHIFT)  /*   * These are the page tables (2MB each) covering uncached, DMA consistent allocations   */ -static pte_t *consistent_pte[NUM_CONSISTENT_PTES]; +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_start	= CONSISTENT_BASE,  	.vm_end		= CONSISTENT_END,  }; @@ -155,7 +168,17 @@ static int __init consistent_init(void)  	pmd_t *pmd;  	pte_t *pte;  	int i = 0; -	u32 base = CONSISTENT_BASE; +	unsigned long base = consistent_base; +	unsigned long num_ptes = (CONSISTENT_END - base) >> PGDIR_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); @@ -198,7 +221,7 @@ __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot)  	size_t align;  	int bit; -	if (!consistent_pte[0]) { +	if (!consistent_pte) {  		printk(KERN_ERR "%s: not initialised\n", __func__);  		dump_stack();  		return NULL;  |