dma-mapping.h revision 289644
1219820Sjeff/*-
2219820Sjeff * Copyright (c) 2010 Isilon Systems, Inc.
3219820Sjeff * Copyright (c) 2010 iX Systems, Inc.
4219820Sjeff * Copyright (c) 2010 Panasas, Inc.
5270710Shselasky * Copyright (c) 2013, 2014 Mellanox Technologies, Ltd.
6219820Sjeff * All rights reserved.
7219820Sjeff *
8219820Sjeff * Redistribution and use in source and binary forms, with or without
9219820Sjeff * modification, are permitted provided that the following conditions
10219820Sjeff * are met:
11219820Sjeff * 1. Redistributions of source code must retain the above copyright
12219820Sjeff *    notice unmodified, this list of conditions, and the following
13219820Sjeff *    disclaimer.
14219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright
15219820Sjeff *    notice, this list of conditions and the following disclaimer in the
16219820Sjeff *    documentation and/or other materials provided with the distribution.
17219820Sjeff *
18219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19219820Sjeff * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20219820Sjeff * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21219820Sjeff * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22219820Sjeff * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23219820Sjeff * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24219820Sjeff * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25219820Sjeff * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26219820Sjeff * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27219820Sjeff * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28289644Shselasky *
29289644Shselasky * $FreeBSD: head/sys/ofed/include/linux/dma-mapping.h 289644 2015-10-20 19:08:26Z hselasky $
30219820Sjeff */
31219820Sjeff#ifndef	_LINUX_DMA_MAPPING_H_
32219820Sjeff#define _LINUX_DMA_MAPPING_H_
33219820Sjeff
34219820Sjeff#include <linux/types.h>
35219820Sjeff#include <linux/device.h>
36219820Sjeff#include <linux/err.h>
37219820Sjeff#include <linux/dma-attrs.h>
38219820Sjeff#include <linux/scatterlist.h>
39219820Sjeff#include <linux/mm.h>
40219820Sjeff#include <linux/page.h>
41219820Sjeff
42219820Sjeff#include <sys/systm.h>
43219820Sjeff#include <sys/malloc.h>
44219820Sjeff
45219820Sjeff#include <vm/vm.h>
46219820Sjeff#include <vm/vm_page.h>
47219820Sjeff#include <vm/pmap.h>
48219820Sjeff
49219820Sjeff#include <machine/bus.h>
50219820Sjeff#include <machine/pmap.h>
51219820Sjeff
52219820Sjeffenum dma_data_direction {
53219820Sjeff	DMA_BIDIRECTIONAL = 0,
54219820Sjeff	DMA_TO_DEVICE = 1,
55219820Sjeff	DMA_FROM_DEVICE = 2,
56219820Sjeff	DMA_NONE = 3,
57219820Sjeff};
58219820Sjeff
59219820Sjeffstruct dma_map_ops {
60219820Sjeff	void* (*alloc_coherent)(struct device *dev, size_t size,
61219820Sjeff	    dma_addr_t *dma_handle, gfp_t gfp);
62219820Sjeff	void (*free_coherent)(struct device *dev, size_t size,
63219820Sjeff	    void *vaddr, dma_addr_t dma_handle);
64219820Sjeff	dma_addr_t (*map_page)(struct device *dev, struct page *page,
65219820Sjeff	    unsigned long offset, size_t size, enum dma_data_direction dir,
66219820Sjeff	    struct dma_attrs *attrs);
67219820Sjeff	void (*unmap_page)(struct device *dev, dma_addr_t dma_handle,
68219820Sjeff	    size_t size, enum dma_data_direction dir, struct dma_attrs *attrs);
69219820Sjeff	int (*map_sg)(struct device *dev, struct scatterlist *sg,
70219820Sjeff	    int nents, enum dma_data_direction dir, struct dma_attrs *attrs);
71219820Sjeff	void (*unmap_sg)(struct device *dev, struct scatterlist *sg, int nents,
72219820Sjeff	    enum dma_data_direction dir, struct dma_attrs *attrs);
73219820Sjeff	void (*sync_single_for_cpu)(struct device *dev, dma_addr_t dma_handle,
74219820Sjeff	    size_t size, enum dma_data_direction dir);
75219820Sjeff	void (*sync_single_for_device)(struct device *dev,
76219820Sjeff	    dma_addr_t dma_handle, size_t size, enum dma_data_direction dir);
77219820Sjeff	void (*sync_single_range_for_cpu)(struct device *dev,
78219820Sjeff	    dma_addr_t dma_handle, unsigned long offset, size_t size,
79219820Sjeff	    enum dma_data_direction dir);
80219820Sjeff	void (*sync_single_range_for_device)(struct device *dev,
81219820Sjeff	    dma_addr_t dma_handle, unsigned long offset, size_t size,
82219820Sjeff	    enum dma_data_direction dir);
83219820Sjeff	void (*sync_sg_for_cpu)(struct device *dev, struct scatterlist *sg,
84219820Sjeff	    int nents, enum dma_data_direction dir);
85219820Sjeff	void (*sync_sg_for_device)(struct device *dev, struct scatterlist *sg,
86219820Sjeff	    int nents, enum dma_data_direction dir);
87219820Sjeff	int (*mapping_error)(struct device *dev, dma_addr_t dma_addr);
88219820Sjeff	int (*dma_supported)(struct device *dev, u64 mask);
89219820Sjeff	int is_phys;
90219820Sjeff};
91219820Sjeff
92289571Shselasky#define	DMA_BIT_MASK(n)	((2ULL << ((n) - 1)) - 1ULL)
93219820Sjeff
94219820Sjeffstatic inline int
95219820Sjeffdma_supported(struct device *dev, u64 mask)
96219820Sjeff{
97219820Sjeff
98219820Sjeff	/* XXX busdma takes care of this elsewhere. */
99219820Sjeff	return (1);
100219820Sjeff}
101219820Sjeff
102219820Sjeffstatic inline int
103219820Sjeffdma_set_mask(struct device *dev, u64 dma_mask)
104219820Sjeff{
105219820Sjeff
106219820Sjeff	if (!dev->dma_mask || !dma_supported(dev, dma_mask))
107219820Sjeff		return -EIO;
108219820Sjeff
109219820Sjeff	*dev->dma_mask = dma_mask;
110219820Sjeff	return (0);
111219820Sjeff}
112219820Sjeff
113219820Sjeffstatic inline int
114219820Sjeffdma_set_coherent_mask(struct device *dev, u64 mask)
115219820Sjeff{
116219820Sjeff
117219820Sjeff	if (!dma_supported(dev, mask))
118219820Sjeff		return -EIO;
119219820Sjeff	/* XXX Currently we don't support a seperate coherent mask. */
120219820Sjeff	return 0;
121219820Sjeff}
122219820Sjeff
123219820Sjeffstatic inline void *
124219820Sjeffdma_alloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
125219820Sjeff    gfp_t flag)
126219820Sjeff{
127219820Sjeff	vm_paddr_t high;
128219820Sjeff	size_t align;
129219820Sjeff	void *mem;
130219820Sjeff
131219820Sjeff	if (dev->dma_mask)
132219820Sjeff		high = *dev->dma_mask;
133219820Sjeff	else
134219820Sjeff		high = BUS_SPACE_MAXADDR_32BIT;
135219820Sjeff	align = PAGE_SIZE << get_order(size);
136254025Sjeff	mem = (void *)kmem_alloc_contig(kmem_arena, size, flag, 0, high, align,
137219820Sjeff	    0, VM_MEMATTR_DEFAULT);
138219820Sjeff	if (mem)
139219820Sjeff		*dma_handle = vtophys(mem);
140219820Sjeff	else
141219820Sjeff		*dma_handle = 0;
142219820Sjeff	return (mem);
143219820Sjeff}
144277396Shselasky
145277396Shselaskystatic inline void *
146277396Shselaskydma_zalloc_coherent(struct device *dev, size_t size, dma_addr_t *dma_handle,
147277396Shselasky    gfp_t flag)
148277396Shselasky{
149277396Shselasky
150277396Shselasky	return (dma_alloc_coherent(dev, size, dma_handle, flag | __GFP_ZERO));
151277396Shselasky}
152219820Sjeff
153219820Sjeffstatic inline void
154219820Sjeffdma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
155219820Sjeff    dma_addr_t dma_handle)
156219820Sjeff{
157219820Sjeff
158254025Sjeff	kmem_free(kmem_arena, (vm_offset_t)cpu_addr, size);
159219820Sjeff}
160219820Sjeff
161219820Sjeff/* XXX This only works with no iommu. */
162219820Sjeffstatic inline dma_addr_t
163219820Sjeffdma_map_single_attrs(struct device *dev, void *ptr, size_t size,
164219820Sjeff    enum dma_data_direction dir, struct dma_attrs *attrs)
165219820Sjeff{
166219820Sjeff
167219820Sjeff	return vtophys(ptr);
168219820Sjeff}
169219820Sjeff
170219820Sjeffstatic inline void
171219820Sjeffdma_unmap_single_attrs(struct device *dev, dma_addr_t addr, size_t size,
172219820Sjeff    enum dma_data_direction dir, struct dma_attrs *attrs)
173219820Sjeff{
174219820Sjeff}
175219820Sjeff
176219820Sjeffstatic inline int
177219820Sjeffdma_map_sg_attrs(struct device *dev, struct scatterlist *sgl, int nents,
178219820Sjeff    enum dma_data_direction dir, struct dma_attrs *attrs)
179219820Sjeff{
180219820Sjeff	struct scatterlist *sg;
181219820Sjeff	int i;
182219820Sjeff
183219820Sjeff	for_each_sg(sgl, sg, nents, i)
184219820Sjeff		sg_dma_address(sg) = sg_phys(sg);
185219820Sjeff
186219820Sjeff	return (nents);
187219820Sjeff}
188219820Sjeff
189219820Sjeffstatic inline void
190219820Sjeffdma_unmap_sg_attrs(struct device *dev, struct scatterlist *sg, int nents,
191219820Sjeff    enum dma_data_direction dir, struct dma_attrs *attrs)
192219820Sjeff{
193219820Sjeff}
194219820Sjeff
195219820Sjeffstatic inline dma_addr_t
196219820Sjeffdma_map_page(struct device *dev, struct page *page,
197219820Sjeff    unsigned long offset, size_t size, enum dma_data_direction direction)
198219820Sjeff{
199219820Sjeff
200219820Sjeff	return VM_PAGE_TO_PHYS(page) + offset;
201219820Sjeff}
202219820Sjeff
203219820Sjeffstatic inline void
204219820Sjeffdma_unmap_page(struct device *dev, dma_addr_t dma_address, size_t size,
205219820Sjeff    enum dma_data_direction direction)
206219820Sjeff{
207219820Sjeff}
208219820Sjeff
209219820Sjeffstatic inline void
210219820Sjeffdma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
211219820Sjeff    enum dma_data_direction direction)
212219820Sjeff{
213219820Sjeff}
214219820Sjeff
215219820Sjeffstatic inline void
216219820Sjeffdma_sync_single(struct device *dev, dma_addr_t addr, size_t size,
217219820Sjeff    enum dma_data_direction dir)
218219820Sjeff{
219219820Sjeff	dma_sync_single_for_cpu(dev, addr, size, dir);
220219820Sjeff}
221219820Sjeff
222219820Sjeffstatic inline void
223219820Sjeffdma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle,
224219820Sjeff    size_t size, enum dma_data_direction direction)
225219820Sjeff{
226219820Sjeff}
227219820Sjeff
228219820Sjeffstatic inline void
229219820Sjeffdma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, int nelems,
230219820Sjeff    enum dma_data_direction direction)
231219820Sjeff{
232219820Sjeff}
233219820Sjeff
234219820Sjeffstatic inline void
235219820Sjeffdma_sync_sg_for_device(struct device *dev, struct scatterlist *sg, int nelems,
236219820Sjeff    enum dma_data_direction direction)
237219820Sjeff{
238219820Sjeff}
239219820Sjeff
240219820Sjeffstatic inline void
241219820Sjeffdma_sync_single_range_for_cpu(struct device *dev, dma_addr_t dma_handle,
242219820Sjeff    unsigned long offset, size_t size, int direction)
243219820Sjeff{
244219820Sjeff}
245219820Sjeff
246219820Sjeffstatic inline void
247219820Sjeffdma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle,
248219820Sjeff    unsigned long offset, size_t size, int direction)
249219820Sjeff{
250219820Sjeff}
251219820Sjeff
252219820Sjeffstatic inline int
253219820Sjeffdma_mapping_error(struct device *dev, dma_addr_t dma_addr)
254219820Sjeff{
255219820Sjeff
256219820Sjeff	return (0);
257219820Sjeff}
258219820Sjeff
259255932Salfredstatic inline unsigned int dma_set_max_seg_size(struct device *dev,
260255932Salfred                                                 unsigned int size)
261255932Salfred{
262255932Salfred        return (0);
263255932Salfred}
264255932Salfred
265255932Salfred
266219820Sjeff#define dma_map_single(d, a, s, r) dma_map_single_attrs(d, a, s, r, NULL)
267219820Sjeff#define dma_unmap_single(d, a, s, r) dma_unmap_single_attrs(d, a, s, r, NULL)
268219820Sjeff#define dma_map_sg(d, s, n, r) dma_map_sg_attrs(d, s, n, r, NULL)
269219820Sjeff#define dma_unmap_sg(d, s, n, r) dma_unmap_sg_attrs(d, s, n, r, NULL)
270219820Sjeff
271219820Sjeff#define	DEFINE_DMA_UNMAP_ADDR(name)		dma_addr_t name
272219820Sjeff#define	DEFINE_DMA_UNMAP_LEN(name)		__u32 name
273219820Sjeff#define	dma_unmap_addr(p, name)			((p)->name)
274219820Sjeff#define	dma_unmap_addr_set(p, name, v)		(((p)->name) = (v))
275219820Sjeff#define	dma_unmap_len(p, name)			((p)->name)
276219820Sjeff#define	dma_unmap_len_set(p, name, v)		(((p)->name) = (v))
277219820Sjeff
278219820Sjeffextern int uma_align_cache;
279219820Sjeff#define	dma_get_cache_alignment()	uma_align_cache
280219820Sjeff
281219820Sjeff#endif	/* _LINUX_DMA_MAPPING_H_ */
282