Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2021 NVIDIA CORPORATION & AFFILIATES. All rights reserved.
3 : : */
4 : :
5 : : #include "spdk/dma.h"
6 : : #include "spdk/log.h"
7 : : #include "spdk/util.h"
8 : : #include "spdk/likely.h"
9 : :
10 : : pthread_mutex_t g_dma_mutex = PTHREAD_MUTEX_INITIALIZER;
11 : : TAILQ_HEAD(, spdk_memory_domain) g_dma_memory_domains = TAILQ_HEAD_INITIALIZER(
12 : : g_dma_memory_domains);
13 : :
14 : : struct spdk_memory_domain {
15 : : enum spdk_dma_device_type type;
16 : : spdk_memory_domain_pull_data_cb pull_cb;
17 : : spdk_memory_domain_push_data_cb push_cb;
18 : : spdk_memory_domain_translate_memory_cb translate_cb;
19 : : spdk_memory_domain_invalidate_data_cb invalidate_cb;
20 : : spdk_memory_domain_memzero_cb memzero_cb;
21 : : TAILQ_ENTRY(spdk_memory_domain) link;
22 : : struct spdk_memory_domain_ctx *ctx;
23 : : char *id;
24 : : };
25 : :
26 : : static struct spdk_memory_domain g_system_domain = {
27 : : .type = SPDK_DMA_DEVICE_TYPE_DMA,
28 : : .id = "system",
29 : : };
30 : :
31 : : static void
32 : : __attribute__((constructor))
33 : 2824 : _memory_domain_register(void)
34 : : {
35 : 2824 : TAILQ_INSERT_TAIL(&g_dma_memory_domains, &g_system_domain, link);
36 : 2824 : }
37 : :
38 : : struct spdk_memory_domain *
39 : 160259 : spdk_memory_domain_get_system_domain(void)
40 : : {
41 : 160259 : return &g_system_domain;
42 : : }
43 : :
44 : : int
45 : 2620 : spdk_memory_domain_create(struct spdk_memory_domain **_domain, enum spdk_dma_device_type type,
46 : : struct spdk_memory_domain_ctx *ctx, const char *id)
47 : : {
48 : : struct spdk_memory_domain *domain;
49 : : size_t ctx_size;
50 : :
51 [ + + ]: 2620 : if (!_domain) {
52 : 3 : return -EINVAL;
53 : : }
54 : :
55 [ + + + + ]: 2617 : if (ctx && ctx->size == 0) {
56 : 3 : SPDK_ERRLOG("Context size can't be 0\n");
57 : 3 : return -EINVAL;
58 : : }
59 : :
60 : 2614 : domain = calloc(1, sizeof(*domain));
61 [ - + ]: 2614 : if (!domain) {
62 : 0 : SPDK_ERRLOG("Failed to allocate memory");
63 : 0 : return -ENOMEM;
64 : : }
65 : :
66 [ + - ]: 2614 : if (id) {
67 [ - + ]: 2614 : domain->id = strdup(id);
68 [ - + ]: 2614 : if (!domain->id) {
69 : 0 : SPDK_ERRLOG("Failed to allocate memory");
70 : 0 : free(domain);
71 : 0 : return -ENOMEM;
72 : : }
73 : : }
74 : :
75 [ + + ]: 2614 : if (ctx) {
76 : 301 : domain->ctx = calloc(1, sizeof(*domain->ctx));
77 [ - + ]: 301 : if (!domain->ctx) {
78 : 0 : SPDK_ERRLOG("Failed to allocate memory");
79 : 0 : free(domain->id);
80 : 0 : free(domain);
81 : 0 : return -ENOMEM;
82 : : }
83 : :
84 : 301 : ctx_size = spdk_min(sizeof(*domain->ctx), ctx->size);
85 [ - + - + ]: 301 : memcpy(domain->ctx, ctx, ctx_size);
86 : 301 : domain->ctx->size = ctx_size;
87 : : }
88 : :
89 : 2614 : domain->type = type;
90 : :
91 [ - + ]: 2614 : pthread_mutex_lock(&g_dma_mutex);
92 : 2614 : TAILQ_INSERT_TAIL(&g_dma_memory_domains, domain, link);
93 [ - + ]: 2614 : pthread_mutex_unlock(&g_dma_mutex);
94 : :
95 : 2614 : *_domain = domain;
96 : :
97 : 2614 : return 0;
98 : : }
99 : :
100 : : void
101 : 2322 : spdk_memory_domain_set_translation(struct spdk_memory_domain *domain,
102 : : spdk_memory_domain_translate_memory_cb translate_cb)
103 : : {
104 [ - + ]: 2322 : assert(domain);
105 : :
106 : 2322 : domain->translate_cb = translate_cb;
107 : 2322 : }
108 : :
109 : : void
110 : 2309 : spdk_memory_domain_set_invalidate(struct spdk_memory_domain *domain,
111 : : spdk_memory_domain_invalidate_data_cb invalidate_cb)
112 : : {
113 [ - + ]: 2309 : assert(domain);
114 : :
115 : 2309 : domain->invalidate_cb = invalidate_cb;
116 : 2309 : }
117 : :
118 : : void
119 : 13 : spdk_memory_domain_set_pull(struct spdk_memory_domain *domain,
120 : : spdk_memory_domain_pull_data_cb pull_cb)
121 : : {
122 [ - + ]: 13 : assert(domain);
123 : :
124 : 13 : domain->pull_cb = pull_cb;
125 : 13 : }
126 : :
127 : : void
128 : 7 : spdk_memory_domain_set_push(struct spdk_memory_domain *domain,
129 : : spdk_memory_domain_push_data_cb push_cb)
130 : : {
131 [ - + ]: 7 : assert(domain);
132 : :
133 : 7 : domain->push_cb = push_cb;
134 : 7 : }
135 : :
136 : : void
137 : 13 : spdk_memory_domain_set_memzero(struct spdk_memory_domain *domain,
138 : : spdk_memory_domain_memzero_cb memzero_cb)
139 : : {
140 [ - + ]: 13 : assert(domain);
141 : :
142 : 13 : domain->memzero_cb = memzero_cb;
143 : 13 : }
144 : :
145 : : struct spdk_memory_domain_ctx *
146 : 3 : spdk_memory_domain_get_context(struct spdk_memory_domain *domain)
147 : : {
148 [ - + ]: 3 : assert(domain);
149 : :
150 : 3 : return domain->ctx;
151 : : }
152 : :
153 : : /* We have to use the typedef in the function declaration to appease astyle. */
154 : : typedef enum spdk_dma_device_type spdk_dma_device_type_t;
155 : :
156 : : spdk_dma_device_type_t
157 : 38196 : spdk_memory_domain_get_dma_device_type(struct spdk_memory_domain *domain)
158 : : {
159 [ - + ]: 38196 : assert(domain);
160 : :
161 : 38196 : return domain->type;
162 : : }
163 : :
164 : : const char *
165 : 38191 : spdk_memory_domain_get_dma_device_id(struct spdk_memory_domain *domain)
166 : : {
167 [ - + ]: 38191 : assert(domain);
168 : :
169 : 38191 : return domain->id;
170 : : }
171 : :
172 : : void
173 : 2606 : spdk_memory_domain_destroy(struct spdk_memory_domain *domain)
174 : : {
175 [ + + ]: 2606 : if (!domain) {
176 : 3 : return;
177 : : }
178 : :
179 [ - + ]: 2603 : assert(domain != &g_system_domain);
180 : :
181 [ - + ]: 2603 : pthread_mutex_lock(&g_dma_mutex);
182 [ + + ]: 2603 : TAILQ_REMOVE(&g_dma_memory_domains, domain, link);
183 [ - + ]: 2603 : pthread_mutex_unlock(&g_dma_mutex);
184 : :
185 : 2603 : free(domain->ctx);
186 : 2603 : free(domain->id);
187 : 2603 : free(domain);
188 : : }
189 : :
190 : : int
191 : 178558 : spdk_memory_domain_pull_data(struct spdk_memory_domain *src_domain, void *src_domain_ctx,
192 : : struct iovec *src_iov, uint32_t src_iov_cnt, struct iovec *dst_iov, uint32_t dst_iov_cnt,
193 : : spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
194 : : {
195 [ - + ]: 178558 : assert(src_domain);
196 [ - + ]: 178558 : assert(src_iov);
197 [ - + ]: 178558 : assert(dst_iov);
198 : :
199 [ + + ]: 178558 : if (spdk_unlikely(!src_domain->pull_cb)) {
200 : 3 : return -ENOTSUP;
201 : : }
202 : :
203 : 178555 : return src_domain->pull_cb(src_domain, src_domain_ctx, src_iov, src_iov_cnt, dst_iov, dst_iov_cnt,
204 : : cpl_cb, cpl_cb_arg);
205 : : }
206 : :
207 : : int
208 : 417290 : spdk_memory_domain_push_data(struct spdk_memory_domain *dst_domain, void *dst_domain_ctx,
209 : : struct iovec *dst_iov, uint32_t dst_iovcnt, struct iovec *src_iov, uint32_t src_iovcnt,
210 : : spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
211 : : {
212 [ - + ]: 417290 : assert(dst_domain);
213 [ - + ]: 417290 : assert(dst_iov);
214 [ - + ]: 417290 : assert(src_iov);
215 : :
216 [ + + ]: 417290 : if (spdk_unlikely(!dst_domain->push_cb)) {
217 : 3 : return -ENOTSUP;
218 : : }
219 : :
220 : 417287 : return dst_domain->push_cb(dst_domain, dst_domain_ctx, dst_iov, dst_iovcnt, src_iov, src_iovcnt,
221 : : cpl_cb, cpl_cb_arg);
222 : : }
223 : :
224 : : int
225 : 498168 : spdk_memory_domain_translate_data(struct spdk_memory_domain *src_domain, void *src_domain_ctx,
226 : : struct spdk_memory_domain *dst_domain, struct spdk_memory_domain_translation_ctx *dst_domain_ctx,
227 : : void *addr, size_t len, struct spdk_memory_domain_translation_result *result)
228 : : {
229 [ - + ]: 498168 : assert(src_domain);
230 [ - + ]: 498168 : assert(dst_domain);
231 [ - + ]: 498168 : assert(result);
232 : :
233 [ + + ]: 498168 : if (spdk_unlikely(!src_domain->translate_cb)) {
234 : 3 : return -ENOTSUP;
235 : : }
236 : :
237 : 498165 : return src_domain->translate_cb(src_domain, src_domain_ctx, dst_domain, dst_domain_ctx, addr, len,
238 : : result);
239 : : }
240 : :
241 : : void
242 : 80038 : spdk_memory_domain_invalidate_data(struct spdk_memory_domain *domain, void *domain_ctx,
243 : : struct iovec *iov, uint32_t iovcnt)
244 : : {
245 [ - + ]: 80038 : assert(domain);
246 : :
247 [ - + ]: 80038 : if (spdk_unlikely(!domain->invalidate_cb)) {
248 : 0 : return;
249 : : }
250 : :
251 : 80038 : domain->invalidate_cb(domain, domain_ctx, iov, iovcnt);
252 : : }
253 : :
254 : : int
255 : 788992 : spdk_memory_domain_memzero(struct spdk_memory_domain *domain, void *domain_ctx, struct iovec *iov,
256 : : uint32_t iovcnt, spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
257 : : {
258 [ - + ]: 788992 : assert(domain);
259 [ - + ]: 788992 : assert(iov);
260 [ - + ]: 788992 : assert(iovcnt);
261 : :
262 [ + + ]: 788992 : if (spdk_unlikely(!domain->memzero_cb)) {
263 : 3 : return -ENOTSUP;
264 : : }
265 : :
266 : 788989 : return domain->memzero_cb(domain, domain_ctx, iov, iovcnt, cpl_cb, cpl_cb_arg);
267 : : }
268 : :
269 : : struct spdk_memory_domain *
270 : 85388 : spdk_memory_domain_get_first(const char *id)
271 : : {
272 : : struct spdk_memory_domain *domain;
273 : :
274 [ + + ]: 85388 : if (!id) {
275 : 85379 : pthread_mutex_lock(&g_dma_mutex);
276 : 85379 : domain = TAILQ_FIRST(&g_dma_memory_domains);
277 : 85379 : pthread_mutex_unlock(&g_dma_mutex);
278 : :
279 : 85379 : return domain;
280 : : }
281 : :
282 : 9 : pthread_mutex_lock(&g_dma_mutex);
283 [ + + ]: 24 : TAILQ_FOREACH(domain, &g_dma_memory_domains, link) {
284 [ + + - + : 21 : if (!strcmp(domain->id, id)) {
+ + ]
285 : 6 : break;
286 : : }
287 : : }
288 : 9 : pthread_mutex_unlock(&g_dma_mutex);
289 : :
290 : 9 : return domain;
291 : : }
292 : :
293 : : struct spdk_memory_domain *
294 : 170766 : spdk_memory_domain_get_next(struct spdk_memory_domain *prev, const char *id)
295 : : {
296 : : struct spdk_memory_domain *domain;
297 : :
298 [ - + ]: 170766 : if (!prev) {
299 : 0 : return NULL;
300 : : }
301 : :
302 : 170766 : pthread_mutex_lock(&g_dma_mutex);
303 : 170766 : domain = TAILQ_NEXT(prev, link);
304 : 170766 : pthread_mutex_unlock(&g_dma_mutex);
305 : :
306 [ + + + + ]: 170766 : if (!id || !domain) {
307 : 170760 : return domain;
308 : : }
309 : :
310 : 6 : pthread_mutex_lock(&g_dma_mutex);
311 [ - + + + ]: 12 : TAILQ_FOREACH_FROM(domain, &g_dma_memory_domains, link) {
312 [ + + - + : 9 : if (!strcmp(domain->id, id)) {
+ + ]
313 : 3 : break;
314 : : }
315 : : }
316 : 6 : pthread_mutex_unlock(&g_dma_mutex);
317 : :
318 : 6 : return domain;
319 : : }
|