diff options
Diffstat (limited to 'kernel/dma/virt.c')
-rw-r--r-- | kernel/dma/virt.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/kernel/dma/virt.c b/kernel/dma/virt.c new file mode 100644 index 000000000000..631ddec4b60a --- /dev/null +++ b/kernel/dma/virt.c | |||
@@ -0,0 +1,59 @@ | |||
1 | // SPDX-License-Identifier: GPL-2.0 | ||
2 | /* | ||
3 | * DMA operations that map to virtual addresses without flushing memory. | ||
4 | */ | ||
5 | #include <linux/export.h> | ||
6 | #include <linux/mm.h> | ||
7 | #include <linux/dma-mapping.h> | ||
8 | #include <linux/scatterlist.h> | ||
9 | |||
10 | static void *dma_virt_alloc(struct device *dev, size_t size, | ||
11 | dma_addr_t *dma_handle, gfp_t gfp, | ||
12 | unsigned long attrs) | ||
13 | { | ||
14 | void *ret; | ||
15 | |||
16 | ret = (void *)__get_free_pages(gfp, get_order(size)); | ||
17 | if (ret) | ||
18 | *dma_handle = (uintptr_t)ret; | ||
19 | return ret; | ||
20 | } | ||
21 | |||
22 | static void dma_virt_free(struct device *dev, size_t size, | ||
23 | void *cpu_addr, dma_addr_t dma_addr, | ||
24 | unsigned long attrs) | ||
25 | { | ||
26 | free_pages((unsigned long)cpu_addr, get_order(size)); | ||
27 | } | ||
28 | |||
29 | static dma_addr_t dma_virt_map_page(struct device *dev, struct page *page, | ||
30 | unsigned long offset, size_t size, | ||
31 | enum dma_data_direction dir, | ||
32 | unsigned long attrs) | ||
33 | { | ||
34 | return (uintptr_t)(page_address(page) + offset); | ||
35 | } | ||
36 | |||
37 | static int dma_virt_map_sg(struct device *dev, struct scatterlist *sgl, | ||
38 | int nents, enum dma_data_direction dir, | ||
39 | unsigned long attrs) | ||
40 | { | ||
41 | int i; | ||
42 | struct scatterlist *sg; | ||
43 | |||
44 | for_each_sg(sgl, sg, nents, i) { | ||
45 | BUG_ON(!sg_page(sg)); | ||
46 | sg_dma_address(sg) = (uintptr_t)sg_virt(sg); | ||
47 | sg_dma_len(sg) = sg->length; | ||
48 | } | ||
49 | |||
50 | return nents; | ||
51 | } | ||
52 | |||
53 | const struct dma_map_ops dma_virt_ops = { | ||
54 | .alloc = dma_virt_alloc, | ||
55 | .free = dma_virt_free, | ||
56 | .map_page = dma_virt_map_page, | ||
57 | .map_sg = dma_virt_map_sg, | ||
58 | }; | ||
59 | EXPORT_SYMBOL(dma_virt_ops); | ||