Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/kernel/dma/remap.c
29265 views
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
struct page **dma_common_find_pages(void *cpu_addr)
10
{
11
struct vm_struct *area = find_vm_area(cpu_addr);
12
13
if (!area || !(area->flags & VM_DMA_COHERENT))
14
return NULL;
15
WARN(area->flags != VM_DMA_COHERENT,
16
"unexpected flags in area: %p\n", cpu_addr);
17
return area->pages;
18
}
19
20
/*
21
* Remaps an array of PAGE_SIZE pages into another vm_area.
22
* Cannot be used in non-sleeping contexts
23
*/
24
void *dma_common_pages_remap(struct page **pages, size_t size,
25
pgprot_t prot, const void *caller)
26
{
27
void *vaddr;
28
29
vaddr = vmap(pages, PAGE_ALIGN(size) >> PAGE_SHIFT,
30
VM_DMA_COHERENT, prot);
31
if (vaddr)
32
find_vm_area(vaddr)->pages = pages;
33
return vaddr;
34
}
35
36
/*
37
* Remaps an allocated contiguous region into another vm_area.
38
* Cannot be used in non-sleeping contexts
39
*/
40
void *dma_common_contiguous_remap(struct page *page, size_t size,
41
pgprot_t prot, const void *caller)
42
{
43
int count = PAGE_ALIGN(size) >> PAGE_SHIFT;
44
struct page **pages;
45
void *vaddr;
46
int i;
47
48
pages = kvmalloc_array(count, sizeof(struct page *), GFP_KERNEL);
49
if (!pages)
50
return NULL;
51
for (i = 0; i < count; i++)
52
pages[i] = page++;
53
vaddr = vmap(pages, count, VM_DMA_COHERENT, prot);
54
kvfree(pages);
55
56
return vaddr;
57
}
58
59
/*
60
* Unmaps a range previously mapped by dma_common_*_remap
61
*/
62
void dma_common_free_remap(void *cpu_addr, size_t size)
63
{
64
struct vm_struct *area = find_vm_area(cpu_addr);
65
66
if (!area || !(area->flags & VM_DMA_COHERENT)) {
67
WARN(1, "trying to free invalid coherent area: %p\n", cpu_addr);
68
return;
69
}
70
71
vunmap(cpu_addr);
72
}
73
74