1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright (c) 2014 The Linux Foundation
5 #include <linux/dma-mapping.h>
6 #include <linux/slab.h>
7 #include <linux/vmalloc.h>
9 struct page
**dma_common_find_pages(void *cpu_addr
)
11 struct vm_struct
*area
= find_vm_area(cpu_addr
);
13 if (!area
|| area
->flags
!= VM_DMA_COHERENT
)
19 * Remaps an array of PAGE_SIZE pages into another vm_area.
20 * Cannot be used in non-sleeping contexts
22 void *dma_common_pages_remap(struct page
**pages
, size_t size
,
23 pgprot_t prot
, const void *caller
)
27 vaddr
= vmap(pages
, size
>> PAGE_SHIFT
, VM_DMA_COHERENT
, prot
);
29 find_vm_area(vaddr
)->pages
= pages
;
34 * Remaps an allocated contiguous region into another vm_area.
35 * Cannot be used in non-sleeping contexts
37 void *dma_common_contiguous_remap(struct page
*page
, size_t size
,
38 pgprot_t prot
, const void *caller
)
40 int count
= size
>> PAGE_SHIFT
;
45 pages
= kmalloc_array(count
, sizeof(struct page
*), GFP_KERNEL
);
48 for (i
= 0; i
< count
; i
++)
49 pages
[i
] = nth_page(page
, i
);
50 vaddr
= vmap(pages
, count
, VM_DMA_COHERENT
, prot
);
57 * Unmaps a range previously mapped by dma_common_*_remap
59 void dma_common_free_remap(void *cpu_addr
, size_t size
)
61 struct vm_struct
*area
= find_vm_area(cpu_addr
);
63 if (!area
|| area
->flags
!= VM_DMA_COHERENT
) {
64 WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr
);
68 unmap_kernel_range((unsigned long)cpu_addr
, PAGE_ALIGN(size
));