Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/drivers/base/dma-mapping.c
15109 views
1
/*
2
* drivers/base/dma-mapping.c - arch-independent dma-mapping routines
3
*
4
* Copyright (c) 2006 SUSE Linux Products GmbH
5
* Copyright (c) 2006 Tejun Heo <[email protected]>
6
*
7
* This file is released under the GPLv2.
8
*/
9
10
#include <linux/dma-mapping.h>
11
#include <linux/gfp.h>
12
13
/*
14
* Managed DMA API
15
*/
16
struct dma_devres {
17
size_t size;
18
void *vaddr;
19
dma_addr_t dma_handle;
20
};
21
22
static void dmam_coherent_release(struct device *dev, void *res)
23
{
24
struct dma_devres *this = res;
25
26
dma_free_coherent(dev, this->size, this->vaddr, this->dma_handle);
27
}
28
29
static void dmam_noncoherent_release(struct device *dev, void *res)
30
{
31
struct dma_devres *this = res;
32
33
dma_free_noncoherent(dev, this->size, this->vaddr, this->dma_handle);
34
}
35
36
static int dmam_match(struct device *dev, void *res, void *match_data)
37
{
38
struct dma_devres *this = res, *match = match_data;
39
40
if (this->vaddr == match->vaddr) {
41
WARN_ON(this->size != match->size ||
42
this->dma_handle != match->dma_handle);
43
return 1;
44
}
45
return 0;
46
}
47
48
/**
49
* dmam_alloc_coherent - Managed dma_alloc_coherent()
50
* @dev: Device to allocate coherent memory for
51
* @size: Size of allocation
52
* @dma_handle: Out argument for allocated DMA handle
53
* @gfp: Allocation flags
54
*
55
* Managed dma_alloc_coherent(). Memory allocated using this function
56
* will be automatically released on driver detach.
57
*
58
* RETURNS:
59
* Pointer to allocated memory on success, NULL on failure.
60
*/
61
void * dmam_alloc_coherent(struct device *dev, size_t size,
62
dma_addr_t *dma_handle, gfp_t gfp)
63
{
64
struct dma_devres *dr;
65
void *vaddr;
66
67
dr = devres_alloc(dmam_coherent_release, sizeof(*dr), gfp);
68
if (!dr)
69
return NULL;
70
71
vaddr = dma_alloc_coherent(dev, size, dma_handle, gfp);
72
if (!vaddr) {
73
devres_free(dr);
74
return NULL;
75
}
76
77
dr->vaddr = vaddr;
78
dr->dma_handle = *dma_handle;
79
dr->size = size;
80
81
devres_add(dev, dr);
82
83
return vaddr;
84
}
85
EXPORT_SYMBOL(dmam_alloc_coherent);
86
87
/**
88
* dmam_free_coherent - Managed dma_free_coherent()
89
* @dev: Device to free coherent memory for
90
* @size: Size of allocation
91
* @vaddr: Virtual address of the memory to free
92
* @dma_handle: DMA handle of the memory to free
93
*
94
* Managed dma_free_coherent().
95
*/
96
void dmam_free_coherent(struct device *dev, size_t size, void *vaddr,
97
dma_addr_t dma_handle)
98
{
99
struct dma_devres match_data = { size, vaddr, dma_handle };
100
101
dma_free_coherent(dev, size, vaddr, dma_handle);
102
WARN_ON(devres_destroy(dev, dmam_coherent_release, dmam_match,
103
&match_data));
104
}
105
EXPORT_SYMBOL(dmam_free_coherent);
106
107
/**
108
* dmam_alloc_non_coherent - Managed dma_alloc_non_coherent()
109
* @dev: Device to allocate non_coherent memory for
110
* @size: Size of allocation
111
* @dma_handle: Out argument for allocated DMA handle
112
* @gfp: Allocation flags
113
*
114
* Managed dma_alloc_non_coherent(). Memory allocated using this
115
* function will be automatically released on driver detach.
116
*
117
* RETURNS:
118
* Pointer to allocated memory on success, NULL on failure.
119
*/
120
void *dmam_alloc_noncoherent(struct device *dev, size_t size,
121
dma_addr_t *dma_handle, gfp_t gfp)
122
{
123
struct dma_devres *dr;
124
void *vaddr;
125
126
dr = devres_alloc(dmam_noncoherent_release, sizeof(*dr), gfp);
127
if (!dr)
128
return NULL;
129
130
vaddr = dma_alloc_noncoherent(dev, size, dma_handle, gfp);
131
if (!vaddr) {
132
devres_free(dr);
133
return NULL;
134
}
135
136
dr->vaddr = vaddr;
137
dr->dma_handle = *dma_handle;
138
dr->size = size;
139
140
devres_add(dev, dr);
141
142
return vaddr;
143
}
144
EXPORT_SYMBOL(dmam_alloc_noncoherent);
145
146
/**
147
* dmam_free_coherent - Managed dma_free_noncoherent()
148
* @dev: Device to free noncoherent memory for
149
* @size: Size of allocation
150
* @vaddr: Virtual address of the memory to free
151
* @dma_handle: DMA handle of the memory to free
152
*
153
* Managed dma_free_noncoherent().
154
*/
155
void dmam_free_noncoherent(struct device *dev, size_t size, void *vaddr,
156
dma_addr_t dma_handle)
157
{
158
struct dma_devres match_data = { size, vaddr, dma_handle };
159
160
dma_free_noncoherent(dev, size, vaddr, dma_handle);
161
WARN_ON(!devres_destroy(dev, dmam_noncoherent_release, dmam_match,
162
&match_data));
163
}
164
EXPORT_SYMBOL(dmam_free_noncoherent);
165
166
#ifdef ARCH_HAS_DMA_DECLARE_COHERENT_MEMORY
167
168
static void dmam_coherent_decl_release(struct device *dev, void *res)
169
{
170
dma_release_declared_memory(dev);
171
}
172
173
/**
174
* dmam_declare_coherent_memory - Managed dma_declare_coherent_memory()
175
* @dev: Device to declare coherent memory for
176
* @bus_addr: Bus address of coherent memory to be declared
177
* @device_addr: Device address of coherent memory to be declared
178
* @size: Size of coherent memory to be declared
179
* @flags: Flags
180
*
181
* Managed dma_declare_coherent_memory().
182
*
183
* RETURNS:
184
* 0 on success, -errno on failure.
185
*/
186
int dmam_declare_coherent_memory(struct device *dev, dma_addr_t bus_addr,
187
dma_addr_t device_addr, size_t size, int flags)
188
{
189
void *res;
190
int rc;
191
192
res = devres_alloc(dmam_coherent_decl_release, 0, GFP_KERNEL);
193
if (!res)
194
return -ENOMEM;
195
196
rc = dma_declare_coherent_memory(dev, bus_addr, device_addr, size,
197
flags);
198
if (rc == 0)
199
devres_add(dev, res);
200
else
201
devres_free(res);
202
203
return rc;
204
}
205
EXPORT_SYMBOL(dmam_declare_coherent_memory);
206
207
/**
208
* dmam_release_declared_memory - Managed dma_release_declared_memory().
209
* @dev: Device to release declared coherent memory for
210
*
211
* Managed dmam_release_declared_memory().
212
*/
213
void dmam_release_declared_memory(struct device *dev)
214
{
215
WARN_ON(devres_destroy(dev, dmam_coherent_decl_release, NULL, NULL));
216
}
217
EXPORT_SYMBOL(dmam_release_declared_memory);
218
219
#endif
220
221