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_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 1 : _memory_domain_register(void)
34 : {
35 1 : TAILQ_INSERT_TAIL(&g_dma_memory_domains, &g_system_domain, link);
36 1 : }
37 :
38 : struct spdk_memory_domain *
39 1 : spdk_memory_domain_get_system_domain(void)
40 : {
41 1 : return &g_system_domain;
42 : }
43 :
44 : int
45 5 : 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 5 : if (!_domain) {
52 1 : return -EINVAL;
53 : }
54 :
55 4 : if (ctx && ctx->size == 0) {
56 1 : SPDK_ERRLOG("Context size can't be 0\n");
57 1 : return -EINVAL;
58 : }
59 :
60 3 : domain = calloc(1, sizeof(*domain));
61 3 : if (!domain) {
62 0 : SPDK_ERRLOG("Failed to allocate memory");
63 0 : return -ENOMEM;
64 : }
65 :
66 3 : if (id) {
67 3 : domain->id = strdup(id);
68 3 : if (!domain->id) {
69 0 : SPDK_ERRLOG("Failed to allocate memory");
70 0 : free(domain);
71 0 : return -ENOMEM;
72 : }
73 : }
74 :
75 3 : if (ctx) {
76 3 : domain->ctx = calloc(1, sizeof(*domain->ctx));
77 3 : 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 3 : ctx_size = spdk_min(sizeof(*domain->ctx), ctx->size);
85 3 : memcpy(domain->ctx, ctx, ctx_size);
86 3 : domain->ctx->size = ctx_size;
87 : }
88 :
89 3 : domain->type = type;
90 :
91 3 : pthread_mutex_lock(&g_dma_mutex);
92 3 : TAILQ_INSERT_TAIL(&g_dma_memory_domains, domain, link);
93 3 : pthread_mutex_unlock(&g_dma_mutex);
94 :
95 3 : *_domain = domain;
96 :
97 3 : return 0;
98 : }
99 :
100 : void
101 3 : spdk_memory_domain_set_translation(struct spdk_memory_domain *domain,
102 : spdk_memory_domain_translate_memory_cb translate_cb)
103 : {
104 3 : assert(domain);
105 :
106 3 : domain->translate_cb = translate_cb;
107 3 : }
108 :
109 : void
110 0 : spdk_memory_domain_set_invalidate(struct spdk_memory_domain *domain,
111 : spdk_memory_domain_invalidate_data_cb invalidate_cb)
112 : {
113 0 : assert(domain);
114 :
115 0 : domain->invalidate_cb = invalidate_cb;
116 0 : }
117 :
118 : void
119 3 : spdk_memory_domain_set_pull(struct spdk_memory_domain *domain,
120 : spdk_memory_domain_pull_data_cb pull_cb)
121 : {
122 3 : assert(domain);
123 :
124 3 : domain->pull_cb = pull_cb;
125 3 : }
126 :
127 : void
128 1 : spdk_memory_domain_set_push(struct spdk_memory_domain *domain,
129 : spdk_memory_domain_push_data_cb push_cb)
130 : {
131 1 : assert(domain);
132 :
133 1 : domain->push_cb = push_cb;
134 1 : }
135 :
136 : void
137 3 : spdk_memory_domain_set_memzero(struct spdk_memory_domain *domain,
138 : spdk_memory_domain_memzero_cb memzero_cb)
139 : {
140 3 : assert(domain);
141 :
142 3 : domain->memzero_cb = memzero_cb;
143 3 : }
144 :
145 : struct spdk_memory_domain_ctx *
146 1 : spdk_memory_domain_get_context(struct spdk_memory_domain *domain)
147 : {
148 1 : assert(domain);
149 :
150 1 : 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 1 : spdk_memory_domain_get_dma_device_type(struct spdk_memory_domain *domain)
158 : {
159 1 : assert(domain);
160 :
161 1 : return domain->type;
162 : }
163 :
164 : const char *
165 1 : spdk_memory_domain_get_dma_device_id(struct spdk_memory_domain *domain)
166 : {
167 1 : assert(domain);
168 :
169 1 : return domain->id;
170 : }
171 :
172 : void
173 4 : spdk_memory_domain_destroy(struct spdk_memory_domain *domain)
174 : {
175 4 : if (!domain) {
176 1 : return;
177 : }
178 :
179 3 : assert(domain != &g_system_domain);
180 :
181 3 : pthread_mutex_lock(&g_dma_mutex);
182 3 : TAILQ_REMOVE(&g_dma_memory_domains, domain, link);
183 3 : pthread_mutex_unlock(&g_dma_mutex);
184 :
185 3 : free(domain->ctx);
186 3 : free(domain->id);
187 3 : free(domain);
188 : }
189 :
190 : int
191 2 : 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 2 : assert(src_domain);
196 2 : assert(src_iov);
197 2 : assert(dst_iov);
198 :
199 2 : if (spdk_unlikely(!src_domain->pull_cb)) {
200 1 : return -ENOTSUP;
201 : }
202 :
203 1 : 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 2 : 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 2 : assert(dst_domain);
213 2 : assert(dst_iov);
214 2 : assert(src_iov);
215 :
216 2 : if (spdk_unlikely(!dst_domain->push_cb)) {
217 1 : return -ENOTSUP;
218 : }
219 :
220 1 : 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 2 : 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 2 : assert(src_domain);
230 2 : assert(dst_domain);
231 2 : assert(result);
232 :
233 2 : if (spdk_unlikely(!src_domain->translate_cb)) {
234 1 : return -ENOTSUP;
235 : }
236 :
237 1 : return src_domain->translate_cb(src_domain, src_domain_ctx, dst_domain, dst_domain_ctx, addr, len,
238 : result);
239 : }
240 :
241 : void
242 0 : spdk_memory_domain_invalidate_data(struct spdk_memory_domain *domain, void *domain_ctx,
243 : struct iovec *iov, uint32_t iovcnt)
244 : {
245 0 : assert(domain);
246 :
247 0 : if (spdk_unlikely(!domain->invalidate_cb)) {
248 0 : return;
249 : }
250 :
251 0 : domain->invalidate_cb(domain, domain_ctx, iov, iovcnt);
252 : }
253 :
254 : int
255 2 : 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 2 : assert(domain);
259 2 : assert(iov);
260 2 : assert(iovcnt);
261 :
262 2 : if (spdk_unlikely(!domain->memzero_cb)) {
263 1 : return -ENOTSUP;
264 : }
265 :
266 1 : return domain->memzero_cb(domain, domain_ctx, iov, iovcnt, cpl_cb, cpl_cb_arg);
267 : }
268 :
269 : struct spdk_memory_domain *
270 8 : spdk_memory_domain_get_first(const char *id)
271 : {
272 : struct spdk_memory_domain *domain;
273 :
274 8 : if (!id) {
275 5 : pthread_mutex_lock(&g_dma_mutex);
276 5 : domain = TAILQ_FIRST(&g_dma_memory_domains);
277 5 : pthread_mutex_unlock(&g_dma_mutex);
278 :
279 5 : return domain;
280 : }
281 :
282 3 : pthread_mutex_lock(&g_dma_mutex);
283 8 : TAILQ_FOREACH(domain, &g_dma_memory_domains, link) {
284 7 : if (!strcmp(domain->id, id)) {
285 2 : break;
286 : }
287 : }
288 3 : pthread_mutex_unlock(&g_dma_mutex);
289 :
290 3 : return domain;
291 : }
292 :
293 : struct spdk_memory_domain *
294 12 : spdk_memory_domain_get_next(struct spdk_memory_domain *prev, const char *id)
295 : {
296 : struct spdk_memory_domain *domain;
297 :
298 12 : if (!prev) {
299 0 : return NULL;
300 : }
301 :
302 12 : pthread_mutex_lock(&g_dma_mutex);
303 12 : domain = TAILQ_NEXT(prev, link);
304 12 : pthread_mutex_unlock(&g_dma_mutex);
305 :
306 12 : if (!id || !domain) {
307 10 : return domain;
308 : }
309 :
310 2 : pthread_mutex_lock(&g_dma_mutex);
311 4 : TAILQ_FOREACH_FROM(domain, &g_dma_memory_domains, link) {
312 3 : if (!strcmp(domain->id, id)) {
313 1 : break;
314 : }
315 : }
316 2 : pthread_mutex_unlock(&g_dma_mutex);
317 :
318 2 : return domain;
319 : }
|