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 : : static pthread_mutex_t g_dma_mutex = PTHREAD_MUTEX_INITIALIZER;
11 : : static 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_transfer_data_cb transfer_cb;
19 : : spdk_memory_domain_translate_memory_cb translate_cb;
20 : : spdk_memory_domain_invalidate_data_cb invalidate_cb;
21 : : spdk_memory_domain_memzero_cb memzero_cb;
22 : : TAILQ_ENTRY(spdk_memory_domain) link;
23 : : struct spdk_memory_domain_ctx *ctx;
24 : : char *id;
25 : : size_t user_ctx_size;
26 : : uint8_t user_ctx[];
27 : : };
28 : :
29 : : static struct spdk_memory_domain g_system_domain = {
30 : : .type = SPDK_DMA_DEVICE_TYPE_DMA,
31 : : .id = "system",
32 : : };
33 : :
34 : : static void
35 : : __attribute__((constructor))
36 : 2687 : _memory_domain_register(void)
37 : : {
38 [ + - + - : 2687 : TAILQ_INSERT_TAIL(&g_dma_memory_domains, &g_system_domain, link);
+ - + - +
- + - + -
+ - + - ]
39 : 2687 : }
40 : :
41 : : struct spdk_memory_domain *
42 : 155889 : spdk_memory_domain_get_system_domain(void)
43 : : {
44 : 155889 : return &g_system_domain;
45 : : }
46 : :
47 : : int
48 : 2439 : spdk_memory_domain_create(struct spdk_memory_domain **_domain, enum spdk_dma_device_type type,
49 : : struct spdk_memory_domain_ctx *ctx, const char *id)
50 : : {
51 : : struct spdk_memory_domain *domain;
52 : 2439 : size_t ctx_size, user_ctx_size = 0;
53 : :
54 [ + + ]: 2439 : if (!_domain) {
55 : 3 : return -EINVAL;
56 : : }
57 : :
58 [ + + ]: 2436 : if (ctx) {
59 [ + + # # : 329 : if (ctx->size == 0) {
# # ]
60 : 3 : SPDK_ERRLOG("Context size can't be 0\n");
61 : 3 : return -EINVAL;
62 : : }
63 [ + - # # : 326 : if (ctx->user_ctx &&
# # # # ]
64 [ + - # # ]: 326 : offsetof(struct spdk_memory_domain_ctx, user_ctx_size) + sizeof(ctx->user_ctx_size) <= ctx->size) {
65 [ # # # # ]: 326 : user_ctx_size = ctx->user_ctx_size;
66 : 0 : }
67 : 0 : }
68 : :
69 : 2433 : domain = calloc(1, sizeof(*domain) + user_ctx_size);
70 [ + + ]: 2433 : if (!domain) {
71 : 0 : SPDK_ERRLOG("Failed to allocate memory");
72 : 0 : return -ENOMEM;
73 : : }
74 : :
75 [ + + ]: 2433 : if (id) {
76 [ + + + - : 2433 : domain->id = strdup(id);
+ - ]
77 [ + + + - : 2433 : if (!domain->id) {
+ - ]
78 : 0 : SPDK_ERRLOG("Failed to allocate memory");
79 : 0 : free(domain);
80 : 0 : return -ENOMEM;
81 : : }
82 : 58 : }
83 : :
84 [ + + ]: 2433 : if (ctx) {
85 [ # # # # ]: 326 : domain->ctx = calloc(1, sizeof(*domain->ctx));
86 [ - + # # : 326 : if (!domain->ctx) {
# # ]
87 : 0 : SPDK_ERRLOG("Failed to allocate memory");
88 [ # # # # ]: 0 : free(domain->id);
89 : 0 : free(domain);
90 : 0 : return -ENOMEM;
91 : : }
92 : :
93 [ # # # # : 326 : ctx_size = spdk_min(sizeof(*domain->ctx), ctx->size);
# # # # #
# ]
94 [ - + - + : 326 : memcpy(domain->ctx, ctx, ctx_size);
# # # # ]
95 [ # # # # : 326 : domain->ctx->size = ctx_size;
# # # # ]
96 : 0 : }
97 : :
98 [ + + ]: 2433 : if (user_ctx_size) {
99 [ - + # # ]: 317 : assert(ctx);
100 [ - + - + : 317 : memcpy(domain->user_ctx, ctx->user_ctx, user_ctx_size);
# # # # #
# ]
101 [ # # # # ]: 317 : domain->user_ctx_size = user_ctx_size;
102 : 0 : }
103 : :
104 [ + - + - ]: 2433 : domain->type = type;
105 : :
106 [ + + ]: 2433 : pthread_mutex_lock(&g_dma_mutex);
107 [ + - + - : 2433 : TAILQ_INSERT_TAIL(&g_dma_memory_domains, domain, link);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
108 [ + + ]: 2433 : pthread_mutex_unlock(&g_dma_mutex);
109 : :
110 [ + - ]: 2433 : *_domain = domain;
111 : :
112 : 2433 : return 0;
113 : 58 : }
114 : :
115 : : void
116 : 2116 : spdk_memory_domain_set_translation(struct spdk_memory_domain *domain,
117 : : spdk_memory_domain_translate_memory_cb translate_cb)
118 : : {
119 [ + + # # ]: 2116 : assert(domain);
120 : :
121 [ + - + - ]: 2116 : domain->translate_cb = translate_cb;
122 : 2116 : }
123 : :
124 : : void
125 : 2103 : spdk_memory_domain_set_invalidate(struct spdk_memory_domain *domain,
126 : : spdk_memory_domain_invalidate_data_cb invalidate_cb)
127 : : {
128 [ + + # # ]: 2103 : assert(domain);
129 : :
130 [ + - + - ]: 2103 : domain->invalidate_cb = invalidate_cb;
131 : 2103 : }
132 : :
133 : : void
134 : 13 : spdk_memory_domain_set_pull(struct spdk_memory_domain *domain,
135 : : spdk_memory_domain_pull_data_cb pull_cb)
136 : : {
137 [ - + # # ]: 13 : assert(domain);
138 : :
139 [ # # # # ]: 13 : domain->pull_cb = pull_cb;
140 : 13 : }
141 : :
142 : : void
143 : 7 : spdk_memory_domain_set_push(struct spdk_memory_domain *domain,
144 : : spdk_memory_domain_push_data_cb push_cb)
145 : : {
146 [ - + # # ]: 7 : assert(domain);
147 : :
148 [ # # # # ]: 7 : domain->push_cb = push_cb;
149 : 7 : }
150 : :
151 : : void
152 : 0 : spdk_memory_domain_set_data_transfer(struct spdk_memory_domain *domain,
153 : : spdk_memory_domain_transfer_data_cb transfer_cb)
154 : : {
155 [ # # # # ]: 0 : assert(domain);
156 : :
157 [ # # # # ]: 0 : domain->transfer_cb = transfer_cb;
158 : 0 : }
159 : :
160 : : void
161 : 13 : spdk_memory_domain_set_memzero(struct spdk_memory_domain *domain,
162 : : spdk_memory_domain_memzero_cb memzero_cb)
163 : : {
164 [ - + # # ]: 13 : assert(domain);
165 : :
166 [ # # # # ]: 13 : domain->memzero_cb = memzero_cb;
167 : 13 : }
168 : :
169 : : struct spdk_memory_domain_ctx *
170 : 3 : spdk_memory_domain_get_context(struct spdk_memory_domain *domain)
171 : : {
172 [ - + # # ]: 3 : assert(domain);
173 : :
174 [ # # # # ]: 3 : return domain->ctx;
175 : : }
176 : :
177 : : void *
178 : 0 : spdk_memory_domain_get_user_context(struct spdk_memory_domain *domain, size_t *ctx_size)
179 : : {
180 [ # # # # ]: 0 : assert(domain);
181 : :
182 [ # # # # : 0 : if (!domain->user_ctx_size) {
# # ]
183 : 0 : return NULL;
184 : : }
185 : :
186 [ # # # # : 0 : *ctx_size = domain->user_ctx_size;
# # ]
187 [ # # ]: 0 : return domain->user_ctx;
188 : 0 : }
189 : :
190 : : /* We have to use the typedef in the function declaration to appease astyle. */
191 : : typedef enum spdk_dma_device_type spdk_dma_device_type_t;
192 : :
193 : : spdk_dma_device_type_t
194 : 42629 : spdk_memory_domain_get_dma_device_type(struct spdk_memory_domain *domain)
195 : : {
196 [ + + # # ]: 42629 : assert(domain);
197 : :
198 [ + - + - ]: 42629 : return domain->type;
199 : : }
200 : :
201 : : const char *
202 : 42624 : spdk_memory_domain_get_dma_device_id(struct spdk_memory_domain *domain)
203 : : {
204 [ + + # # ]: 42624 : assert(domain);
205 : :
206 [ + - + - ]: 42624 : return domain->id;
207 : : }
208 : :
209 : : void
210 : 2423 : spdk_memory_domain_destroy(struct spdk_memory_domain *domain)
211 : : {
212 [ + + ]: 2423 : if (!domain) {
213 : 3 : return;
214 : : }
215 : :
216 [ + + # # ]: 2420 : assert(domain != &g_system_domain);
217 : :
218 [ + + ]: 2420 : pthread_mutex_lock(&g_dma_mutex);
219 [ + + + - : 2420 : TAILQ_REMOVE(&g_dma_memory_domains, domain, link);
+ - - + #
# # # # #
# # # # #
# # # # #
# # + - +
- + - + -
+ - + - +
- + - + -
+ - + - ]
220 [ + + ]: 2420 : pthread_mutex_unlock(&g_dma_mutex);
221 : :
222 [ + - + - ]: 2420 : free(domain->ctx);
223 [ + - + - ]: 2420 : free(domain->id);
224 : 2420 : free(domain);
225 : 58 : }
226 : :
227 : : int
228 : 174926 : spdk_memory_domain_pull_data(struct spdk_memory_domain *src_domain, void *src_domain_ctx,
229 : : struct iovec *src_iov, uint32_t src_iov_cnt, struct iovec *dst_iov, uint32_t dst_iov_cnt,
230 : : spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
231 : : {
232 [ - + # # ]: 174926 : assert(src_domain);
233 [ - + # # ]: 174926 : assert(src_iov);
234 [ - + # # ]: 174926 : assert(dst_iov);
235 : :
236 [ + + # # : 174926 : if (spdk_unlikely(!src_domain->pull_cb)) {
# # ]
237 : 3 : return -ENOTSUP;
238 : : }
239 : :
240 [ # # # # : 174923 : return src_domain->pull_cb(src_domain, src_domain_ctx, src_iov, src_iov_cnt, dst_iov, dst_iov_cnt,
# # # # ]
241 : 0 : cpl_cb, cpl_cb_arg);
242 : 0 : }
243 : :
244 : : int
245 : 408854 : spdk_memory_domain_push_data(struct spdk_memory_domain *dst_domain, void *dst_domain_ctx,
246 : : struct iovec *dst_iov, uint32_t dst_iovcnt, struct iovec *src_iov, uint32_t src_iovcnt,
247 : : spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
248 : : {
249 [ - + # # ]: 408854 : assert(dst_domain);
250 [ - + # # ]: 408854 : assert(dst_iov);
251 [ - + # # ]: 408854 : assert(src_iov);
252 : :
253 [ + + # # : 408854 : if (spdk_unlikely(!dst_domain->push_cb)) {
# # ]
254 : 3 : return -ENOTSUP;
255 : : }
256 : :
257 [ # # # # : 408851 : return dst_domain->push_cb(dst_domain, dst_domain_ctx, dst_iov, dst_iovcnt, src_iov, src_iovcnt,
# # # # ]
258 : 0 : cpl_cb, cpl_cb_arg);
259 : 0 : }
260 : :
261 : : int
262 : 0 : spdk_memory_domain_transfer_data(struct spdk_memory_domain *dst_domain, void *dst_domain_ctx,
263 : : struct iovec *dst_iov, uint32_t dst_iovcnt,
264 : : struct spdk_memory_domain *src_domain, void *src_domain_ctx,
265 : : struct iovec *src_iov, uint32_t src_iovcnt,
266 : : struct spdk_memory_domain_translation_result *src_translation,
267 : : spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
268 : : {
269 [ # # # # ]: 0 : assert(dst_domain);
270 [ # # # # ]: 0 : assert(dst_iov);
271 [ # # # # ]: 0 : assert(src_iov);
272 : :
273 [ # # # # : 0 : if (spdk_unlikely(!dst_domain->transfer_cb)) {
# # ]
274 : 0 : return -ENOTSUP;
275 : : }
276 : :
277 [ # # # # : 0 : return dst_domain->transfer_cb(dst_domain, dst_domain_ctx, dst_iov, dst_iovcnt, src_domain,
# # # # ]
278 : 0 : src_domain_ctx, src_iov, src_iovcnt,
279 : 0 : src_translation, cpl_cb, cpl_cb_arg);
280 : 0 : }
281 : :
282 : : int
283 : 487760 : spdk_memory_domain_translate_data(struct spdk_memory_domain *src_domain, void *src_domain_ctx,
284 : : struct spdk_memory_domain *dst_domain, struct spdk_memory_domain_translation_ctx *dst_domain_ctx,
285 : : void *addr, size_t len, struct spdk_memory_domain_translation_result *result)
286 : : {
287 [ - + # # ]: 487760 : assert(src_domain);
288 [ - + # # ]: 487760 : assert(dst_domain);
289 [ - + # # ]: 487760 : assert(result);
290 : :
291 [ + + # # : 487760 : if (spdk_unlikely(!src_domain->translate_cb)) {
# # ]
292 : 3 : return -ENOTSUP;
293 : : }
294 : :
295 [ # # # # : 487757 : return src_domain->translate_cb(src_domain, src_domain_ctx, dst_domain, dst_domain_ctx, addr, len,
# # # # ]
296 : 0 : result);
297 : 0 : }
298 : :
299 : : void
300 : 77833 : spdk_memory_domain_invalidate_data(struct spdk_memory_domain *domain, void *domain_ctx,
301 : : struct iovec *iov, uint32_t iovcnt)
302 : : {
303 [ - + # # ]: 77833 : assert(domain);
304 : :
305 [ - + # # : 77833 : if (spdk_unlikely(!domain->invalidate_cb)) {
# # ]
306 : 0 : return;
307 : : }
308 : :
309 [ # # # # : 77833 : domain->invalidate_cb(domain, domain_ctx, iov, iovcnt);
# # # # ]
310 : 0 : }
311 : :
312 : : int
313 : 668459 : spdk_memory_domain_memzero(struct spdk_memory_domain *domain, void *domain_ctx, struct iovec *iov,
314 : : uint32_t iovcnt, spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
315 : : {
316 [ - + # # ]: 668459 : assert(domain);
317 [ - + # # ]: 668459 : assert(iov);
318 [ - + # # ]: 668459 : assert(iovcnt);
319 : :
320 [ + + # # : 668459 : if (spdk_unlikely(!domain->memzero_cb)) {
# # ]
321 : 3 : return -ENOTSUP;
322 : : }
323 : :
324 [ # # # # : 668456 : return domain->memzero_cb(domain, domain_ctx, iov, iovcnt, cpl_cb, cpl_cb_arg);
# # # # ]
325 : 0 : }
326 : :
327 : : struct spdk_memory_domain *
328 : 81401 : spdk_memory_domain_get_first(const char *id)
329 : : {
330 : : struct spdk_memory_domain *domain;
331 : :
332 [ + + ]: 81401 : if (!id) {
333 [ + - ]: 81392 : pthread_mutex_lock(&g_dma_mutex);
334 : 81392 : domain = TAILQ_FIRST(&g_dma_memory_domains);
335 [ + - ]: 81392 : pthread_mutex_unlock(&g_dma_mutex);
336 : :
337 : 81392 : return domain;
338 : : }
339 : :
340 [ # # ]: 9 : pthread_mutex_lock(&g_dma_mutex);
341 [ + + # # : 24 : TAILQ_FOREACH(domain, &g_dma_memory_domains, link) {
# # # # ]
342 [ + + - + : 21 : if (!strcmp(domain->id, id)) {
+ + # # #
# ]
343 : 6 : break;
344 : : }
345 : 0 : }
346 [ # # ]: 9 : pthread_mutex_unlock(&g_dma_mutex);
347 : :
348 : 9 : return domain;
349 : 263 : }
350 : :
351 : : struct spdk_memory_domain *
352 : 162792 : spdk_memory_domain_get_next(struct spdk_memory_domain *prev, const char *id)
353 : : {
354 : : struct spdk_memory_domain *domain;
355 : :
356 [ + + ]: 162792 : if (!prev) {
357 : 0 : return NULL;
358 : : }
359 : :
360 [ + - ]: 162792 : pthread_mutex_lock(&g_dma_mutex);
361 [ + - + - : 162792 : domain = TAILQ_NEXT(prev, link);
+ - ]
362 [ + - ]: 162792 : pthread_mutex_unlock(&g_dma_mutex);
363 : :
364 [ + + + + ]: 162792 : if (!id || !domain) {
365 : 162786 : return domain;
366 : : }
367 : :
368 [ # # ]: 6 : pthread_mutex_lock(&g_dma_mutex);
369 [ - + + + : 12 : TAILQ_FOREACH_FROM(domain, &g_dma_memory_domains, link) {
# # # # #
# ]
370 [ + + - + : 9 : if (!strcmp(domain->id, id)) {
+ + # # #
# ]
371 : 3 : break;
372 : : }
373 : 0 : }
374 [ # # ]: 6 : pthread_mutex_unlock(&g_dma_mutex);
375 : :
376 : 6 : return domain;
377 : 526 : }
|