Skip to content

Commit

Permalink
MIPS: DMA: Add cma support
Browse files Browse the repository at this point in the history
Adds cma support to the MIPS architecture.

cma uses memblock. However, mips uses bootmem.
bootmem is informed about any regions reserved by memblock

dma api is modified to use cma reserved memory regions when available

Tested using cma_test. cma_test is a simple driver that assigns blocks
of memory from cma reserved sections.

Signed-off-by: Zubair Lutfullah Kakakhel <Zubair.Kakakhel@imgtec.com>
Acked-by: Michal Nazarewicz <mina86@mina86.com>
Cc: catalin.marinas@arm.com
Cc: will.deacon@arm.com
Cc: tglx@linutronix.de
Cc: mingo@redhat.com
Cc: hpa@zytor.com
Cc: arnd@arndb.de
Cc: gregkh@linuxfoundation.org
Cc: m.szyprowski@samsung.com
Cc: x86@kernel.org
Cc: linux-arm-kernel@lists.infradead.org
Cc: linux-kernel@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: linux-arch@vger.kernel.org
Patchwork: https://patchwork.linux-mips.org/patch/7360/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
  • Loading branch information
Zubair Lutfullah Kakakhel authored and Ralf Baechle committed Sep 22, 2014
1 parent 8057b30 commit f464938
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 12 deletions.
1 change: 1 addition & 0 deletions arch/mips/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ config MIPS
select GENERIC_ATOMIC64 if !64BIT
select ARCH_HAS_ATOMIC64_DEC_IF_POSITIVE
select HAVE_DMA_ATTRS
select HAVE_DMA_CONTIGUOUS
select HAVE_DMA_API_DEBUG
select GENERIC_IRQ_PROBE
select GENERIC_IRQ_SHOW
Expand Down
1 change: 1 addition & 0 deletions arch/mips/include/asm/Kbuild
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# MIPS headers
generic-y += cputime.h
generic-y += current.h
generic-y += dma-contiguous.h
generic-y += emergency-restart.h
generic-y += hash.h
generic-y += local64.h
Expand Down
9 changes: 9 additions & 0 deletions arch/mips/kernel/setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
#include <linux/debugfs.h>
#include <linux/kexec.h>
#include <linux/sizes.h>
#include <linux/device.h>
#include <linux/dma-contiguous.h>

#include <asm/addrspace.h>
#include <asm/bootinfo.h>
Expand Down Expand Up @@ -476,6 +478,7 @@ static void __init bootmem_init(void)
* o bootmem_init()
* o sparse_init()
* o paging_init()
* o dma_continguous_reserve()
*
* At this stage the bootmem allocator is ready to use.
*
Expand Down Expand Up @@ -609,6 +612,7 @@ static void __init request_crashkernel(struct resource *res)

static void __init arch_mem_init(char **cmdline_p)
{
struct memblock_region *reg;
extern void plat_mem_setup(void);

/* call board setup routine */
Expand Down Expand Up @@ -675,6 +679,11 @@ static void __init arch_mem_init(char **cmdline_p)
sparse_init();
plat_swiotlb_setup();
paging_init();

dma_contiguous_reserve(PFN_PHYS(max_low_pfn));
/* Tell bootmem about cma reserved memblock section */
for_each_memblock(reserved, reg)
reserve_bootmem(reg->base, reg->size, BOOTMEM_DEFAULT);
}

static void __init resource_init(void)
Expand Down
37 changes: 25 additions & 12 deletions arch/mips/mm/dma-default.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <linux/string.h>
#include <linux/gfp.h>
#include <linux/highmem.h>
#include <linux/dma-contiguous.h>

#include <asm/cache.h>
#include <asm/cpu-type.h>
Expand Down Expand Up @@ -128,23 +129,30 @@ static void *mips_dma_alloc_coherent(struct device *dev, size_t size,
dma_addr_t * dma_handle, gfp_t gfp, struct dma_attrs *attrs)
{
void *ret;
struct page *page = NULL;
unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;

if (dma_alloc_from_coherent(dev, size, dma_handle, &ret))
return ret;

gfp = massage_gfp_flags(dev, gfp);

ret = (void *) __get_free_pages(gfp, get_order(size));

if (ret) {
memset(ret, 0, size);
*dma_handle = plat_map_dma_mem(dev, ret, size);

if (!plat_device_is_coherent(dev)) {
dma_cache_wback_inv((unsigned long) ret, size);
if (!hw_coherentio)
ret = UNCAC_ADDR(ret);
}
if (IS_ENABLED(CONFIG_DMA_CMA) && !(gfp & GFP_ATOMIC))
page = dma_alloc_from_contiguous(dev,
count, get_order(size));
if (!page)
page = alloc_pages(gfp, get_order(size));

if (!page)
return NULL;

ret = page_address(page);
memset(ret, 0, size);
*dma_handle = plat_map_dma_mem(dev, ret, size);
if (!plat_device_is_coherent(dev)) {
dma_cache_wback_inv((unsigned long) ret, size);
if (!hw_coherentio)
ret = UNCAC_ADDR(ret);
}

return ret;
Expand All @@ -164,6 +172,8 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
{
unsigned long addr = (unsigned long) vaddr;
int order = get_order(size);
unsigned int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
struct page *page = NULL;

if (dma_release_from_coherent(dev, order, vaddr))
return;
Expand All @@ -173,7 +183,10 @@ static void mips_dma_free_coherent(struct device *dev, size_t size, void *vaddr,
if (!plat_device_is_coherent(dev) && !hw_coherentio)
addr = CAC_ADDR(addr);

free_pages(addr, get_order(size));
page = virt_to_page((void *) addr);

if (!dma_release_from_contiguous(dev, page, count))
__free_pages(page, get_order(size));
}

static inline void __dma_sync_virtual(void *addr, size_t size,
Expand Down

0 comments on commit f464938

Please sign in to comment.