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_memzero_cb memzero_cb;
20 : TAILQ_ENTRY(spdk_memory_domain) link;
21 : struct spdk_memory_domain_ctx *ctx;
22 : char *id;
23 : };
24 :
25 : int
26 5 : spdk_memory_domain_create(struct spdk_memory_domain **_domain, enum spdk_dma_device_type type,
27 : struct spdk_memory_domain_ctx *ctx, const char *id)
28 : {
29 : struct spdk_memory_domain *domain;
30 : size_t ctx_size;
31 :
32 5 : if (!_domain) {
33 1 : return -EINVAL;
34 : }
35 :
36 4 : if (ctx && ctx->size == 0) {
37 1 : SPDK_ERRLOG("Context size can't be 0\n");
38 1 : return -EINVAL;
39 : }
40 :
41 3 : domain = calloc(1, sizeof(*domain));
42 3 : if (!domain) {
43 0 : SPDK_ERRLOG("Failed to allocate memory");
44 0 : return -ENOMEM;
45 : }
46 :
47 3 : if (id) {
48 3 : domain->id = strdup(id);
49 3 : if (!domain->id) {
50 0 : SPDK_ERRLOG("Failed to allocate memory");
51 0 : free(domain);
52 0 : return -ENOMEM;
53 : }
54 : }
55 :
56 3 : if (ctx) {
57 3 : domain->ctx = calloc(1, sizeof(*domain->ctx));
58 3 : if (!domain->ctx) {
59 0 : SPDK_ERRLOG("Failed to allocate memory");
60 0 : free(domain->id);
61 0 : free(domain);
62 0 : return -ENOMEM;
63 : }
64 :
65 3 : ctx_size = spdk_min(sizeof(*domain->ctx), ctx->size);
66 3 : memcpy(domain->ctx, ctx, ctx_size);
67 3 : domain->ctx->size = ctx_size;
68 : }
69 :
70 3 : domain->type = type;
71 :
72 3 : pthread_mutex_lock(&g_dma_mutex);
73 3 : TAILQ_INSERT_TAIL(&g_dma_memory_domains, domain, link);
74 3 : pthread_mutex_unlock(&g_dma_mutex);
75 :
76 3 : *_domain = domain;
77 :
78 3 : return 0;
79 : }
80 :
81 : void
82 3 : spdk_memory_domain_set_translation(struct spdk_memory_domain *domain,
83 : spdk_memory_domain_translate_memory_cb translate_cb)
84 : {
85 3 : if (!domain) {
86 0 : return;
87 : }
88 :
89 3 : domain->translate_cb = translate_cb;
90 : }
91 :
92 : void
93 3 : spdk_memory_domain_set_pull(struct spdk_memory_domain *domain,
94 : spdk_memory_domain_pull_data_cb pull_cb)
95 : {
96 3 : if (!domain) {
97 0 : return;
98 : }
99 :
100 3 : domain->pull_cb = pull_cb;
101 : }
102 :
103 : void
104 1 : spdk_memory_domain_set_push(struct spdk_memory_domain *domain,
105 : spdk_memory_domain_push_data_cb push_cb)
106 : {
107 1 : if (!domain) {
108 0 : return;
109 : }
110 :
111 1 : domain->push_cb = push_cb;
112 : }
113 :
114 : void
115 3 : spdk_memory_domain_set_memzero(struct spdk_memory_domain *domain,
116 : spdk_memory_domain_memzero_cb memzero_cb)
117 : {
118 3 : if (!domain) {
119 0 : return;
120 : }
121 :
122 3 : domain->memzero_cb = memzero_cb;
123 : }
124 :
125 : struct spdk_memory_domain_ctx *
126 1 : spdk_memory_domain_get_context(struct spdk_memory_domain *domain)
127 : {
128 1 : assert(domain);
129 :
130 1 : return domain->ctx;
131 : }
132 :
133 : /* We have to use the typedef in the function declaration to appease astyle. */
134 : typedef enum spdk_dma_device_type spdk_dma_device_type_t;
135 :
136 : spdk_dma_device_type_t
137 1 : spdk_memory_domain_get_dma_device_type(struct spdk_memory_domain *domain)
138 : {
139 1 : assert(domain);
140 :
141 1 : return domain->type;
142 : }
143 :
144 : const char *
145 1 : spdk_memory_domain_get_dma_device_id(struct spdk_memory_domain *domain)
146 : {
147 1 : assert(domain);
148 :
149 1 : return domain->id;
150 : }
151 :
152 : void
153 4 : spdk_memory_domain_destroy(struct spdk_memory_domain *domain)
154 : {
155 4 : if (!domain) {
156 1 : return;
157 : }
158 :
159 3 : pthread_mutex_lock(&g_dma_mutex);
160 3 : TAILQ_REMOVE(&g_dma_memory_domains, domain, link);
161 3 : pthread_mutex_unlock(&g_dma_mutex);
162 :
163 3 : free(domain->ctx);
164 3 : free(domain->id);
165 3 : free(domain);
166 : }
167 :
168 : int
169 2 : spdk_memory_domain_pull_data(struct spdk_memory_domain *src_domain, void *src_domain_ctx,
170 : struct iovec *src_iov, uint32_t src_iov_cnt, struct iovec *dst_iov, uint32_t dst_iov_cnt,
171 : spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
172 : {
173 2 : assert(src_domain);
174 2 : assert(src_iov);
175 2 : assert(dst_iov);
176 :
177 2 : if (spdk_unlikely(!src_domain->pull_cb)) {
178 1 : return -ENOTSUP;
179 : }
180 :
181 1 : return src_domain->pull_cb(src_domain, src_domain_ctx, src_iov, src_iov_cnt, dst_iov, dst_iov_cnt,
182 : cpl_cb, cpl_cb_arg);
183 : }
184 :
185 : int
186 2 : spdk_memory_domain_push_data(struct spdk_memory_domain *dst_domain, void *dst_domain_ctx,
187 : struct iovec *dst_iov, uint32_t dst_iovcnt, struct iovec *src_iov, uint32_t src_iovcnt,
188 : spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
189 : {
190 2 : assert(dst_domain);
191 2 : assert(dst_iov);
192 2 : assert(src_iov);
193 :
194 2 : if (spdk_unlikely(!dst_domain->push_cb)) {
195 1 : return -ENOTSUP;
196 : }
197 :
198 1 : return dst_domain->push_cb(dst_domain, dst_domain_ctx, dst_iov, dst_iovcnt, src_iov, src_iovcnt,
199 : cpl_cb, cpl_cb_arg);
200 : }
201 :
202 : int
203 2 : spdk_memory_domain_translate_data(struct spdk_memory_domain *src_domain, void *src_domain_ctx,
204 : struct spdk_memory_domain *dst_domain, struct spdk_memory_domain_translation_ctx *dst_domain_ctx,
205 : void *addr, size_t len, struct spdk_memory_domain_translation_result *result)
206 : {
207 2 : assert(src_domain);
208 2 : assert(dst_domain);
209 2 : assert(result);
210 :
211 2 : if (spdk_unlikely(!src_domain->translate_cb)) {
212 1 : return -ENOTSUP;
213 : }
214 :
215 1 : return src_domain->translate_cb(src_domain, src_domain_ctx, dst_domain, dst_domain_ctx, addr, len,
216 : result);
217 : }
218 :
219 : int
220 2 : spdk_memory_domain_memzero(struct spdk_memory_domain *domain, void *domain_ctx, struct iovec *iov,
221 : uint32_t iovcnt, spdk_memory_domain_data_cpl_cb cpl_cb, void *cpl_cb_arg)
222 : {
223 2 : assert(domain);
224 2 : assert(iov);
225 2 : assert(iovcnt);
226 :
227 2 : if (spdk_unlikely(!domain->memzero_cb)) {
228 1 : return -ENOTSUP;
229 : }
230 :
231 1 : return domain->memzero_cb(domain, domain_ctx, iov, iovcnt, cpl_cb, cpl_cb_arg);
232 : }
233 :
234 : struct spdk_memory_domain *
235 8 : spdk_memory_domain_get_first(const char *id)
236 : {
237 : struct spdk_memory_domain *domain;
238 :
239 8 : if (!id) {
240 5 : pthread_mutex_lock(&g_dma_mutex);
241 5 : domain = TAILQ_FIRST(&g_dma_memory_domains);
242 5 : pthread_mutex_unlock(&g_dma_mutex);
243 :
244 5 : return domain;
245 : }
246 :
247 3 : pthread_mutex_lock(&g_dma_mutex);
248 5 : TAILQ_FOREACH(domain, &g_dma_memory_domains, link) {
249 4 : if (!strcmp(domain->id, id)) {
250 2 : break;
251 : }
252 : }
253 3 : pthread_mutex_unlock(&g_dma_mutex);
254 :
255 3 : return domain;
256 : }
257 :
258 : struct spdk_memory_domain *
259 9 : spdk_memory_domain_get_next(struct spdk_memory_domain *prev, const char *id)
260 : {
261 : struct spdk_memory_domain *domain;
262 :
263 9 : if (!prev) {
264 0 : return NULL;
265 : }
266 :
267 9 : pthread_mutex_lock(&g_dma_mutex);
268 9 : domain = TAILQ_NEXT(prev, link);
269 9 : pthread_mutex_unlock(&g_dma_mutex);
270 :
271 9 : if (!id || !domain) {
272 7 : return domain;
273 : }
274 :
275 2 : pthread_mutex_lock(&g_dma_mutex);
276 4 : TAILQ_FOREACH_FROM(domain, &g_dma_memory_domains, link) {
277 3 : if (!strcmp(domain->id, id)) {
278 1 : break;
279 : }
280 : }
281 2 : pthread_mutex_unlock(&g_dma_mutex);
282 :
283 2 : return domain;
284 : }
|