arm64: Enable CMA

arm64 bit targets need the features CMA provides. Add the appropriate
hooks, header files, and Kconfig to allow this to happen.

Cc: Will Deacon <will.deacon@arm.com>
Cc: Marek Szyprowski <m.szyprowski@samsung.com>
Signed-off-by: Laura Abbott <lauraa@codeaurora.org>
Signed-off-by: Catalin Marinas <catalin.marinas@arm.com>
This commit is contained in:
Laura Abbott 2013-12-12 19:28:33 +00:00 committed by Catalin Marinas
parent c666e8d5ca
commit 6ac2104deb
4 changed files with 56 additions and 2 deletions

View File

@ -27,6 +27,7 @@ config ARM64
select HAVE_DEBUG_KMEMLEAK
select HAVE_DMA_API_DEBUG
select HAVE_DMA_ATTRS
select HAVE_DMA_CONTIGUOUS
select HAVE_EFFICIENT_UNALIGNED_ACCESS
select HAVE_GENERIC_DMA_COHERENT
select HAVE_HW_BREAKPOINT if PERF_EVENTS

View File

@ -0,0 +1,29 @@
/*
* Copyright (c) 2013, The Linux Foundation. All rights reserved.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 and
* only version 2 as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#ifndef _ASM_DMA_CONTIGUOUS_H
#define _ASM_DMA_CONTIGUOUS_H
#ifdef __KERNEL__
#ifdef CONFIG_DMA_CMA
#include <linux/types.h>
#include <asm-generic/dma-contiguous.h>
static inline void
dma_contiguous_early_fixup(phys_addr_t base, unsigned long size) { }
#endif
#endif
#endif

View File

@ -21,6 +21,7 @@
#include <linux/export.h>
#include <linux/slab.h>
#include <linux/dma-mapping.h>
#include <linux/dma-contiguous.h>
#include <linux/vmalloc.h>
#include <linux/swiotlb.h>
@ -41,7 +42,19 @@ static void *arm64_swiotlb_alloc_coherent(struct device *dev, size_t size,
if (IS_ENABLED(CONFIG_ZONE_DMA32) &&
dev->coherent_dma_mask <= DMA_BIT_MASK(32))
flags |= GFP_DMA32;
return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
if (IS_ENABLED(CONFIG_DMA_CMA)) {
struct page *page;
page = dma_alloc_from_contiguous(dev, size >> PAGE_SHIFT,
get_order(size));
if (!page)
return NULL;
*dma_handle = phys_to_dma(dev, page_to_phys(page));
return page_address(page);
} else {
return swiotlb_alloc_coherent(dev, size, dma_handle, flags);
}
}
static void arm64_swiotlb_free_coherent(struct device *dev, size_t size,
@ -53,7 +66,15 @@ static void arm64_swiotlb_free_coherent(struct device *dev, size_t size,
return;
}
swiotlb_free_coherent(dev, size, vaddr, dma_handle);
if (IS_ENABLED(CONFIG_DMA_CMA)) {
phys_addr_t paddr = dma_to_phys(dev, dma_handle);
dma_release_from_contiguous(dev,
phys_to_page(paddr),
size >> PAGE_SHIFT);
} else {
swiotlb_free_coherent(dev, size, vaddr, dma_handle);
}
}
static struct dma_map_ops arm64_swiotlb_dma_ops = {

View File

@ -30,6 +30,7 @@
#include <linux/memblock.h>
#include <linux/sort.h>
#include <linux/of_fdt.h>
#include <linux/dma-contiguous.h>
#include <asm/sections.h>
#include <asm/setup.h>
@ -159,6 +160,8 @@ void __init arm64_memblock_init(void)
memblock_reserve(base, size);
}
dma_contiguous_reserve(0);
memblock_allow_resize();
memblock_dump_all();
}