Merge branch 'for-linus' of git://git.linaro.org/people/mszyprowski/linux-dma-mapping
Pull CMA and ARM DMA-mapping updates from Marek Szyprowski: "These patches contain two major updates for DMA mapping subsystem (mainly for ARM architecture). First one is Contiguous Memory Allocator (CMA) which makes it possible for device drivers to allocate big contiguous chunks of memory after the system has booted. The main difference from the similar frameworks is the fact that CMA allows to transparently reuse the memory region reserved for the big chunk allocation as a system memory, so no memory is wasted when no big chunk is allocated. Once the alloc request is issued, the framework migrates system pages to create space for the required big chunk of physically contiguous memory. For more information one can refer to nice LWN articles: - 'A reworked contiguous memory allocator': http://lwn.net/Articles/447405/ - 'CMA and ARM': http://lwn.net/Articles/450286/ - 'A deep dive into CMA': http://lwn.net/Articles/486301/ - and the following thread with the patches and links to all previous versions: https://lkml.org/lkml/2012/4/3/204 The main client for this new framework is ARM DMA-mapping subsystem. The second part provides a complete redesign in ARM DMA-mapping subsystem. The core implementation has been changed to use common struct dma_map_ops based infrastructure with the recent updates for new dma attributes merged in v3.4-rc2. This allows to use more than one implementation of dma-mapping calls and change/select them on the struct device basis. The first client of this new infractructure is dmabounce implementation which has been completely cut out of the core, common code. The last patch of this redesign update introduces a new, experimental implementation of dma-mapping calls on top of generic IOMMU framework. This lets ARM sub-platform to transparently use IOMMU for DMA-mapping calls if one provides required IOMMU hardware. For more information please refer to the following thread: http://www.spinics.net/lists/arm-kernel/msg175729.html The last patch merges changes from both updates and provides a resolution for the conflicts which cannot be avoided when patches have been applied on the same files (mainly arch/arm/mm/dma-mapping.c)." Acked by Andrew Morton <akpm@linux-foundation.org>: "Yup, this one please. It's had much work, plenty of review and I think even Russell is happy with it." * 'for-linus' of git://git.linaro.org/people/mszyprowski/linux-dma-mapping: (28 commits) ARM: dma-mapping: use PMD size for section unmap cma: fix migration mode ARM: integrate CMA with DMA-mapping subsystem X86: integrate CMA with DMA-mapping subsystem drivers: add Contiguous Memory Allocator mm: trigger page reclaim in alloc_contig_range() to stabilise watermarks mm: extract reclaim code from __alloc_pages_direct_reclaim() mm: Serialize access to min_free_kbytes mm: page_isolation: MIGRATE_CMA isolation functions added mm: mmzone: MIGRATE_CMA migration type added mm: page_alloc: change fallbacks array handling mm: page_alloc: introduce alloc_contig_range() mm: compaction: export some of the functions mm: compaction: introduce isolate_freepages_range() mm: compaction: introduce map_pages() mm: compaction: introduce isolate_migratepages_range() mm: page_alloc: remove trailing whitespace ARM: dma-mapping: add support for IOMMU mapper ARM: dma-mapping: use alloc, mmap, free from dma_ops ARM: dma-mapping: remove redundant code and do the cleanup ... Conflicts: arch/x86/include/asm/dma-mapping.h
这个提交包含在:
文件差异内容过多而无法显示
加载差异
@@ -20,6 +20,7 @@
|
||||
#include <linux/highmem.h>
|
||||
#include <linux/gfp.h>
|
||||
#include <linux/memblock.h>
|
||||
#include <linux/dma-contiguous.h>
|
||||
|
||||
#include <asm/mach-types.h>
|
||||
#include <asm/memblock.h>
|
||||
@@ -226,6 +227,17 @@ static void __init arm_adjust_dma_zone(unsigned long *size, unsigned long *hole,
|
||||
}
|
||||
#endif
|
||||
|
||||
void __init setup_dma_zone(struct machine_desc *mdesc)
|
||||
{
|
||||
#ifdef CONFIG_ZONE_DMA
|
||||
if (mdesc->dma_zone_size) {
|
||||
arm_dma_zone_size = mdesc->dma_zone_size;
|
||||
arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1;
|
||||
} else
|
||||
arm_dma_limit = 0xffffffff;
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __init arm_bootmem_free(unsigned long min, unsigned long max_low,
|
||||
unsigned long max_high)
|
||||
{
|
||||
@@ -273,12 +285,9 @@ static void __init arm_bootmem_free(unsigned long min, unsigned long max_low,
|
||||
* Adjust the sizes according to any special requirements for
|
||||
* this machine type.
|
||||
*/
|
||||
if (arm_dma_zone_size) {
|
||||
if (arm_dma_zone_size)
|
||||
arm_adjust_dma_zone(zone_size, zhole_size,
|
||||
arm_dma_zone_size >> PAGE_SHIFT);
|
||||
arm_dma_limit = PHYS_OFFSET + arm_dma_zone_size - 1;
|
||||
} else
|
||||
arm_dma_limit = 0xffffffff;
|
||||
#endif
|
||||
|
||||
free_area_init_node(0, zone_size, min, zhole_size);
|
||||
@@ -364,6 +373,12 @@ void __init arm_memblock_init(struct meminfo *mi, struct machine_desc *mdesc)
|
||||
if (mdesc->reserve)
|
||||
mdesc->reserve();
|
||||
|
||||
/*
|
||||
* reserve memory for DMA contigouos allocations,
|
||||
* must come from DMA area inside low memory
|
||||
*/
|
||||
dma_contiguous_reserve(min(arm_dma_limit, arm_lowmem_limit));
|
||||
|
||||
arm_memblock_steal_permitted = false;
|
||||
memblock_allow_resize();
|
||||
memblock_dump_all();
|
||||
|
@@ -67,5 +67,8 @@ extern u32 arm_dma_limit;
|
||||
#define arm_dma_limit ((u32)~0)
|
||||
#endif
|
||||
|
||||
extern phys_addr_t arm_lowmem_limit;
|
||||
|
||||
void __init bootmem_init(void);
|
||||
void arm_mm_memblock_reserve(void);
|
||||
void dma_contiguous_remap(void);
|
||||
|
@@ -288,6 +288,11 @@ static struct mem_type mem_types[] = {
|
||||
PMD_SECT_UNCACHED | PMD_SECT_XN,
|
||||
.domain = DOMAIN_KERNEL,
|
||||
},
|
||||
[MT_MEMORY_DMA_READY] = {
|
||||
.prot_pte = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY,
|
||||
.prot_l1 = PMD_TYPE_TABLE,
|
||||
.domain = DOMAIN_KERNEL,
|
||||
},
|
||||
};
|
||||
|
||||
const struct mem_type *get_mem_type(unsigned int type)
|
||||
@@ -429,6 +434,7 @@ static void __init build_mem_type_table(void)
|
||||
if (arch_is_coherent() && cpu_is_xsc3()) {
|
||||
mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
|
||||
mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
|
||||
mem_types[MT_MEMORY_DMA_READY].prot_pte |= L_PTE_SHARED;
|
||||
mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
|
||||
mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED;
|
||||
}
|
||||
@@ -460,6 +466,7 @@ static void __init build_mem_type_table(void)
|
||||
mem_types[MT_DEVICE_CACHED].prot_pte |= L_PTE_SHARED;
|
||||
mem_types[MT_MEMORY].prot_sect |= PMD_SECT_S;
|
||||
mem_types[MT_MEMORY].prot_pte |= L_PTE_SHARED;
|
||||
mem_types[MT_MEMORY_DMA_READY].prot_pte |= L_PTE_SHARED;
|
||||
mem_types[MT_MEMORY_NONCACHED].prot_sect |= PMD_SECT_S;
|
||||
mem_types[MT_MEMORY_NONCACHED].prot_pte |= L_PTE_SHARED;
|
||||
}
|
||||
@@ -512,6 +519,7 @@ static void __init build_mem_type_table(void)
|
||||
mem_types[MT_HIGH_VECTORS].prot_l1 |= ecc_mask;
|
||||
mem_types[MT_MEMORY].prot_sect |= ecc_mask | cp->pmd;
|
||||
mem_types[MT_MEMORY].prot_pte |= kern_pgprot;
|
||||
mem_types[MT_MEMORY_DMA_READY].prot_pte |= kern_pgprot;
|
||||
mem_types[MT_MEMORY_NONCACHED].prot_sect |= ecc_mask;
|
||||
mem_types[MT_ROM].prot_sect |= cp->pmd;
|
||||
|
||||
@@ -596,7 +604,7 @@ static void __init alloc_init_section(pud_t *pud, unsigned long addr,
|
||||
* L1 entries, whereas PGDs refer to a group of L1 entries making
|
||||
* up one logical pointer to an L2 table.
|
||||
*/
|
||||
if (((addr | end | phys) & ~SECTION_MASK) == 0) {
|
||||
if (type->prot_sect && ((addr | end | phys) & ~SECTION_MASK) == 0) {
|
||||
pmd_t *p = pmd;
|
||||
|
||||
#ifndef CONFIG_ARM_LPAE
|
||||
@@ -814,7 +822,7 @@ static int __init early_vmalloc(char *arg)
|
||||
}
|
||||
early_param("vmalloc", early_vmalloc);
|
||||
|
||||
static phys_addr_t lowmem_limit __initdata = 0;
|
||||
phys_addr_t arm_lowmem_limit __initdata = 0;
|
||||
|
||||
void __init sanity_check_meminfo(void)
|
||||
{
|
||||
@@ -897,8 +905,8 @@ void __init sanity_check_meminfo(void)
|
||||
bank->size = newsize;
|
||||
}
|
||||
#endif
|
||||
if (!bank->highmem && bank->start + bank->size > lowmem_limit)
|
||||
lowmem_limit = bank->start + bank->size;
|
||||
if (!bank->highmem && bank->start + bank->size > arm_lowmem_limit)
|
||||
arm_lowmem_limit = bank->start + bank->size;
|
||||
|
||||
j++;
|
||||
}
|
||||
@@ -923,8 +931,8 @@ void __init sanity_check_meminfo(void)
|
||||
}
|
||||
#endif
|
||||
meminfo.nr_banks = j;
|
||||
high_memory = __va(lowmem_limit - 1) + 1;
|
||||
memblock_set_current_limit(lowmem_limit);
|
||||
high_memory = __va(arm_lowmem_limit - 1) + 1;
|
||||
memblock_set_current_limit(arm_lowmem_limit);
|
||||
}
|
||||
|
||||
static inline void prepare_page_table(void)
|
||||
@@ -949,8 +957,8 @@ static inline void prepare_page_table(void)
|
||||
* Find the end of the first block of lowmem.
|
||||
*/
|
||||
end = memblock.memory.regions[0].base + memblock.memory.regions[0].size;
|
||||
if (end >= lowmem_limit)
|
||||
end = lowmem_limit;
|
||||
if (end >= arm_lowmem_limit)
|
||||
end = arm_lowmem_limit;
|
||||
|
||||
/*
|
||||
* Clear out all the kernel space mappings, except for the first
|
||||
@@ -1093,8 +1101,8 @@ static void __init map_lowmem(void)
|
||||
phys_addr_t end = start + reg->size;
|
||||
struct map_desc map;
|
||||
|
||||
if (end > lowmem_limit)
|
||||
end = lowmem_limit;
|
||||
if (end > arm_lowmem_limit)
|
||||
end = arm_lowmem_limit;
|
||||
if (start >= end)
|
||||
break;
|
||||
|
||||
@@ -1115,11 +1123,12 @@ void __init paging_init(struct machine_desc *mdesc)
|
||||
{
|
||||
void *zero_page;
|
||||
|
||||
memblock_set_current_limit(lowmem_limit);
|
||||
memblock_set_current_limit(arm_lowmem_limit);
|
||||
|
||||
build_mem_type_table();
|
||||
prepare_page_table();
|
||||
map_lowmem();
|
||||
dma_contiguous_remap();
|
||||
devicemaps_init(mdesc);
|
||||
kmap_init();
|
||||
|
||||
|
@@ -17,7 +17,7 @@ struct arm_vmregion {
|
||||
struct list_head vm_list;
|
||||
unsigned long vm_start;
|
||||
unsigned long vm_end;
|
||||
struct page *vm_pages;
|
||||
void *priv;
|
||||
int vm_active;
|
||||
const void *caller;
|
||||
};
|
||||
|
在新工单中引用
屏蔽一个用户