Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9bc9333e authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "ARM: dma-mapping: Allow highmem pages to not have a mapping"

parents 6c1335bb 172b6f07
Loading
Loading
Loading
Loading
+45 −23
Original line number Diff line number Diff line
@@ -375,10 +375,10 @@ __dma_alloc_remap(struct page *page, size_t size, gfp_t gfp, pgprot_t prot,
			prot, caller);
}

static void __dma_free_remap(void *cpu_addr, size_t size)
static void __dma_free_remap(void *cpu_addr, size_t size, bool no_warn)
{
	dma_common_free_remap(cpu_addr, size,
			VM_ARM_DMA_CONSISTENT | VM_USERMAP, false);
			VM_ARM_DMA_CONSISTENT | VM_USERMAP, no_warn);
}

#define DEFAULT_DMA_COHERENT_POOL_SIZE	SZ_256K
@@ -527,21 +527,39 @@ static int __dma_update_pte(pte_t *pte, pgtable_t token, unsigned long addr,
	return 0;
}

static void __dma_remap(struct page *page, size_t size, pgprot_t prot)
static int __dma_clear_pte(pte_t *pte, pgtable_t token, unsigned long addr,
			    void *data)
{
	pte_clear(&init_mm, addr, pte);
	return 0;
}

static void __dma_remap(struct page *page, size_t size, pgprot_t prot,
			bool want_vaddr)
{
	unsigned long start = (unsigned long) page_address(page);
	unsigned end = start + size;
	int (*func)(pte_t *pte, pgtable_t token, unsigned long addr,
			    void *data);

	apply_to_page_range(&init_mm, start, size, __dma_update_pte, &prot);
	if (!want_vaddr)
		func = __dma_clear_pte;
	else
		func = __dma_update_pte;

	apply_to_page_range(&init_mm, start, size, func, &prot);
	mb(); /*Ensure pte's are updated */
	flush_tlb_kernel_range(start, end);
}


#define NO_KERNEL_MAPPING_DUMMY	0x2222
static void *__alloc_remap_buffer(struct device *dev, size_t size, gfp_t gfp,
				 pgprot_t prot, struct page **ret_page,
				 const void *caller, bool want_vaddr)
{
	struct page *page;
	void *ptr = NULL;
	void *ptr = (void *)NO_KERNEL_MAPPING_DUMMY;
	/*
	 * __alloc_remap_buffer is only called when the device is
	 * non-coherent
@@ -620,21 +638,27 @@ static void *__alloc_from_contiguous(struct device *dev, size_t size,
	if (!(skip_cpu_sync  && skip_zeroing))
		__dma_clear_buffer(page, size, skip_zeroing, coherent_flag);

	if (!want_vaddr)
		goto out;

	if (PageHighMem(page)) {
		ptr = __dma_alloc_remap(page, size, GFP_KERNEL, prot, caller);
		if (!want_vaddr) {
			/*
			 * Something non-NULL needs to be returned here. Give
			 * back a dummy address that is unmapped to catch
			 * clients trying to use the address incorrectly
			 */
			ptr = (void *)NO_KERNEL_MAPPING_DUMMY;
		} else {
			ptr = __dma_alloc_remap(page, size, GFP_KERNEL, prot,
						caller);
			if (!ptr) {
				dma_release_from_contiguous(dev, page, count);
				return NULL;
			}
		}
	} else {
		__dma_remap(page, size, prot);
		__dma_remap(page, size, prot, want_vaddr);
		ptr = page_address(page);
	}

 out:
	*ret_page = page;
	return ptr;
}
@@ -642,12 +666,10 @@ static void *__alloc_from_contiguous(struct device *dev, size_t size,
static void __free_from_contiguous(struct device *dev, struct page *page,
				   void *cpu_addr, size_t size, bool want_vaddr)
{
	if (want_vaddr) {
	if (PageHighMem(page))
			__dma_free_remap(cpu_addr, size);
		__dma_free_remap(cpu_addr, size, true);
	else
			__dma_remap(page, size, PAGE_KERNEL);
	}
		__dma_remap(page, size, PAGE_KERNEL, true);
	dma_release_from_contiguous(dev, page, size >> PAGE_SHIFT);
}

@@ -672,7 +694,7 @@ static inline pgprot_t __get_dma_pgprot(unsigned long attrs, pgprot_t prot)
					wv, scs, sz, coherent_flag) NULL
#define __free_from_pool(cpu_addr, size)			do { } while (0)
#define __free_from_contiguous(dev, page, cpu_addr, size, wv)	do { } while (0)
#define __dma_free_remap(cpu_addr, size)			do { } while (0)
#define __dma_free_remap(cpu_addr, size, w)			do { } while (0)

#endif	/* CONFIG_MMU */

@@ -753,7 +775,7 @@ static void *remap_allocator_alloc(struct arm_dma_alloc_args *args,
static void remap_allocator_free(struct arm_dma_free_args *args)
{
	if (args->want_vaddr)
		__dma_free_remap(args->cpu_addr, args->size);
		__dma_free_remap(args->cpu_addr, args->size, false);

	__dma_free_buffer(args->page, args->size);
}
@@ -842,7 +864,7 @@ static void *__dma_alloc(struct device *dev, size_t size, dma_addr_t *handle,
		kfree(buf);
	}

	return args.want_vaddr ? addr : page;
	return  addr;
}

/*