Line data Source code
1 : // SPDX-License-Identifier: GPL-2.0 2 : /* 3 : * Copyright (c) 2014 The Linux Foundation 4 : */ 5 : #include <linux/dma-map-ops.h> 6 : #include <linux/slab.h> 7 : #include <linux/vmalloc.h> 8 : 9 0 : struct page **dma_common_find_pages(void *cpu_addr) 10 : { 11 0 : struct vm_struct *area = find_vm_area(cpu_addr); 12 : 13 0 : if (!area || area->flags != VM_DMA_COHERENT) 14 : return NULL; 15 0 : return area->pages; 16 : } 17 : 18 : /* 19 : * Remaps an array of PAGE_SIZE pages into another vm_area. 20 : * Cannot be used in non-sleeping contexts 21 : */ 22 0 : void *dma_common_pages_remap(struct page **pages, size_t size, 23 : pgprot_t prot, const void *caller) 24 : { 25 : void *vaddr; 26 : 27 0 : vaddr = vmap(pages, PAGE_ALIGN(size) >> PAGE_SHIFT, 28 : VM_DMA_COHERENT, prot); 29 0 : if (vaddr) 30 0 : find_vm_area(vaddr)->pages = pages; 31 0 : return vaddr; 32 : } 33 : 34 : /* 35 : * Remaps an allocated contiguous region into another vm_area. 36 : * Cannot be used in non-sleeping contexts 37 : */ 38 0 : void *dma_common_contiguous_remap(struct page *page, size_t size, 39 : pgprot_t prot, const void *caller) 40 : { 41 0 : int count = PAGE_ALIGN(size) >> PAGE_SHIFT; 42 : struct page **pages; 43 : void *vaddr; 44 : int i; 45 : 46 0 : pages = kvmalloc_array(count, sizeof(struct page *), GFP_KERNEL); 47 0 : if (!pages) 48 : return NULL; 49 0 : for (i = 0; i < count; i++) 50 0 : pages[i] = nth_page(page, i); 51 0 : vaddr = vmap(pages, count, VM_DMA_COHERENT, prot); 52 0 : kvfree(pages); 53 : 54 0 : return vaddr; 55 : } 56 : 57 : /* 58 : * Unmaps a range previously mapped by dma_common_*_remap 59 : */ 60 0 : void dma_common_free_remap(void *cpu_addr, size_t size) 61 : { 62 0 : struct vm_struct *area = find_vm_area(cpu_addr); 63 : 64 0 : if (!area || area->flags != VM_DMA_COHERENT) { 65 0 : WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr); 66 0 : return; 67 : } 68 : 69 0 : vunmap(cpu_addr); 70 : }