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 : 2938 : _memory_domain_register(void)
37 : : {
38 [ + - + - : 2938 : TAILQ_INSERT_TAIL(&g_dma_memory_domains, &g_system_domain, link);
+ - + - +
- + - + -
+ - + - ]
39 : 2938 : }
40 : :
41 : : struct spdk_memory_domain *
42 : 136337 : spdk_memory_domain_get_system_domain(void)
43 : : {
44 : 136337 : return &g_system_domain;
45 : : }
46 : :
47 : : int
48 : 3851 : 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 : 3851 : size_t ctx_size, user_ctx_size = 0;
53 : :
54 [ + + ]: 3851 : if (!_domain) {
55 : 4 : return -EINVAL;
56 : : }
57 : :
58 [ + + ]: 3847 : if (ctx) {
59 [ + + # # : 1545 : if (ctx->size == 0) {
# # ]
60 : 4 : SPDK_ERRLOG("Context size can't be 0\n");
61 : 4 : return -EINVAL;
62 : : }
63 [ + - - + : 1541 : if (ctx->user_ctx &&
# # # # ]
64 [ + - # # ]: 1541 : offsetof(struct spdk_memory_domain_ctx, user_ctx_size) + sizeof(ctx->user_ctx_size) <= ctx->size) {
65 [ # # # # ]: 1541 : user_ctx_size = ctx->user_ctx_size;
66 : 3 : }
67 : 3 : }
68 : :
69 : 3843 : domain = calloc(1, sizeof(*domain) + user_ctx_size);
70 [ + + ]: 3843 : if (!domain) {
71 : 0 : SPDK_ERRLOG("Failed to allocate memory");
72 : 0 : return -ENOMEM;
73 : : }
74 : :
75 [ + + ]: 3843 : if (id) {
76 [ + + + - : 3843 : domain->id = strdup(id);
+ - ]
77 [ + + + - : 3843 : if (!domain->id) {
+ - ]
78 : 0 : SPDK_ERRLOG("Failed to allocate memory");
79 : 0 : free(domain);
80 : 0 : return -ENOMEM;
81 : : }
82 : 99 : }
83 : :
84 [ + + ]: 3843 : if (ctx) {
85 [ # # # # ]: 1541 : domain->ctx = calloc(1, sizeof(*domain->ctx));
86 [ + + # # : 1541 : 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 [ - + # # : 1541 : ctx_size = spdk_min(sizeof(*domain->ctx), ctx->size);
# # # # #
# ]
94 [ - + - + : 1541 : memcpy(domain->ctx, ctx, ctx_size);
# # # # ]
95 [ # # # # : 1541 : domain->ctx->size = ctx_size;
# # # # ]
96 : 3 : }
97 : :
98 [ + + ]: 3843 : if (user_ctx_size) {
99 [ - + # # ]: 1529 : assert(ctx);
100 [ - + - + : 1529 : memcpy(domain->user_ctx, ctx->user_ctx, user_ctx_size);
# # # # #
# ]
101 [ # # # # ]: 1529 : domain->user_ctx_size = user_ctx_size;
102 : 0 : }
103 : :
104 [ + - + - ]: 3843 : domain->type = type;
105 : :
106 [ + + ]: 3843 : pthread_mutex_lock(&g_dma_mutex);
107 [ + - + - : 3843 : TAILQ_INSERT_TAIL(&g_dma_memory_domains, domain, link);
+ - + - +
- + - + -
+ - + - +
- + - +
- ]
108 [ + + ]: 3843 : pthread_mutex_unlock(&g_dma_mutex);
109 : :
110 [ + - ]: 3843 : *_domain = domain;
111 : :
112 : 3843 : return 0;
113 : 101 : }
114 : :
115 : : void
116 : 2314 : spdk_memory_domain_set_translation(struct spdk_memory_domain *domain,
117 : : spdk_memory_domain_translate_memory_cb translate_cb)
118 : : {
119 [ + + # # ]: 2314 : assert(domain);
120 : :
121 [ + - + - ]: 2314 : domain->translate_cb = translate_cb;
122 : 2314 : }
123 : :
124 : : void
125 : 2294 : spdk_memory_domain_set_invalidate(struct spdk_memory_domain *domain,
126 : : spdk_memory_domain_invalidate_data_cb invalidate_cb)
127 : : {
128 [ + + # # ]: 2294 : assert(domain);
129 : :
130 [ + - + - ]: 2294 : domain->invalidate_cb = invalidate_cb;
131 : 2294 : }
132 : :
133 : : void
134 : 20 : spdk_memory_domain_set_pull(struct spdk_memory_domain *domain,
135 : : spdk_memory_domain_pull_data_cb pull_cb)
136 : : {
137 [ + + # # ]: 20 : assert(domain);
138 : :
139 [ # # # # ]: 20 : domain->pull_cb = pull_cb;
140 : 20 : }
141 : :
142 : : void
143 : 12 : spdk_memory_domain_set_push(struct spdk_memory_domain *domain,
144 : : spdk_memory_domain_push_data_cb push_cb)
145 : : {
146 [ + + # # ]: 12 : assert(domain);
147 : :
148 [ # # # # ]: 12 : domain->push_cb = push_cb;
149 : 12 : }
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 : 20 : spdk_memory_domain_set_memzero(struct spdk_memory_domain *domain,
162 : : spdk_memory_domain_memzero_cb memzero_cb)
163 : : {
164 [ + + # # ]: 20 : assert(domain);
165 : :
166 [ # # # # ]: 20 : domain->memzero_cb = memzero_cb;
167 : 20 : }
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 : 48737 : spdk_memory_domain_get_dma_device_type(struct spdk_memory_domain *domain)
195 : : {
196 [ + + # # ]: 48737 : assert(domain);
197 : :
198 [ + - + - ]: 48737 : return domain->type;
199 : : }
200 : :
201 : : const char *
202 : 48727 : spdk_memory_domain_get_dma_device_id(struct spdk_memory_domain *domain)
203 : : {
204 [ + + # # ]: 48727 : assert(domain);
205 : :
206 [ + - + - ]: 48727 : return domain->id;
207 : : }
208 : :
209 : : void
210 : 3839 : spdk_memory_domain_destroy(struct spdk_memory_domain *domain)
211 : : {
212 [ + + ]: 3839 : if (!domain) {
213 : 4 : return;
214 : : }
215 : :
216 [ + + # # ]: 3835 : assert(domain != &g_system_domain);
217 : :
218 [ + + ]: 3835 : pthread_mutex_lock(&g_dma_mutex);
219 [ + + + - : 3835 : TAILQ_REMOVE(&g_dma_memory_domains, domain, link);
+ - - + #
# # # # #
# # # # #
# # # # #
# # + - +
- + - + -
+ - + - +
- + - + -
+ - + - ]
220 [ + + ]: 3835 : pthread_mutex_unlock(&g_dma_mutex);
221 : :
222 [ + - + - ]: 3835 : free(domain->ctx);
223 [ + - + - ]: 3835 : free(domain->id);
224 : 3835 : free(domain);
225 : 100 : }
226 : :
227 : : int
228 : 289776 : 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 [ + + # # ]: 289776 : assert(src_domain);
233 [ + + # # ]: 289776 : assert(src_iov);
234 [ - + # # ]: 289776 : assert(dst_iov);
235 : :
236 [ + + # # : 289776 : if (spdk_unlikely(!src_domain->pull_cb)) {
# # ]
237 : 4 : return -ENOTSUP;
238 : : }
239 : :
240 [ # # # # : 289773 : 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 : 675440 : 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 [ + + # # ]: 675440 : assert(dst_domain);
250 [ + + # # ]: 675440 : assert(dst_iov);
251 [ - + # # ]: 675440 : assert(src_iov);
252 : :
253 [ + + # # : 675440 : if (spdk_unlikely(!dst_domain->push_cb)) {
# # ]
254 : 4 : return -ENOTSUP;
255 : : }
256 : :
257 [ # # # # : 675437 : 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 : 789923 : 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 [ + + # # ]: 789923 : assert(src_domain);
288 [ + + # # ]: 789923 : assert(dst_domain);
289 [ - + # # ]: 789923 : assert(result);
290 : :
291 [ + + # # : 789923 : if (spdk_unlikely(!src_domain->translate_cb)) {
# # ]
292 : 4 : return -ENOTSUP;
293 : : }
294 : :
295 [ # # # # : 789920 : 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 : 68058 : spdk_memory_domain_invalidate_data(struct spdk_memory_domain *domain, void *domain_ctx,
301 : : struct iovec *iov, uint32_t iovcnt)
302 : : {
303 [ - + # # ]: 68058 : assert(domain);
304 : :
305 [ - + # # : 68058 : if (spdk_unlikely(!domain->invalidate_cb)) {
# # ]
306 : 0 : return;
307 : : }
308 : :
309 [ # # # # : 68058 : domain->invalidate_cb(domain, domain_ctx, iov, iovcnt);
# # # # ]
310 : 0 : }
311 : :
312 : : int
313 : 1237205 : 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 [ + + # # ]: 1237205 : assert(domain);
317 [ + + # # ]: 1237205 : assert(iov);
318 [ - + # # ]: 1237205 : assert(iovcnt);
319 : :
320 [ + + # # : 1237205 : if (spdk_unlikely(!domain->memzero_cb)) {
# # ]
321 : 4 : return -ENOTSUP;
322 : : }
323 : :
324 [ # # # # : 1237201 : return domain->memzero_cb(domain, domain_ctx, iov, iovcnt, cpl_cb, cpl_cb_arg);
# # # # ]
325 : 2 : }
326 : :
327 : : struct spdk_memory_domain *
328 : 92245 : spdk_memory_domain_get_first(const char *id)
329 : : {
330 : : struct spdk_memory_domain *domain;
331 : :
332 [ + + ]: 92245 : if (!id) {
333 [ + - ]: 92233 : pthread_mutex_lock(&g_dma_mutex);
334 : 92233 : domain = TAILQ_FIRST(&g_dma_memory_domains);
335 [ + - ]: 92233 : pthread_mutex_unlock(&g_dma_mutex);
336 : :
337 : 92233 : 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 : 184669 : spdk_memory_domain_get_next(struct spdk_memory_domain *prev, const char *id)
353 : : {
354 : : struct spdk_memory_domain *domain;
355 : :
356 [ + + ]: 184669 : if (!prev) {
357 : 0 : return NULL;
358 : : }
359 : :
360 [ + - ]: 184669 : pthread_mutex_lock(&g_dma_mutex);
361 [ + - + - : 184669 : domain = TAILQ_NEXT(prev, link);
+ - ]
362 [ + - ]: 184669 : pthread_mutex_unlock(&g_dma_mutex);
363 : :
364 [ + + + + ]: 184669 : if (!id || !domain) {
365 : 184661 : 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 : }
|