dma-mapping.h revision 325937
1130803Smarcel/*-
2130803Smarcel * Copyright (c) 2010 Isilon Systems, Inc.
3130803Smarcel * Copyright (c) 2010 iX Systems, Inc.
4130803Smarcel * Copyright (c) 2010 Panasas, Inc.
5130803Smarcel * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
6130803Smarcel * All rights reserved.
7130803Smarcel *
8130803Smarcel * Redistribution and use in source and binary forms, with or without
9130803Smarcel * modification, are permitted provided that the following conditions
10130803Smarcel * are met:
11130803Smarcel * 1. Redistributions of source code must retain the above copyright
12130803Smarcel *    notice unmodified, this list of conditions, and the following
13130803Smarcel *    disclaimer.
14130803Smarcel * 2. Redistributions in binary form must reproduce the above copyright
15130803Smarcel *    notice, this list of conditions and the following disclaimer in the
16130803Smarcel *    documentation and/or other materials provided with the distribution.
17130803Smarcel *
18130803Smarcel * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19130803Smarcel * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20130803Smarcel * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21130803Smarcel * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22130803Smarcel * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23130803Smarcel * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24130803Smarcel * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25130803Smarcel * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26130803Smarcel * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27130803Smarcel * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28130803Smarcel */
29130803Smarcel#ifndef	_LINUX_DMA_MAPPING_H_
30130803Smarcel#define _LINUX_DMA_MAPPING_H_
31130803Smarcel
32130803Smarcel#include <linux/types.h>
33130803Smarcel#include <linux/device.h>
34130803Smarcel#include <linux/err.h>
35130803Smarcel#include <linux/dma-attrs.h>
36130803Smarcel#include <linux/scatterlist.h>
37130803Smarcel#include <linux/mm.h>
38130803Smarcel#include <linux/page.h>
39130803Smarcel
40130803Smarcel#include <sys/systm.h>
41130803Smarcel#include <sys/malloc.h>
42130803Smarcel
43130803Smarcel#include <vm/vm.h>
44130803Smarcel#include <vm/vm_page.h>
45130803Smarcel#include <vm/pmap.h>
46130803Smarcel
47130803Smarcel#include <machine/bus.h>
48130803Smarcel#include <machine/pmap.h>
49130803Smarcel
50130803Smarcelenum dma_data_direction {
51130803Smarcel	DMA_BIDIRECTIONAL = 0,
52130803Smarcel	DMA_TO_DEVICE = 1,
53130803Smarcel	DMA_FROM_DEVICE = 2,
54130803Smarcel	DMA_NONE = 3,
55130803Smarcel};
56130803Smarcel
57130803Smarcelstruct dma_map_ops {
58130803Smarcel	void* (*alloc_coherent)(struct device *dev, size_t size,
59130803Smarcel	    dma_addr_t *dma_handle, gfp_t gfp);
60130803Smarcel	void (*free_coherent)(struct device *dev, size_t size,
61130803Smarcel	    void *vaddr, dma_addr_t dma_handle);
62130803Smarcel	dma_addr_t (*map_page)(struct device *dev, struct page *page,
63130803Smarcel	    unsigned long offset, size_t size, enum dma_data_direction dir,
64130803Smarcel	    struct dma_attrs *attrs);
65130803Smarcel	void (*unmap_page)(struct device *dev, dma_addr_t dma_handle,
66130803Smarcel	    size_t size, enum dma_data_direction dir, struct dma_attrs *attrs);
67130803Smarcel	int (*map_sg)(struct device *dev, struct scatterlist *sg,
68130803Smarcel	    int nents, enum dma_data_direction dir, struct dma_attrs *attrs);
69130803Smarcel	void (*unmap_sg)(struct device *dev, struct scatterlist *sg, int nents,
70130803Smarcel	    enum dma_data_direction dir, struct dma_attrs *attrs);
71130803Smarcel	void (*sync_single_for_cpu)(struct device *dev, dma_addr_t dma_handle,
72130803Smarcel	    size_t size, enum dma_data_direction dir);
73130803Smarcel	void (*sync_single_for_device)(struct device *dev,
74130803Smarcel	    dma_addr_t dma_handle, size_t size, enum dma_data_direction dir);
75130803Smarcel	void (*sync_single_range_for_cpu)(struct device *dev,
76130803Smarcel	    dma_addr_t dma_handle, unsigned long offset, size_t size,
77130803Smarcel	    enum dma_data_direction dir);
78130803Smarcel	void (*sync_single_range_for_device)(struct device *dev,
79130803Smarcel	    dma_addr_t dma_handle, unsigned long offset, size_t size,
80130803Smarcel	    enum dma_data_direction dir);
81130803Smarcel	void (*sync_sg_for_cpu)(struct device *dev, struct scatterlist *sg,
82130803Smarcel	    int nents, enum dma_data_direction dir);
83130803Smarcel	void (*sync_sg_for_device)(struct device *dev, struct scatterlist *sg,
84130803Smarcel	    int nents, enum dma_data_direction dir);
85130803Smarcel	int (*mapping_error)(struct device *dev, dma_addr_t dma_addr);
86130803Smarcel	int (*dma_supported)(struct device *dev, u64 mask);
87130803Smarcel	int is_phys;
88130803Smarcel};
89130803Smarcel
90130803Smarcel#define	DMA_BIT_MASK(n)	(((n) == 64) ? ~0ULL : ((1ULL << (n)) - 1))
91130803Smarcel
92130803Smarcelstatic inline int
93130803Smarceldma_supported(struct device *dev, u64 mask)
94130803Smarcel{
95130803Smarcel
96130803Smarcel	/* XXX busdma takes care of this elsewhere. */
97130803Smarcel	return (1);
98130803Smarcel}
99130803Smarcel
100130803Smarcelstatic inline int
101130803Smarceldma_set_mask(struct device *dev, u64 dma_mask)
102130803Smarcel{
103130803Smarcel
104130803Smarcel	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
105130803Smarcel		return -EIO;
106130803Smarcel
107130803Smarcel	*dev->dma_mask = dma_mask;
108130803Smarcel	return (0);
109130803Smarcel}
110130803Smarcel
111130803Smarcelstatic inline int
112130803Smarceldma_set_coherent_mask(struct device *dev, u64 mask)
113130803Smarcel{
114130803Smarcel
115130803Smarcel	if (!dma_supported(dev, mask))
116130803Smarcel		return -EIO;
117130803Smarcel	/* XXX Currently we don't support a seperate coherent mask. */
118130803Smarcel	return 0;
119130803Smarcel}
120130803Smarcel
121130803Smarcelstatic inline void *
122130803Smarceldma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
123130803Smarcel    gfp_t flag)
124130803Smarcel{
125130803Smarcel	vm_paddr_t high;
126130803Smarcel	size_t align;
127130803Smarcel	void *mem;
128130803Smarcel
129130803Smarcel	if (dev != NULL && dev->dma_mask)
130130803Smarcel		high = *dev->dma_mask;
131130803Smarcel	else
132130803Smarcel		high = BUS_SPACE_MAXADDR_32BIT;
133130803Smarcel	align = PAGE_SIZE << get_order(size);
134130803Smarcel	mem = (void *)kmem_alloc_contig(kmem_arena, size, flag, 0, high, align,
135130803Smarcel	    0, VM_MEMATTR_DEFAULT);
136130803Smarcel	if (mem)
137130803Smarcel		*dma_handle = vtophys(mem);
138130803Smarcel	else
139130803Smarcel		*dma_handle = 0;
140130803Smarcel	return (mem);
141130803Smarcel}
142130803Smarcel
143130803Smarcelstatic inline void *
144130803Smarceldma_zalloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
145130803Smarcel    gfp_t flag)
146130803Smarcel{
147130803Smarcel
148130803Smarcel	return (dma_alloc_coherent(dev, size, dma_handle, flag | __GFP_ZERO));
149130803Smarcel}
150130803Smarcel
151130803Smarcelstatic inline void
152130803Smarceldma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
153130803Smarcel    dma_addr_t dma_handle)
154130803Smarcel{
155130803Smarcel
156130803Smarcel	kmem_free(kmem_arena, (vm_offset_t)cpu_addr, size);
157130803Smarcel}
158130803Smarcel
159130803Smarcel/* XXX This only works with no iommu. */
160130803Smarcelstatic inline dma_addr_t
161130803Smarceldma_map_single_attrs(struct device *dev, void *ptr, size_t size,
162130803Smarcel    enum dma_data_direction dir, struct dma_attrs *attrs)
163130803Smarcel{
164130803Smarcel
165130803Smarcel	return vtophys(ptr);
166130803Smarcel}
167130803Smarcel
168130803Smarcelstatic inline void
169130803Smarceldma_unmap_single_attrs(struct device *dev, dma_addr_t addr, size_t size,
170130803Smarcel    enum dma_data_direction dir, struct dma_attrs *attrs)
171130803Smarcel{
172130803Smarcel}
173130803Smarcel
174130803Smarcelstatic inline int
175130803Smarceldma_map_sg_attrs(struct device *dev, struct scatterlist *sgl, int nents,
176130803Smarcel    enum dma_data_direction dir, struct dma_attrs *attrs)
177130803Smarcel{
178130803Smarcel	struct scatterlist *sg;
179130803Smarcel	int i;
180130803Smarcel
181130803Smarcel	for_each_sg(sgl, sg, nents, i)
182130803Smarcel		sg_dma_address(sg) = sg_phys(sg);
183130803Smarcel
184130803Smarcel	return (nents);
185130803Smarcel}
186130803Smarcel
187130803Smarcelstatic inline void
188130803Smarceldma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg, int nents,
189130803Smarcel    enum dma_data_direction dir, struct dma_attrs *attrs)
190130803Smarcel{
191130803Smarcel}
192130803Smarcel
193130803Smarcelstatic inline dma_addr_t
194130803Smarceldma_map_page(struct device *dev, struct page *page,
195130803Smarcel    unsigned long offset, size_t size, enum dma_data_direction direction)
196130803Smarcel{
197130803Smarcel
198130803Smarcel	return VM_PAGE_TO_PHYS(page) + offset;
199130803Smarcel}
200130803Smarcel
201130803Smarcelstatic inline void
202130803Smarceldma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
203130803Smarcel    enum dma_data_direction direction)
204130803Smarcel{
205130803Smarcel}
206130803Smarcel
207130803Smarcelstatic inline void
208130803Smarceldma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
209130803Smarcel    enum dma_data_direction direction)
210130803Smarcel{
211130803Smarcel}
212130803Smarcel
213130803Smarcelstatic inline void
214130803Smarceldma_sync_single(struct device *dev, dma_addr_t addr, size_t size,
215130803Smarcel    enum dma_data_direction dir)
216130803Smarcel{
217130803Smarcel	dma_sync_single_for_cpu(dev, addr, size, dir);
218130803Smarcel}
219130803Smarcel
220130803Smarcelstatic inline void
221130803Smarceldma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
222130803Smarcel    size_t size, enum dma_data_direction direction)
223130803Smarcel{
224130803Smarcel}
225130803Smarcel
226130803Smarcelstatic inline void
227130803Smarceldma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
228130803Smarcel    enum dma_data_direction direction)
229130803Smarcel{
230130803Smarcel}
231130803Smarcel
232130803Smarcelstatic inline void
233130803Smarceldma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
234130803Smarcel    enum dma_data_direction direction)
235130803Smarcel{
236130803Smarcel}
237130803Smarcel
238130803Smarcelstatic inline void
239130803Smarceldma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
240130803Smarcel    unsigned long offset, size_t size, int direction)
241130803Smarcel{
242130803Smarcel}
243130803Smarcel
244130803Smarcelstatic inline void
245130803Smarceldma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
246130803Smarcel    unsigned long offset, size_t size, int direction)
247130803Smarcel{
248130803Smarcel}
249130803Smarcel
250130803Smarcelstatic inline int
251130803Smarceldma_mapping_error(struct device *dev, dma_addr_t dma_addr)
252130803Smarcel{
253130803Smarcel
254130803Smarcel	return (0);
255130803Smarcel}
256130803Smarcel
257130803Smarcelstatic inline unsigned int dma_set_max_seg_size(struct device *dev,
258130803Smarcel                                                 unsigned int size)
259130803Smarcel{
260130803Smarcel        return (0);
261130803Smarcel}
262130803Smarcel
263130803Smarcel
264130803Smarcel#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, NULL)
265130803Smarcel#define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, NULL)
266130803Smarcel#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, NULL)
267130803Smarcel#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, NULL)
268130803Smarcel
269130803Smarcel#define	DEFINE_DMA_UNMAP_ADDR(name)		dma_addr_t name
270130803Smarcel#define	DEFINE_DMA_UNMAP_LEN(name)		__u32 name
271130803Smarcel#define	dma_unmap_addr(p, name)			((p)->name)
272130803Smarcel#define	dma_unmap_addr_set(p, name, v)		(((p)->name) = (v))
273130803Smarcel#define	dma_unmap_len(p, name)			((p)->name)
274130803Smarcel#define	dma_unmap_len_set(p, name, v)		(((p)->name) = (v))
275130803Smarcel
276130803Smarcelextern int uma_align_cache;
277130803Smarcel#define	dma_get_cache_alignment()	uma_align_cache
278130803Smarcel
279130803Smarcel#endif	/* _LINUX_DMA_MAPPING_H_ */
280130803Smarcel