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 : 2659 : _memory_domain_register(void)
37 : : {
38 [ + - + - : 2659 : TAILQ_INSERT_TAIL(&g_dma_memory_domains, &g_system_domain, link);
+ - + - +
- + - + -
+ - + - ]
39 : 2659 : }
40 : :
41 : : struct spdk_memory_domain *
42 : 157761 : spdk_memory_domain_get_system_domain(void)
43 : : {
44 : 157761 : return &g_system_domain;
45 : : }
46 : :
47 : : int
48 : 2768 : 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 : 2768 : size_t ctx_size, user_ctx_size = 0;
53 : :
54 [ + + ]: 2768 : if (!_domain) {
55 : 4 : return -EINVAL;
56 : : }
57 : :
58 [ + + ]: 2764 : if (ctx) {
59 [ + + # # : 660 : if (ctx->size == 0) {
# # ]
60 : 4 : SPDK_ERRLOG("Context size can't be 0\n");
61 : 4 : return -EINVAL;
62 : : }
63 [ + - - + : 656 : if (ctx->user_ctx &&
# # # # ]
64 [ + - # # ]: 656 : offsetof(struct spdk_memory_domain_ctx, user_ctx_size) + sizeof(ctx->user_ctx_size) <= ctx->size) {
65 [ # # # # ]: 656 : user_ctx_size = ctx->user_ctx_size;
66 : 3 : }
67 : 3 : }
68 : :
69 : 2760 : domain = calloc(1, sizeof(*domain) + user_ctx_size);
70 [ + + ]: 2760 : if (!domain) {
71 : 0 : SPDK_ERRLOG("Failed to allocate memory");
72 : 0 : return -ENOMEM;
73 : : }
74 : :
75 [ + + ]: 2760 : if (id) {
76 [ + + + - : 2760 : domain->id = strdup(id);
+ - ]
77 [ + + + - : 2760 : if (!domain->id) {
+ - ]
78 : 0 : SPDK_ERRLOG("Failed to allocate memory");
79 : 0 : free(domain);
80 : 0 : return -ENOMEM;
81 : : }
82 : 97 : }
83 : :
84 [ + + ]: 2760 : if (ctx) {
85 [ # # # # ]: 656 : domain->ctx = calloc(1, sizeof(*domain->ctx));
86 [ + + # # : 656 : 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 [ - + # # : 656 : ctx_size = spdk_min(sizeof(*domain->ctx), ctx->size);
# # # # #
# ]
94 [ - + - + : 656 : memcpy(domain->ctx, ctx, ctx_size);
# # # # ]
95 [ # # # # : 656 : domain->ctx->size = ctx_size;
# # # # ]
96 : 3 : }
97 : :
98 [ + + ]: 2760 : if (user_ctx_size) {
99 [ - + # # ]: 644 : assert(ctx);
100 [ - + - + : 644 : memcpy(domain->user_ctx, ctx->user_ctx, user_ctx_size);
# # # # #
# ]
101 [ # # # # ]: 644 : domain->user_ctx_size = user_ctx_size;
102 : 0 : }
103 : :
104 [ + - + - ]: 2760 : domain->type = type;
105 : :
106 [ + + ]: 2760 : pthread_mutex_lock(&g_dma_mutex);
107 [ + - + - : 2760 : TAILQ_INSERT_TAIL(&g_dma_memory_domains, domain, link);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
108 [ + + ]: 2760 : pthread_mutex_unlock(&g_dma_mutex);
109 : :
110 [ + - ]: 2760 : *_domain = domain;
111 : :
112 : 2760 : return 0;
113 : 99 : }
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 : 2100 : spdk_memory_domain_set_invalidate(struct spdk_memory_domain *domain,
126 : : spdk_memory_domain_invalidate_data_cb invalidate_cb)
127 : : {
128 [ + + # # ]: 2100 : assert(domain);
129 : :
130 [ + - + - ]: 2100 : domain->invalidate_cb = invalidate_cb;
131 : 2100 : }
132 : :
133 : : void
134 : 16 : spdk_memory_domain_set_pull(struct spdk_memory_domain *domain,
135 : : spdk_memory_domain_pull_data_cb pull_cb)
136 : : {
137 [ + + # # ]: 16 : assert(domain);
138 : :
139 [ # # # # ]: 16 : domain->pull_cb = pull_cb;
140 : 16 : }
141 : :
142 : : void
143 : 8 : spdk_memory_domain_set_push(struct spdk_memory_domain *domain,
144 : : spdk_memory_domain_push_data_cb push_cb)
145 : : {
146 [ + + # # ]: 8 : assert(domain);
147 : :
148 [ # # # # ]: 8 : domain->push_cb = push_cb;
149 : 8 : }
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 : 16 : spdk_memory_domain_set_memzero(struct spdk_memory_domain *domain,
162 : : spdk_memory_domain_memzero_cb memzero_cb)
163 : : {
164 [ + + # # ]: 16 : assert(domain);
165 : :
166 [ # # # # ]: 16 : domain->memzero_cb = memzero_cb;
167 : 16 : }
168 : :
169 : : struct spdk_memory_domain_ctx *
170 : 4 : spdk_memory_domain_get_context(struct spdk_memory_domain *domain)
171 : : {
172 [ + + # # ]: 4 : assert(domain);
173 : :
174 [ # # # # ]: 4 : 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 : 42685 : spdk_memory_domain_get_dma_device_type(struct spdk_memory_domain *domain)
195 : : {
196 [ + + # # ]: 42685 : assert(domain);
197 : :
198 [ + - + - ]: 42685 : return domain->type;
199 : : }
200 : :
201 : : const char *
202 : 42680 : spdk_memory_domain_get_dma_device_id(struct spdk_memory_domain *domain)
203 : : {
204 [ + + # # ]: 42680 : assert(domain);
205 : :
206 [ + - + - ]: 42680 : return domain->id;
207 : : }
208 : :
209 : : void
210 : 2760 : spdk_memory_domain_destroy(struct spdk_memory_domain *domain)
211 : : {
212 [ + + ]: 2760 : if (!domain) {
213 : 4 : return;
214 : : }
215 : :
216 [ + + # # ]: 2756 : assert(domain != &g_system_domain);
217 : :
218 [ + + ]: 2756 : pthread_mutex_lock(&g_dma_mutex);
219 [ + + + - : 2756 : TAILQ_REMOVE(&g_dma_memory_domains, domain, link);
+ - - + #
# # # # #
# # # # #
# # # # #
# # + - +
- + - + -
+ - + - +
- + - + -
+ - + - ]
220 [ + + ]: 2756 : pthread_mutex_unlock(&g_dma_mutex);
221 : :
222 [ + - + - ]: 2756 : free(domain->ctx);
223 [ + - + - ]: 2756 : free(domain->id);
224 : 2756 : free(domain);
225 : 98 : }
226 : :
227 : : int
228 : 167080 : 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 [ + + # # ]: 167080 : assert(src_domain);
233 [ + + # # ]: 167080 : assert(src_iov);
234 [ - + # # ]: 167080 : assert(dst_iov);
235 : :
236 [ + + # # : 167080 : if (spdk_unlikely(!src_domain->pull_cb)) {
# # ]
237 : 4 : return -ENOTSUP;
238 : : }
239 : :
240 [ # # # # : 167077 : return src_domain->pull_cb(src_domain, src_domain_ctx, src_iov, src_iov_cnt, dst_iov, dst_iov_cnt,
# # # # ]
241 : 1 : cpl_cb, cpl_cb_arg);
242 : 2 : }
243 : :
244 : : int
245 : 390604 : 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 [ + + # # ]: 390604 : assert(dst_domain);
250 [ + + # # ]: 390604 : assert(dst_iov);
251 [ - + # # ]: 390604 : assert(src_iov);
252 : :
253 [ + + # # : 390604 : if (spdk_unlikely(!dst_domain->push_cb)) {
# # ]
254 : 4 : return -ENOTSUP;
255 : : }
256 : :
257 [ # # # # : 390601 : return dst_domain->push_cb(dst_domain, dst_domain_ctx, dst_iov, dst_iovcnt, src_iov, src_iovcnt,
# # # # ]
258 : 1 : cpl_cb, cpl_cb_arg);
259 : 2 : }
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 : 476088 : 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 [ + + # # ]: 476088 : assert(src_domain);
288 [ + + # # ]: 476088 : assert(dst_domain);
289 [ - + # # ]: 476088 : assert(result);
290 : :
291 [ + + # # : 476088 : if (spdk_unlikely(!src_domain->translate_cb)) {
# # ]
292 : 4 : return -ENOTSUP;
293 : : }
294 : :
295 [ # # # # : 476085 : return src_domain->translate_cb(src_domain, src_domain_ctx, dst_domain, dst_domain_ctx, addr, len,
# # # # ]
296 : 1 : result);
297 : 2 : }
298 : :
299 : : void
300 : 78770 : spdk_memory_domain_invalidate_data(struct spdk_memory_domain *domain, void *domain_ctx,
301 : : struct iovec *iov, uint32_t iovcnt)
302 : : {
303 [ - + # # ]: 78770 : assert(domain);
304 : :
305 [ - + # # : 78770 : if (spdk_unlikely(!domain->invalidate_cb)) {
# # ]
306 : 0 : return;
307 : : }
308 : :
309 [ # # # # : 78770 : domain->invalidate_cb(domain, domain_ctx, iov, iovcnt);
# # # # ]
310 : 0 : }
311 : :
312 : : int
313 : 719900 : 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 [ + + # # ]: 719900 : assert(domain);
317 [ + + # # ]: 719900 : assert(iov);
318 [ - + # # ]: 719900 : assert(iovcnt);
319 : :
320 [ + + # # : 719900 : if (spdk_unlikely(!domain->memzero_cb)) {
# # ]
321 : 4 : return -ENOTSUP;
322 : : }
323 : :
324 [ # # # # : 719896 : return domain->memzero_cb(domain, domain_ctx, iov, iovcnt, cpl_cb, cpl_cb_arg);
# # # # ]
325 : 2 : }
326 : :
327 : : struct spdk_memory_domain *
328 : 80861 : spdk_memory_domain_get_first(const char *id)
329 : : {
330 : : struct spdk_memory_domain *domain;
331 : :
332 [ + + ]: 80861 : if (!id) {
333 [ + - ]: 80849 : pthread_mutex_lock(&g_dma_mutex);
334 : 80849 : domain = TAILQ_FIRST(&g_dma_memory_domains);
335 [ + - ]: 80849 : pthread_mutex_unlock(&g_dma_mutex);
336 : :
337 : 80849 : return domain;
338 : : }
339 : :
340 [ # # ]: 12 : pthread_mutex_lock(&g_dma_mutex);
341 [ + + # # : 32 : TAILQ_FOREACH(domain, &g_dma_memory_domains, link) {
# # # # ]
342 [ + + - + : 28 : if (!strcmp(domain->id, id)) {
+ + # # #
# ]
343 : 8 : break;
344 : : }
345 : 5 : }
346 [ # # ]: 12 : pthread_mutex_unlock(&g_dma_mutex);
347 : :
348 : 12 : return domain;
349 : 1359 : }
350 : :
351 : : struct spdk_memory_domain *
352 : 161791 : spdk_memory_domain_get_next(struct spdk_memory_domain *prev, const char *id)
353 : : {
354 : : struct spdk_memory_domain *domain;
355 : :
356 [ + + ]: 161791 : if (!prev) {
357 : 0 : return NULL;
358 : : }
359 : :
360 [ + - ]: 161791 : pthread_mutex_lock(&g_dma_mutex);
361 [ + - + - : 161791 : domain = TAILQ_NEXT(prev, link);
+ - ]
362 [ + - ]: 161791 : pthread_mutex_unlock(&g_dma_mutex);
363 : :
364 [ + + + + ]: 161791 : if (!id || !domain) {
365 : 161783 : return domain;
366 : : }
367 : :
368 [ # # ]: 8 : pthread_mutex_lock(&g_dma_mutex);
369 [ - + + + : 16 : TAILQ_FOREACH_FROM(domain, &g_dma_memory_domains, link) {
# # # # #
# ]
370 [ + + - + : 12 : if (!strcmp(domain->id, id)) {
+ + # # #
# ]
371 : 4 : break;
372 : : }
373 : 2 : }
374 [ # # ]: 8 : pthread_mutex_unlock(&g_dma_mutex);
375 : :
376 : 8 : return domain;
377 : 2714 : }
|