blob: 12ea9653781b1579ed756a0efa7c775b11684592 [file] [log] [blame]
Christoph Hellwig002e6742018-01-09 16:30:23 +01001// SPDX-License-Identifier: GPL-2.0
2/*
Christoph Hellwig2e86a042017-12-22 11:29:51 +01003 * DMA operations that map physical memory directly without using an IOMMU or
4 * flushing caches.
Christoph Hellwig002e6742018-01-09 16:30:23 +01005 */
6#include <linux/export.h>
7#include <linux/mm.h>
Christoph Hellwig2e86a042017-12-22 11:29:51 +01008#include <linux/dma-direct.h>
Christoph Hellwig002e6742018-01-09 16:30:23 +01009#include <linux/scatterlist.h>
10#include <linux/pfn.h>
11
12static void *dma_direct_alloc(struct device *dev, size_t size,
13 dma_addr_t *dma_handle, gfp_t gfp, unsigned long attrs)
14{
15 void *ret;
16
17 ret = (void *)__get_free_pages(gfp, get_order(size));
18 if (ret)
Christoph Hellwig2e86a042017-12-22 11:29:51 +010019 *dma_handle = phys_to_dma(dev, virt_to_phys(ret));
Christoph Hellwig002e6742018-01-09 16:30:23 +010020
21 return ret;
22}
23
24static void dma_direct_free(struct device *dev, size_t size, void *cpu_addr,
25 dma_addr_t dma_addr, unsigned long attrs)
26{
27 free_pages((unsigned long)cpu_addr, get_order(size));
28}
29
30static dma_addr_t dma_direct_map_page(struct device *dev, struct page *page,
31 unsigned long offset, size_t size, enum dma_data_direction dir,
32 unsigned long attrs)
33{
Christoph Hellwig2e86a042017-12-22 11:29:51 +010034 return phys_to_dma(dev, page_to_phys(page)) + offset;
Christoph Hellwig002e6742018-01-09 16:30:23 +010035}
36
37static int dma_direct_map_sg(struct device *dev, struct scatterlist *sgl,
38 int nents, enum dma_data_direction dir, unsigned long attrs)
39{
40 int i;
41 struct scatterlist *sg;
42
43 for_each_sg(sgl, sg, nents, i) {
Christoph Hellwig002e6742018-01-09 16:30:23 +010044 BUG_ON(!sg_page(sg));
Christoph Hellwig2e86a042017-12-22 11:29:51 +010045
46 sg_dma_address(sg) = phys_to_dma(dev, sg_phys(sg));
Christoph Hellwig002e6742018-01-09 16:30:23 +010047 sg_dma_len(sg) = sg->length;
48 }
49
50 return nents;
51}
52
53const struct dma_map_ops dma_direct_ops = {
54 .alloc = dma_direct_alloc,
55 .free = dma_direct_free,
56 .map_page = dma_direct_map_page,
57 .map_sg = dma_direct_map_sg,
58};
59EXPORT_SYMBOL(dma_direct_ops);