dma-mapping.h revision 270710
1226031Sstas/*-
2226031Sstas * Copyright (c) 2010 Isilon Systems, Inc.
3226128Sstas * Copyright (c) 2010 iX Systems, Inc.
4226128Sstas * Copyright (c) 2010 Panasas, Inc.
5226031Sstas * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
6226031Sstas * All rights reserved.
7226128Sstas *
8226031Sstas * Redistribution and use in source and binary forms, with or without
9226031Sstas * modification, are permitted provided that the following conditions
10226031Sstas * are met:
11226031Sstas * 1. Redistributions of source code must retain the above copyright
12226128Sstas *    notice unmodified, this list of conditions, and the following
13226031Sstas *    disclaimer.
14226031Sstas * 2. Redistributions in binary form must reproduce the above copyright
15226031Sstas *    notice, this list of conditions and the following disclaimer in the
16226031Sstas *    documentation and/or other materials provided with the distribution.
17226031Sstas *
18226031Sstas * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19226031Sstas * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20226031Sstas * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21226031Sstas * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22226031Sstas * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23226031Sstas * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24226031Sstas * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25226031Sstas * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26226031Sstas * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27226031Sstas * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28226031Sstas */
29226031Sstas#ifndef	_LINUX_DMA_MAPPING_H_
30226031Sstas#define _LINUX_DMA_MAPPING_H_
31226031Sstas
32226031Sstas#include <linux/types.h>
33226031Sstas#include <linux/device.h>
34226031Sstas#include <linux/err.h>
35226031Sstas#include <linux/dma-attrs.h>
36226031Sstas#include <linux/scatterlist.h>
37226031Sstas#include <linux/mm.h>
38226031Sstas#include <linux/page.h>
39226031Sstas
40226031Sstas#include <sys/systm.h>
41226031Sstas#include <sys/malloc.h>
42226031Sstas
43226031Sstas#include <vm/vm.h>
44226031Sstas#include <vm/vm_page.h>
45226031Sstas#include <vm/pmap.h>
46226031Sstas
47226031Sstas#include <machine/bus.h>
48226031Sstas#include <machine/pmap.h>
49226031Sstas
50226031Sstasenum dma_data_direction {
51226031Sstas	DMA_BIDIRECTIONAL = 0,
52226031Sstas	DMA_TO_DEVICE = 1,
53226031Sstas	DMA_FROM_DEVICE = 2,
54226031Sstas	DMA_NONE = 3,
55226031Sstas};
56226031Sstas
57226031Sstasstruct dma_map_ops {
58226031Sstas	void* (*alloc_coherent)(struct device *dev, size_t size,
59226031Sstas	    dma_addr_t *dma_handle, gfp_t gfp);
60226031Sstas	void (*free_coherent)(struct device *dev, size_t size,
61226031Sstas	    void *vaddr, dma_addr_t dma_handle);
62226031Sstas	dma_addr_t (*map_page)(struct device *dev, struct page *page,
63226031Sstas	    unsigned long offset, size_t size, enum dma_data_direction dir,
64226031Sstas	    struct dma_attrs *attrs);
65226031Sstas	void (*unmap_page)(struct device *dev, dma_addr_t dma_handle,
66226031Sstas	    size_t size, enum dma_data_direction dir, struct dma_attrs *attrs);
67226031Sstas	int (*map_sg)(struct device *dev, struct scatterlist *sg,
68226031Sstas	    int nents, enum dma_data_direction dir, struct dma_attrs *attrs);
69226031Sstas	void (*unmap_sg)(struct device *dev, struct scatterlist *sg, int nents,
70226031Sstas	    enum dma_data_direction dir, struct dma_attrs *attrs);
71226031Sstas	void (*sync_single_for_cpu)(struct device *dev, dma_addr_t dma_handle,
72226031Sstas	    size_t size, enum dma_data_direction dir);
73226031Sstas	void (*sync_single_for_device)(struct device *dev,
74226031Sstas	    dma_addr_t dma_handle, size_t size, enum dma_data_direction dir);
75226031Sstas	void (*sync_single_range_for_cpu)(struct device *dev,
76226031Sstas	    dma_addr_t dma_handle, unsigned long offset, size_t size,
77226031Sstas	    enum dma_data_direction dir);
78226031Sstas	void (*sync_single_range_for_device)(struct device *dev,
79226031Sstas	    dma_addr_t dma_handle, unsigned long offset, size_t size,
80226031Sstas	    enum dma_data_direction dir);
81226031Sstas	void (*sync_sg_for_cpu)(struct device *dev, struct scatterlist *sg,
82226031Sstas	    int nents, enum dma_data_direction dir);
83226031Sstas	void (*sync_sg_for_device)(struct device *dev, struct scatterlist *sg,
84226031Sstas	    int nents, enum dma_data_direction dir);
85226031Sstas	int (*mapping_error)(struct device *dev, dma_addr_t dma_addr);
86226031Sstas	int (*dma_supported)(struct device *dev, u64 mask);
87226031Sstas	int is_phys;
88226031Sstas};
89226031Sstas
90226031Sstas#define	DMA_BIT_MASK(n)	(((n) == 64) ? ~0ULL : ((1ULL << (n)) - 1))
91226031Sstas
92226031Sstasstatic inline int
93226031Sstasdma_supported(struct device *dev, u64 mask)
94226128Sstas{
95226031Sstas
96226031Sstas	/* XXX busdma takes care of this elsewhere. */
97226031Sstas	return (1);
98226031Sstas}
99226031Sstas
100226031Sstasstatic inline int
101226031Sstasdma_set_mask(struct device *dev, u64 dma_mask)
102226031Sstas{
103226031Sstas
104226031Sstas	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
105226031Sstas		return -EIO;
106226031Sstas
107226031Sstas	*dev->dma_mask = dma_mask;
108226031Sstas	return (0);
109226031Sstas}
110226031Sstas
111226031Sstasstatic inline int
112226031Sstasdma_set_coherent_mask(struct device *dev, u64 mask)
113226031Sstas{
114226031Sstas
115226031Sstas	if (!dma_supported(dev, mask))
116226031Sstas		return -EIO;
117226031Sstas	/* XXX Currently we don't support a seperate coherent mask. */
118226031Sstas	return 0;
119226031Sstas}
120226031Sstas
121226031Sstasstatic inline void *
122226031Sstasdma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
123226031Sstas    gfp_t flag)
124226031Sstas{
125226031Sstas	vm_paddr_t high;
126226031Sstas	size_t align;
127226031Sstas	void *mem;
128226031Sstas
129226031Sstas	if (dev->dma_mask)
130226031Sstas		high = *dev->dma_mask;
131226031Sstas	else
132226031Sstas		high = BUS_SPACE_MAXADDR_32BIT;
133226031Sstas	align = PAGE_SIZE << get_order(size);
134226031Sstas	mem = (void *)kmem_alloc_contig(kmem_arena, size, flag, 0, high, align,
135226031Sstas	    0, VM_MEMATTR_DEFAULT);
136226031Sstas	if (mem)
137226031Sstas		*dma_handle = vtophys(mem);
138226031Sstas	else
139226031Sstas		*dma_handle = 0;
140226031Sstas	return (mem);
141226031Sstas}
142226128Sstas
143226128Sstasstatic inline void
144226128Sstasdma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
145226031Sstas    dma_addr_t dma_handle)
146226031Sstas{
147226031Sstas
148226031Sstas	kmem_free(kmem_arena, (vm_offset_t)cpu_addr, size);
149226031Sstas}
150226031Sstas
151226031Sstas/* XXX This only works with no iommu. */
152226031Sstasstatic inline dma_addr_t
153226031Sstasdma_map_single_attrs(struct device *dev, void *ptr, size_t size,
154226031Sstas    enum dma_data_direction dir, struct dma_attrs *attrs)
155226031Sstas{
156226031Sstas
157226031Sstas	return vtophys(ptr);
158226031Sstas}
159226031Sstas
160226031Sstasstatic inline void
161226031Sstasdma_unmap_single_attrs(struct device *dev, dma_addr_t addr, size_t size,
162226031Sstas    enum dma_data_direction dir, struct dma_attrs *attrs)
163226031Sstas{
164226031Sstas}
165226031Sstas
166226031Sstasstatic inline int
167226031Sstasdma_map_sg_attrs(struct device *dev, struct scatterlist *sgl, int nents,
168226031Sstas    enum dma_data_direction dir, struct dma_attrs *attrs)
169226031Sstas{
170226031Sstas	struct scatterlist *sg;
171226031Sstas	int i;
172226031Sstas
173226031Sstas	for_each_sg(sgl, sg, nents, i)
174226031Sstas		sg_dma_address(sg) = sg_phys(sg);
175226031Sstas
176226031Sstas	return (nents);
177226031Sstas}
178226031Sstas
179226031Sstasstatic inline void
180226031Sstasdma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg, int nents,
181226031Sstas    enum dma_data_direction dir, struct dma_attrs *attrs)
182226031Sstas{
183226031Sstas}
184226031Sstas
185226031Sstasstatic inline dma_addr_t
186226031Sstasdma_map_page(struct device *dev, struct page *page,
187226031Sstas    unsigned long offset, size_t size, enum dma_data_direction direction)
188226031Sstas{
189226031Sstas
190226031Sstas	return VM_PAGE_TO_PHYS(page) + offset;
191226031Sstas}
192226031Sstas
193226031Sstasstatic inline void
194226128Sstasdma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
195226128Sstas    enum dma_data_direction direction)
196226128Sstas{
197226128Sstas}
198226128Sstas
199226128Sstasstatic inline void
200226128Sstasdma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
201226128Sstas    enum dma_data_direction direction)
202226031Sstas{
203226128Sstas}
204226031Sstas
205226031Sstasstatic inline void
206226031Sstasdma_sync_single(struct device *dev, dma_addr_t addr, size_t size,
207226031Sstas    enum dma_data_direction dir)
208226031Sstas{
209226031Sstas	dma_sync_single_for_cpu(dev, addr, size, dir);
210226031Sstas}
211226031Sstas
212226031Sstasstatic inline void
213226031Sstasdma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
214226031Sstas    size_t size, enum dma_data_direction direction)
215226031Sstas{
216226031Sstas}
217226031Sstas
218226128Sstasstatic inline void
219226128Sstasdma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
220226031Sstas    enum dma_data_direction direction)
221226128Sstas{
222226128Sstas}
223226128Sstas
224226128Sstasstatic inline void
225226128Sstasdma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
226226128Sstas    enum dma_data_direction direction)
227226128Sstas{
228226031Sstas}
229226128Sstas
230226128Sstasstatic inline void
231226031Sstasdma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
232226128Sstas    unsigned long offset, size_t size, int direction)
233226031Sstas{
234226031Sstas}
235226031Sstas
236226031Sstasstatic inline void
237226031Sstasdma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
238226031Sstas    unsigned long offset, size_t size, int direction)
239226031Sstas{
240226031Sstas}
241226031Sstas
242226031Sstasstatic inline int
243226031Sstasdma_mapping_error(struct device *dev, dma_addr_t dma_addr)
244226031Sstas{
245226031Sstas
246226031Sstas	return (0);
247226031Sstas}
248226031Sstas
249226031Sstasstatic inline unsigned int dma_set_max_seg_size(struct device *dev,
250226031Sstas                                                 unsigned int size)
251226031Sstas{
252226031Sstas        return (0);
253226031Sstas}
254226031Sstas
255226031Sstas
256226031Sstas#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, NULL)
257226031Sstas#define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, NULL)
258226031Sstas#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, NULL)
259226031Sstas#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, NULL)
260226031Sstas
261226031Sstas#define	DEFINE_DMA_UNMAP_ADDR(name)		dma_addr_t name
262226031Sstas#define	DEFINE_DMA_UNMAP_LEN(name)		__u32 name
263226031Sstas#define	dma_unmap_addr(p, name)			((p)->name)
264226031Sstas#define	dma_unmap_addr_set(p, name, v)		(((p)->name) = (v))
265226031Sstas#define	dma_unmap_len(p, name)			((p)->name)
266226031Sstas#define	dma_unmap_len_set(p, name, v)		(((p)->name) = (v))
267226031Sstas
268226031Sstasextern int uma_align_cache;
269226031Sstas#define	dma_get_cache_alignment()	uma_align_cache
270226031Sstas
271226031Sstas#endif	/* _LINUX_DMA_MAPPING_H_ */
272226031Sstas