| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410 | 
							- /*
 
-  *  linux/arch/arm/mm/dma-mapping.c
 
-  *
 
-  *  Copyright (C) 2000-2004 Russell King
 
-  *
 
-  * This program is free software; you can redistribute it and/or modify
 
-  * it under the terms of the GNU General Public License version 2 as
 
-  * published by the Free Software Foundation.
 
-  *
 
-  *  DMA uncached mapping support.
 
-  */
 
- #include <linux/module.h>
 
- #include <linux/mm.h>
 
- #include <linux/gfp.h>
 
- #include <linux/errno.h>
 
- #include <linux/list.h>
 
- #include <linux/init.h>
 
- #include <linux/device.h>
 
- #include <linux/dma-mapping.h>
 
- #include <linux/dma-contiguous.h>
 
- #include <linux/highmem.h>
 
- #include <linux/memblock.h>
 
- #include <linux/slab.h>
 
- #include <linux/iommu.h>
 
- #include <linux/io.h>
 
- #include <linux/vmalloc.h>
 
- #include <linux/sizes.h>
 
- #include <asm/memory.h>
 
- #include <asm/highmem.h>
 
- #include <asm/cacheflush.h>
 
- #include <asm/tlbflush.h>
 
- #include <asm/mach/arch.h>
 
- #include <asm/dma-iommu.h>
 
- #include <asm/mach/map.h>
 
- #include <asm/system_info.h>
 
- #include <asm/dma-contiguous.h>
 
- #include "mm.h"
 
- /*
 
-  * The DMA API is built upon the notion of "buffer ownership".  A buffer
 
-  * is either exclusively owned by the CPU (and therefore may be accessed
 
-  * by it) or exclusively owned by the DMA device.  These helper functions
 
-  * represent the transitions between these two ownership states.
 
-  *
 
-  * Note, however, that on later ARMs, this notion does not work due to
 
-  * speculative prefetches.  We model our approach on the assumption that
 
-  * the CPU does do speculative prefetches, which means we clean caches
 
-  * before transfers and delay cache invalidation until transfer completion.
 
-  *
 
-  */
 
- static void __dma_page_cpu_to_dev(struct page *, unsigned long,
 
- 		size_t, enum dma_data_direction);
 
- static void __dma_page_dev_to_cpu(struct page *, unsigned long,
 
- 		size_t, enum dma_data_direction);
 
- /**
 
-  * arm_dma_map_page - map a portion of a page for streaming DMA
 
-  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
 
-  * @page: page that buffer resides in
 
-  * @offset: offset into page for start of buffer
 
-  * @size: size of buffer to map
 
-  * @dir: DMA transfer direction
 
-  *
 
-  * Ensure that any data held in the cache is appropriately discarded
 
-  * or written back.
 
-  *
 
-  * The device owns this memory once this call has completed.  The CPU
 
-  * can regain ownership by calling dma_unmap_page().
 
-  */
 
- static dma_addr_t arm_dma_map_page(struct device *dev, struct page *page,
 
- 	     unsigned long offset, size_t size, enum dma_data_direction dir,
 
- 	     struct dma_attrs *attrs)
 
- {
 
- 	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 
- 		__dma_page_cpu_to_dev(page, offset, size, dir);
 
- 	return pfn_to_dma(dev, page_to_pfn(page)) + offset;
 
- }
 
- static dma_addr_t arm_coherent_dma_map_page(struct device *dev, struct page *page,
 
- 	     unsigned long offset, size_t size, enum dma_data_direction dir,
 
- 	     struct dma_attrs *attrs)
 
- {
 
- 	return pfn_to_dma(dev, page_to_pfn(page)) + offset;
 
- }
 
- /**
 
-  * arm_dma_unmap_page - unmap a buffer previously mapped through dma_map_page()
 
-  * @dev: valid struct device pointer, or NULL for ISA and EISA-like devices
 
-  * @handle: DMA address of buffer
 
-  * @size: size of buffer (same as passed to dma_map_page)
 
-  * @dir: DMA transfer direction (same as passed to dma_map_page)
 
-  *
 
-  * Unmap a page streaming mode DMA translation.  The handle and size
 
-  * must match what was provided in the previous dma_map_page() call.
 
-  * All other usages are undefined.
 
-  *
 
-  * After this call, reads by the CPU to the buffer are guaranteed to see
 
-  * whatever the device wrote there.
 
-  */
 
- static void arm_dma_unmap_page(struct device *dev, dma_addr_t handle,
 
- 		size_t size, enum dma_data_direction dir,
 
- 		struct dma_attrs *attrs)
 
- {
 
- 	if (!dma_get_attr(DMA_ATTR_SKIP_CPU_SYNC, attrs))
 
- 		__dma_page_dev_to_cpu(pfn_to_page(dma_to_pfn(dev, handle)),
 
- 				      handle & ~PAGE_MASK, size, dir);
 
- }
 
- static void arm_dma_sync_single_for_cpu(struct device *dev,
 
- 		dma_addr_t handle, size_t size, enum dma_data_direction dir)
 
- {
 
- 	unsigned int offset = handle & (PAGE_SIZE - 1);
 
- 	struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
 
- 	__dma_page_dev_to_cpu(page, offset, size, dir);
 
- }
 
- static void arm_dma_sync_single_for_device(struct device *dev,
 
- 		dma_addr_t handle, size_t size, enum dma_data_direction dir)
 
- {
 
- 	unsigned int offset = handle & (PAGE_SIZE - 1);
 
- 	struct page *page = pfn_to_page(dma_to_pfn(dev, handle-offset));
 
- 	__dma_page_cpu_to_dev(page, offset, size, dir);
 
- }
 
- struct dma_map_ops arm_dma_ops = {
 
- 	.alloc			= arm_dma_alloc,
 
- 	.free			= arm_dma_free,
 
- 	.mmap			= arm_dma_mmap,
 
- 	.get_sgtable		= arm_dma_get_sgtable,
 
- 	.map_page		= arm_dma_map_page,
 
- 	.unmap_page		= arm_dma_unmap_page,
 
- 	.map_sg			= arm_dma_map_sg,
 
- 	.unmap_sg		= arm_dma_unmap_sg,
 
- 	.sync_single_for_cpu	= arm_dma_sync_single_for_cpu,
 
- 	.sync_single_for_device	= arm_dma_sync_single_for_device,
 
- 	.sync_sg_for_cpu	= arm_dma_sync_sg_for_cpu,
 
- 	.sync_sg_for_device	= arm_dma_sync_sg_for_device,
 
- 	.set_dma_mask		= arm_dma_set_mask,
 
- };
 
- EXPORT_SYMBOL(arm_dma_ops);
 
- static void *arm_coherent_dma_alloc(struct device *dev, size_t size,
 
- 	dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs);
 
- static void arm_coherent_dma_free(struct device *dev, size_t size, void *cpu_addr,
 
- 				  dma_addr_t handle, struct dma_attrs *attrs);
 
- struct dma_map_ops arm_coherent_dma_ops = {
 
- 	.alloc			= arm_coherent_dma_alloc,
 
- 	.free			= arm_coherent_dma_free,
 
- 	.mmap			= arm_dma_mmap,
 
- 	.get_sgtable		= arm_dma_get_sgtable,
 
- 	.map_page		= arm_coherent_dma_map_page,
 
- 	.map_sg			= arm_dma_map_sg,
 
- 	.set_dma_mask		= arm_dma_set_mask,
 
- };
 
- EXPORT_SYMBOL(arm_coherent_dma_ops);
 
- static u64 get_coherent_dma_mask(struct device *dev)
 
- {
 
- 	u64 mask = (u64)arm_dma_limit;
 
- 	if (dev) {
 
- 		mask = dev->coherent_dma_mask;
 
- 		/*
 
- 		 * Sanity check the DMA mask - it must be non-zero, and
 
- 		 * must be able to be satisfied by a DMA allocation.
 
- 		 */
 
- 		if (mask == 0) {
 
- 			dev_warn(dev, "coherent DMA mask is unset\n");
 
- 			return 0;
 
- 		}
 
- 		if ((~mask) & (u64)arm_dma_limit) {
 
- 			dev_warn(dev, "coherent DMA mask %#llx is smaller "
 
- 				 "than system GFP_DMA mask %#llx\n",
 
- 				 mask, (u64)arm_dma_limit);
 
- 			return 0;
 
- 		}
 
- 	}
 
- 	return mask;
 
- }
 
- static void __dma_clear_buffer(struct page *page, size_t size)
 
- {
 
- 	void *ptr;
 
- 	/*
 
- 	 * Ensure that the allocated pages are zeroed, and that any data
 
- 	 * lurking in the kernel direct-mapped region is invalidated.
 
- 	 */
 
- 	ptr = page_address(page);
 
- 	if (ptr) {
 
- 		memset(ptr, 0, size);
 
- 		dmac_flush_range(ptr, ptr + size);
 
- 		outer_flush_range(__pa(ptr), __pa(ptr) + size);
 
- 	}
 
- }
 
- /*
 
-  * Allocate a DMA buffer for 'dev' of size 'size' using the
 
-  * specified gfp mask.  Note that 'size' must be page aligned.
 
-  */
 
- static struct page *__dma_alloc_buffer(struct device *dev, size_t size, gfp_t gfp)
 
- {
 
- 	unsigned long order = get_order(size);
 
- 	struct page *page, *p, *e;
 
- 	page = alloc_pages(gfp, order);
 
- 	if (!page)
 
- 		return NULL;
 
- 	/*
 
- 	 * Now split the huge page and free the excess pages
 
- 	 */
 
- 	split_page(page, order);
 
- 	for (p = page + (size >> PAGE_SHIFT), e = page + (1 << order); p < e; p++)
 
- 		__free_page(p);
 
- 	__dma_clear_buffer(page, size);
 
- 	return page;
 
- }
 
- /*
 
-  * Free a DMA buffer.  'size' must be page aligned.
 
-  */
 
- static void __dma_free_buffer(struct page *page, size_t size)
 
- {
 
- 	struct page *e = page + (size >> PAGE_SHIFT);
 
- 	while (page < e) {
 
- 		__free_page(page);
 
- 		page++;
 
- 	}
 
- }
 
- #ifdef CONFIG_MMU
 
- #ifdef CONFIG_HUGETLB_PAGE
 
- #error ARM Coherent DMA allocator does not (yet) support huge TLB
 
- #endif
 
- static void *__alloc_from_contiguous(struct device *dev, size_t size,
 
- 				     pgprot_t prot, struct page **ret_page);
 
- static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp,
 
- 				 pgprot_t prot, struct page **ret_page,
 
- 				 const void *caller);
 
- static void *
 
- __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot,
 
- 	const void *caller)
 
- {
 
- 	struct vm_struct *area;
 
- 	unsigned long addr;
 
- 	/*
 
- 	 * DMA allocation can be mapped to user space, so lets
 
- 	 * set VM_USERMAP flags too.
 
- 	 */
 
- 	area = get_vm_area_caller(size, VM_ARM_DMA_CONSISTENT | VM_USERMAP,
 
- 				  caller);
 
- 	if (!area)
 
- 		return NULL;
 
- 	addr = (unsigned long)area->addr;
 
- 	area->phys_addr = __pfn_to_phys(page_to_pfn(page));
 
- 	if (ioremap_page_range(addr, addr + size, area->phys_addr, prot)) {
 
- 		vunmap((void *)addr);
 
- 		return NULL;
 
- 	}
 
- 	return (void *)addr;
 
- }
 
- static void __dma_free_remap(void *cpu_addr, size_t size)
 
- {
 
- 	unsigned int flags = VM_ARM_DMA_CONSISTENT | VM_USERMAP;
 
- 	struct vm_struct *area = find_vm_area(cpu_addr);
 
- 	if (!area || (area->flags & flags) != flags) {
 
- 		WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr);
 
- 		return;
 
- 	}
 
- 	unmap_kernel_range((unsigned long)cpu_addr, size);
 
- 	vunmap(cpu_addr);
 
- }
 
- #define DEFAULT_DMA_COHERENT_POOL_SIZE	SZ_256K
 
- struct dma_pool {
 
- 	size_t size;
 
- 	spinlock_t lock;
 
- 	unsigned long *bitmap;
 
- 	unsigned long nr_pages;
 
- 	void *vaddr;
 
- 	struct page **pages;
 
- };
 
- static struct dma_pool atomic_pool = {
 
- 	.size = DEFAULT_DMA_COHERENT_POOL_SIZE,
 
- };
 
- static int __init early_coherent_pool(char *p)
 
- {
 
- 	atomic_pool.size = memparse(p, &p);
 
- 	return 0;
 
- }
 
- early_param("coherent_pool", early_coherent_pool);
 
- void __init init_dma_coherent_pool_size(unsigned long size)
 
- {
 
- 	/*
 
- 	 * Catch any attempt to set the pool size too late.
 
- 	 */
 
- 	BUG_ON(atomic_pool.vaddr);
 
- 	/*
 
- 	 * Set architecture specific coherent pool size only if
 
- 	 * it has not been changed by kernel command line parameter.
 
- 	 */
 
- 	if (atomic_pool.size == DEFAULT_DMA_COHERENT_POOL_SIZE)
 
- 		atomic_pool.size = size;
 
- }
 
- /*
 
-  * Initialise the coherent pool for atomic allocations.
 
-  */
 
- static int __init atomic_pool_init(void)
 
- {
 
- 	struct dma_pool *pool = &atomic_pool;
 
- 	pgprot_t prot = pgprot_dmacoherent(pgprot_kernel);
 
- 	gfp_t gfp = GFP_KERNEL | GFP_DMA;
 
- 	unsigned long nr_pages = pool->size >> PAGE_SHIFT;
 
- 	unsigned long *bitmap;
 
- 	struct page *page;
 
- 	struct page **pages;
 
- 	void *ptr;
 
- 	int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
 
- 	bitmap = kzalloc(bitmap_size, GFP_KERNEL);
 
- 	if (!bitmap)
 
- 		goto no_bitmap;
 
- 	pages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
 
- 	if (!pages)
 
- 		goto no_pages;
 
- 	if (IS_ENABLED(CONFIG_CMA))
 
- 		ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page);
 
- 	else
 
- 		ptr = __alloc_remap_buffer(NULL, pool->size, gfp, prot, &page,
 
- 					   NULL);
 
- 	if (ptr) {
 
- 		int i;
 
- 		for (i = 0; i < nr_pages; i++)
 
- 			pages[i] = page + i;
 
- 		spin_lock_init(&pool->lock);
 
- 		pool->vaddr = ptr;
 
- 		pool->pages = pages;
 
- 		pool->bitmap = bitmap;
 
- 		pool->nr_pages = nr_pages;
 
- 		pr_info("DMA: preallocated %u KiB pool for atomic coherent allocations\n",
 
- 		       (unsigned)pool->size / 1024);
 
- 		return 0;
 
- 	}
 
- 	kfree(pages);
 
- no_pages:
 
- 	kfree(bitmap);
 
- no_bitmap:
 
- 	pr_err("DMA: failed to allocate %u KiB pool for atomic coherent allocation\n",
 
- 	       (unsigned)pool->size / 1024);
 
- 	return -ENOMEM;
 
- }
 
- /*
 
-  * CMA is activated by core_initcall, so we must be called after it.
 
-  */
 
- postcore_initcall(atomic_pool_init);
 
- struct dma_contig_early_reserve {
 
- 	phys_addr_t base;
 
- 	unsigned long size;
 
- };
 
- static struct dma_contig_early_reserve dma_mmu_remap[MAX_CMA_AREAS] __initdata;
 
- static int dma_mmu_remap_num __initdata;
 
- void __init dma_contiguous_early_fixup(phys_addr_t base, unsigned long size)
 
- {
 
- 	dma_mmu_remap[dma_mmu_remap_num].base = base;
 
- 	dma_mmu_remap[dma_mmu_remap_num].size = size;
 
- 	dma_mmu_remap_num++;
 
- }
 
- void __init dma_contiguous_remap(void)
 
- {
 
- 	int i;
 
- 	for (i = 0; i < dma_mmu_remap_num; i++) {
 
- 		phys_addr_t start = dma_mmu_remap[i].base;
 
- 		phys_addr_t end = start + dma_mmu_remap[i].size;
 
- 		struct map_desc map;
 
- 		unsigned long addr;
 
- 		if (end > arm_lowmem_limit)
 
- 			end = arm_lowmem_limit;
 
- 		if (start >= end)
 
 
  |