Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright (c) 2021 NVIDIA Corporation & Affiliates
3 : : */
4 : :
5 : : #include <stdlib.h>
6 : :
7 : : #include <rte_eal.h>
8 : : #include <rte_tailq.h>
9 : : #include <rte_string_fns.h>
10 : : #include <rte_memzone.h>
11 : : #include <rte_malloc.h>
12 : : #include <rte_errno.h>
13 : : #include <rte_log.h>
14 : :
15 : : #include "rte_gpudev.h"
16 : : #include "gpudev_driver.h"
17 : :
18 : : /* Logging */
19 [ - + ]: 235 : RTE_LOG_REGISTER_DEFAULT(gpu_logtype, NOTICE);
20 : : #define RTE_LOGTYPE_GPUDEV gpu_logtype
21 : :
22 : : #define GPU_LOG(level, ...) \
23 : : RTE_LOG_LINE(level, GPUDEV, RTE_FMT("gpu: " RTE_FMT_HEAD(__VA_ARGS__ ,), \
24 : : RTE_FMT_TAIL(__VA_ARGS__ ,)))
25 : :
26 : : /* Set any driver error as EPERM */
27 : : #define GPU_DRV_RET(function) \
28 : : ((function != 0) ? -(rte_errno = EPERM) : (rte_errno = 0))
29 : :
30 : : /* Array of devices */
31 : : static struct rte_gpu *gpus;
32 : : /* Number of currently valid devices */
33 : : static int16_t gpu_max;
34 : : /* Number of currently valid devices */
35 : : static int16_t gpu_count;
36 : :
37 : : /* Shared memory between processes. */
38 : : static const char *GPU_MEMZONE = "rte_gpu_shared";
39 : : static struct {
40 : : __extension__ struct rte_gpu_mpshared gpus[0];
41 : : } *gpu_shared_mem;
42 : :
43 : : /* Event callback object */
44 : : struct rte_gpu_callback {
45 : : TAILQ_ENTRY(rte_gpu_callback) next;
46 : : rte_gpu_callback_t *function;
47 : : void *user_data;
48 : : enum rte_gpu_event event;
49 : : };
50 : : static rte_rwlock_t gpu_callback_lock = RTE_RWLOCK_INITIALIZER;
51 : : static void gpu_free_callbacks(struct rte_gpu *dev);
52 : :
53 : : int
54 : 0 : rte_gpu_init(size_t dev_max)
55 : : {
56 [ # # ]: 0 : if (dev_max == 0 || dev_max > INT16_MAX) {
57 : 0 : GPU_LOG(ERR, "invalid array size");
58 : 0 : rte_errno = EINVAL;
59 : 0 : return -rte_errno;
60 : : }
61 : :
62 : : /* No lock, it must be called before or during first probing. */
63 [ # # ]: 0 : if (gpus != NULL) {
64 : 0 : GPU_LOG(ERR, "already initialized");
65 : 0 : rte_errno = EBUSY;
66 : 0 : return -rte_errno;
67 : : }
68 : :
69 : 0 : gpus = calloc(dev_max, sizeof(struct rte_gpu));
70 [ # # ]: 0 : if (gpus == NULL) {
71 : 0 : GPU_LOG(ERR, "cannot initialize library");
72 : 0 : rte_errno = ENOMEM;
73 : 0 : return -rte_errno;
74 : : }
75 : :
76 : 0 : gpu_max = dev_max;
77 : 0 : return 0;
78 : : }
79 : :
80 : : uint16_t
81 : 0 : rte_gpu_count_avail(void)
82 : : {
83 : 0 : return gpu_count;
84 : : }
85 : :
86 : : bool
87 : 0 : rte_gpu_is_valid(int16_t dev_id)
88 : : {
89 [ # # # # ]: 0 : if (dev_id >= 0 && dev_id < gpu_max &&
90 [ # # ]: 0 : gpus[dev_id].process_state == RTE_GPU_STATE_INITIALIZED)
91 : 0 : return true;
92 : : return false;
93 : : }
94 : :
95 : : static bool
96 : : gpu_match_parent(int16_t dev_id, int16_t parent)
97 : : {
98 [ # # ]: 0 : if (parent == RTE_GPU_ID_ANY)
99 : : return true;
100 : 0 : return gpus[dev_id].mpshared->info.parent == parent;
101 : : }
102 : :
103 : : int16_t
104 : 0 : rte_gpu_find_next(int16_t dev_id, int16_t parent)
105 : : {
106 : : if (dev_id < 0)
107 : : dev_id = 0;
108 [ # # ]: 0 : while (dev_id < gpu_max &&
109 [ # # # # ]: 0 : (gpus[dev_id].process_state == RTE_GPU_STATE_UNUSED ||
110 : : !gpu_match_parent(dev_id, parent)))
111 : 0 : dev_id++;
112 : :
113 [ # # ]: 0 : if (dev_id >= gpu_max)
114 : 0 : return RTE_GPU_ID_NONE;
115 : : return dev_id;
116 : : }
117 : :
118 : : static int16_t
119 : : gpu_find_free_id(void)
120 : : {
121 : : int16_t dev_id;
122 : :
123 [ # # ]: 0 : for (dev_id = 0; dev_id < gpu_max; dev_id++) {
124 [ # # ]: 0 : if (gpus[dev_id].process_state == RTE_GPU_STATE_UNUSED)
125 : : return dev_id;
126 : : }
127 : : return RTE_GPU_ID_NONE;
128 : : }
129 : :
130 : : static struct rte_gpu *
131 : : gpu_get_by_id(int16_t dev_id)
132 : : {
133 [ # # # # : 0 : if (!rte_gpu_is_valid(dev_id))
# # # # #
# # # # #
# # # # #
# ]
134 : : return NULL;
135 : 0 : return &gpus[dev_id];
136 : : }
137 : :
138 : : struct rte_gpu *
139 : 0 : rte_gpu_get_by_name(const char *name)
140 : : {
141 : : int16_t dev_id;
142 : : struct rte_gpu *dev;
143 : :
144 [ # # ]: 0 : if (name == NULL) {
145 : 0 : rte_errno = EINVAL;
146 : 0 : return NULL;
147 : : }
148 : :
149 [ # # ]: 0 : RTE_GPU_FOREACH(dev_id) {
150 : 0 : dev = &gpus[dev_id];
151 [ # # ]: 0 : if (strncmp(name, dev->mpshared->name, RTE_DEV_NAME_MAX_LEN) == 0)
152 : 0 : return dev;
153 : : }
154 : : return NULL;
155 : : }
156 : :
157 : : static int
158 : 0 : gpu_shared_mem_init(void)
159 : : {
160 : : const struct rte_memzone *memzone;
161 : :
162 [ # # ]: 0 : if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
163 : 0 : memzone = rte_memzone_reserve(GPU_MEMZONE,
164 : : sizeof(*gpu_shared_mem) +
165 : : sizeof(*gpu_shared_mem->gpus) * gpu_max,
166 : : SOCKET_ID_ANY, 0);
167 : : } else {
168 : 0 : memzone = rte_memzone_lookup(GPU_MEMZONE);
169 : : }
170 [ # # ]: 0 : if (memzone == NULL) {
171 : 0 : GPU_LOG(ERR, "cannot initialize shared memory");
172 : 0 : rte_errno = ENOMEM;
173 : 0 : return -rte_errno;
174 : : }
175 : :
176 : 0 : gpu_shared_mem = memzone->addr;
177 : 0 : return 0;
178 : : }
179 : :
180 : : struct rte_gpu *
181 : 0 : rte_gpu_allocate(const char *name)
182 : : {
183 : : int16_t dev_id;
184 : : struct rte_gpu *dev;
185 : :
186 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
187 : 0 : GPU_LOG(ERR, "only primary process can allocate device");
188 : 0 : rte_errno = EPERM;
189 : 0 : return NULL;
190 : : }
191 [ # # ]: 0 : if (name == NULL) {
192 : 0 : GPU_LOG(ERR, "allocate device without a name");
193 : 0 : rte_errno = EINVAL;
194 : 0 : return NULL;
195 : : }
196 : :
197 : : /* implicit initialization of library before adding first device */
198 [ # # # # ]: 0 : if (gpus == NULL && rte_gpu_init(RTE_GPU_DEFAULT_MAX) < 0)
199 : : return NULL;
200 : :
201 : : /* initialize shared memory before adding first device */
202 [ # # # # ]: 0 : if (gpu_shared_mem == NULL && gpu_shared_mem_init() < 0)
203 : : return NULL;
204 : :
205 [ # # ]: 0 : if (rte_gpu_get_by_name(name) != NULL) {
206 : 0 : GPU_LOG(ERR, "device with name %s already exists", name);
207 : 0 : rte_errno = EEXIST;
208 : 0 : return NULL;
209 : : }
210 : : dev_id = gpu_find_free_id();
211 [ # # ]: 0 : if (dev_id == RTE_GPU_ID_NONE) {
212 : 0 : GPU_LOG(ERR, "reached maximum number of devices");
213 : 0 : rte_errno = ENOENT;
214 : 0 : return NULL;
215 : : }
216 : :
217 : 0 : dev = &gpus[dev_id];
218 : : memset(dev, 0, sizeof(*dev));
219 : :
220 : 0 : dev->mpshared = &gpu_shared_mem->gpus[dev_id];
221 : : memset(dev->mpshared, 0, sizeof(*dev->mpshared));
222 : :
223 [ # # ]: 0 : if (rte_strscpy(dev->mpshared->name, name, RTE_DEV_NAME_MAX_LEN) < 0) {
224 : 0 : GPU_LOG(ERR, "device name too long: %s", name);
225 : 0 : rte_errno = ENAMETOOLONG;
226 : 0 : return NULL;
227 : : }
228 : 0 : dev->mpshared->info.name = dev->mpshared->name;
229 : 0 : dev->mpshared->info.dev_id = dev_id;
230 : 0 : dev->mpshared->info.numa_node = -1;
231 : 0 : dev->mpshared->info.parent = RTE_GPU_ID_NONE;
232 : 0 : TAILQ_INIT(&dev->callbacks);
233 : 0 : rte_atomic_fetch_add_explicit(&dev->mpshared->process_refcnt, 1, rte_memory_order_relaxed);
234 : :
235 : 0 : gpu_count++;
236 : 0 : GPU_LOG(DEBUG, "new device %s (id %d) of total %d",
237 : : name, dev_id, gpu_count);
238 : 0 : return dev;
239 : : }
240 : :
241 : : struct rte_gpu *
242 : 0 : rte_gpu_attach(const char *name)
243 : : {
244 : : int16_t dev_id;
245 : : struct rte_gpu *dev;
246 : : struct rte_gpu_mpshared *shared_dev;
247 : :
248 [ # # ]: 0 : if (rte_eal_process_type() != RTE_PROC_SECONDARY) {
249 : 0 : GPU_LOG(ERR, "only secondary process can attach device");
250 : 0 : rte_errno = EPERM;
251 : 0 : return NULL;
252 : : }
253 [ # # ]: 0 : if (name == NULL) {
254 : 0 : GPU_LOG(ERR, "attach device without a name");
255 : 0 : rte_errno = EINVAL;
256 : 0 : return NULL;
257 : : }
258 : :
259 : : /* implicit initialization of library before adding first device */
260 [ # # # # ]: 0 : if (gpus == NULL && rte_gpu_init(RTE_GPU_DEFAULT_MAX) < 0)
261 : : return NULL;
262 : :
263 : : /* initialize shared memory before adding first device */
264 [ # # # # ]: 0 : if (gpu_shared_mem == NULL && gpu_shared_mem_init() < 0)
265 : : return NULL;
266 : :
267 [ # # ]: 0 : for (dev_id = 0; dev_id < gpu_max; dev_id++) {
268 : 0 : shared_dev = &gpu_shared_mem->gpus[dev_id];
269 [ # # ]: 0 : if (strncmp(name, shared_dev->name, RTE_DEV_NAME_MAX_LEN) == 0)
270 : : break;
271 : : }
272 [ # # ]: 0 : if (dev_id >= gpu_max) {
273 : 0 : GPU_LOG(ERR, "device with name %s not found", name);
274 : 0 : rte_errno = ENOENT;
275 : 0 : return NULL;
276 : : }
277 : 0 : dev = &gpus[dev_id];
278 : : memset(dev, 0, sizeof(*dev));
279 : :
280 : 0 : TAILQ_INIT(&dev->callbacks);
281 : 0 : dev->mpshared = shared_dev;
282 : 0 : rte_atomic_fetch_add_explicit(&dev->mpshared->process_refcnt, 1, rte_memory_order_relaxed);
283 : :
284 : 0 : gpu_count++;
285 : 0 : GPU_LOG(DEBUG, "attached device %s (id %d) of total %d",
286 : : name, dev_id, gpu_count);
287 : 0 : return dev;
288 : : }
289 : :
290 : : int16_t
291 : 0 : rte_gpu_add_child(const char *name, int16_t parent, uint64_t child_context)
292 : : {
293 : : struct rte_gpu *dev;
294 : :
295 [ # # ]: 0 : if (!rte_gpu_is_valid(parent)) {
296 : 0 : GPU_LOG(ERR, "add child to invalid parent ID %d", parent);
297 : 0 : rte_errno = ENODEV;
298 : 0 : return -rte_errno;
299 : : }
300 : :
301 : 0 : dev = rte_gpu_allocate(name);
302 [ # # ]: 0 : if (dev == NULL)
303 : 0 : return -rte_errno;
304 : :
305 : 0 : dev->mpshared->info.parent = parent;
306 : 0 : dev->mpshared->info.context = child_context;
307 : :
308 : 0 : rte_gpu_complete_new(dev);
309 : 0 : return dev->mpshared->info.dev_id;
310 : : }
311 : :
312 : : void
313 : 0 : rte_gpu_complete_new(struct rte_gpu *dev)
314 : : {
315 [ # # ]: 0 : if (dev == NULL)
316 : : return;
317 : :
318 : 0 : dev->process_state = RTE_GPU_STATE_INITIALIZED;
319 : 0 : rte_gpu_notify(dev, RTE_GPU_EVENT_NEW);
320 : : }
321 : :
322 : : int
323 : 0 : rte_gpu_release(struct rte_gpu *dev)
324 : : {
325 : : int16_t dev_id, child;
326 : :
327 [ # # ]: 0 : if (dev == NULL) {
328 : 0 : rte_errno = ENODEV;
329 : 0 : return -rte_errno;
330 : : }
331 : 0 : dev_id = dev->mpshared->info.dev_id;
332 [ # # ]: 0 : RTE_GPU_FOREACH_CHILD(child, dev_id) {
333 : 0 : GPU_LOG(ERR, "cannot release device %d with child %d",
334 : : dev_id, child);
335 : 0 : rte_errno = EBUSY;
336 : 0 : return -rte_errno;
337 : : }
338 : :
339 : 0 : GPU_LOG(DEBUG, "free device %s (id %d)",
340 : : dev->mpshared->info.name, dev->mpshared->info.dev_id);
341 : 0 : rte_gpu_notify(dev, RTE_GPU_EVENT_DEL);
342 : :
343 : 0 : gpu_free_callbacks(dev);
344 : 0 : dev->process_state = RTE_GPU_STATE_UNUSED;
345 : 0 : rte_atomic_fetch_sub_explicit(&dev->mpshared->process_refcnt, 1, rte_memory_order_relaxed);
346 : 0 : gpu_count--;
347 : :
348 : 0 : return 0;
349 : : }
350 : :
351 : : int
352 : 0 : rte_gpu_close(int16_t dev_id)
353 : : {
354 : : int firsterr, binerr;
355 : : int *lasterr = &firsterr;
356 : : struct rte_gpu *dev;
357 : :
358 : 0 : dev = gpu_get_by_id(dev_id);
359 [ # # ]: 0 : if (dev == NULL) {
360 : 0 : GPU_LOG(ERR, "close invalid device ID %d", dev_id);
361 : 0 : rte_errno = ENODEV;
362 : 0 : return -rte_errno;
363 : : }
364 : :
365 [ # # ]: 0 : if (dev->ops.dev_close != NULL) {
366 [ # # ]: 0 : *lasterr = GPU_DRV_RET(dev->ops.dev_close(dev));
367 [ # # ]: 0 : if (*lasterr != 0)
368 : : lasterr = &binerr;
369 : : }
370 : :
371 : 0 : *lasterr = rte_gpu_release(dev);
372 : :
373 : 0 : rte_errno = -firsterr;
374 : 0 : return firsterr;
375 : : }
376 : :
377 : : int
378 : 0 : rte_gpu_callback_register(int16_t dev_id, enum rte_gpu_event event,
379 : : rte_gpu_callback_t *function, void *user_data)
380 : : {
381 : : int16_t next_dev, last_dev;
382 : : struct rte_gpu_callback_list *callbacks;
383 : : struct rte_gpu_callback *callback;
384 : :
385 [ # # # # ]: 0 : if (!rte_gpu_is_valid(dev_id) && dev_id != RTE_GPU_ID_ANY) {
386 : 0 : GPU_LOG(ERR, "register callback of invalid ID %d", dev_id);
387 : 0 : rte_errno = ENODEV;
388 : 0 : return -rte_errno;
389 : : }
390 [ # # ]: 0 : if (function == NULL) {
391 : 0 : GPU_LOG(ERR, "cannot register callback without function");
392 : 0 : rte_errno = EINVAL;
393 : 0 : return -rte_errno;
394 : : }
395 : :
396 [ # # ]: 0 : if (dev_id == RTE_GPU_ID_ANY) {
397 : : next_dev = 0;
398 : 0 : last_dev = gpu_max - 1;
399 : : } else {
400 : : next_dev = last_dev = dev_id;
401 : : }
402 : :
403 : 0 : rte_rwlock_write_lock(&gpu_callback_lock);
404 : : do {
405 : 0 : callbacks = &gpus[next_dev].callbacks;
406 : :
407 : : /* check if not already registered */
408 [ # # ]: 0 : TAILQ_FOREACH(callback, callbacks, next) {
409 [ # # ]: 0 : if (callback->event == event &&
410 [ # # ]: 0 : callback->function == function &&
411 [ # # ]: 0 : callback->user_data == user_data) {
412 : 0 : GPU_LOG(INFO, "callback already registered");
413 : : rte_rwlock_write_unlock(&gpu_callback_lock);
414 : 0 : return 0;
415 : : }
416 : : }
417 : :
418 : 0 : callback = malloc(sizeof(*callback));
419 [ # # ]: 0 : if (callback == NULL) {
420 : 0 : GPU_LOG(ERR, "cannot allocate callback");
421 : : rte_rwlock_write_unlock(&gpu_callback_lock);
422 : 0 : rte_errno = ENOMEM;
423 : 0 : return -rte_errno;
424 : : }
425 : 0 : callback->function = function;
426 : 0 : callback->user_data = user_data;
427 : 0 : callback->event = event;
428 : 0 : TAILQ_INSERT_TAIL(callbacks, callback, next);
429 : :
430 [ # # ]: 0 : } while (++next_dev <= last_dev);
431 : : rte_rwlock_write_unlock(&gpu_callback_lock);
432 : :
433 : 0 : return 0;
434 : : }
435 : :
436 : : int
437 : 0 : rte_gpu_callback_unregister(int16_t dev_id, enum rte_gpu_event event,
438 : : rte_gpu_callback_t *function, void *user_data)
439 : : {
440 : : int16_t next_dev, last_dev;
441 : : struct rte_gpu_callback_list *callbacks;
442 : : struct rte_gpu_callback *callback, *nextcb;
443 : :
444 [ # # # # ]: 0 : if (!rte_gpu_is_valid(dev_id) && dev_id != RTE_GPU_ID_ANY) {
445 : 0 : GPU_LOG(ERR, "unregister callback of invalid ID %d", dev_id);
446 : 0 : rte_errno = ENODEV;
447 : 0 : return -rte_errno;
448 : : }
449 [ # # ]: 0 : if (function == NULL) {
450 : 0 : GPU_LOG(ERR, "cannot unregister callback without function");
451 : 0 : rte_errno = EINVAL;
452 : 0 : return -rte_errno;
453 : : }
454 : :
455 [ # # ]: 0 : if (dev_id == RTE_GPU_ID_ANY) {
456 : : next_dev = 0;
457 : 0 : last_dev = gpu_max - 1;
458 : : } else {
459 : : next_dev = last_dev = dev_id;
460 : : }
461 : :
462 : 0 : rte_rwlock_write_lock(&gpu_callback_lock);
463 : : do {
464 : 0 : callbacks = &gpus[next_dev].callbacks;
465 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(callback, callbacks, next, nextcb) {
466 [ # # ]: 0 : if (callback->event != event ||
467 [ # # ]: 0 : callback->function != function ||
468 [ # # # # ]: 0 : (callback->user_data != user_data &&
469 : : user_data != (void *)-1))
470 : 0 : continue;
471 [ # # ]: 0 : TAILQ_REMOVE(callbacks, callback, next);
472 : 0 : free(callback);
473 : : }
474 [ # # ]: 0 : } while (++next_dev <= last_dev);
475 : : rte_rwlock_write_unlock(&gpu_callback_lock);
476 : :
477 : 0 : return 0;
478 : : }
479 : :
480 : : static void
481 : 0 : gpu_free_callbacks(struct rte_gpu *dev)
482 : : {
483 : : struct rte_gpu_callback_list *callbacks;
484 : : struct rte_gpu_callback *callback, *nextcb;
485 : :
486 : : callbacks = &dev->callbacks;
487 : 0 : rte_rwlock_write_lock(&gpu_callback_lock);
488 [ # # ]: 0 : RTE_TAILQ_FOREACH_SAFE(callback, callbacks, next, nextcb) {
489 [ # # ]: 0 : TAILQ_REMOVE(callbacks, callback, next);
490 : 0 : free(callback);
491 : : }
492 : : rte_rwlock_write_unlock(&gpu_callback_lock);
493 : 0 : }
494 : :
495 : : void
496 : 0 : rte_gpu_notify(struct rte_gpu *dev, enum rte_gpu_event event)
497 : : {
498 : : int16_t dev_id;
499 : : struct rte_gpu_callback *callback;
500 : :
501 : 0 : dev_id = dev->mpshared->info.dev_id;
502 : 0 : rte_rwlock_read_lock(&gpu_callback_lock);
503 [ # # ]: 0 : TAILQ_FOREACH(callback, &dev->callbacks, next) {
504 [ # # # # ]: 0 : if (callback->event != event || callback->function == NULL)
505 : 0 : continue;
506 : 0 : callback->function(dev_id, event, callback->user_data);
507 : : }
508 : : rte_rwlock_read_unlock(&gpu_callback_lock);
509 : 0 : }
510 : :
511 : : int
512 : 0 : rte_gpu_info_get(int16_t dev_id, struct rte_gpu_info *info)
513 : : {
514 : : struct rte_gpu *dev;
515 : :
516 : 0 : dev = gpu_get_by_id(dev_id);
517 [ # # ]: 0 : if (dev == NULL) {
518 : 0 : GPU_LOG(ERR, "query invalid device ID %d", dev_id);
519 : 0 : rte_errno = ENODEV;
520 : 0 : return -rte_errno;
521 : : }
522 [ # # ]: 0 : if (info == NULL) {
523 : 0 : GPU_LOG(ERR, "query without storage");
524 : 0 : rte_errno = EINVAL;
525 : 0 : return -rte_errno;
526 : : }
527 : :
528 [ # # ]: 0 : if (dev->ops.dev_info_get == NULL) {
529 : 0 : *info = dev->mpshared->info;
530 : 0 : return 0;
531 : : }
532 [ # # ]: 0 : return GPU_DRV_RET(dev->ops.dev_info_get(dev, info));
533 : : }
534 : :
535 : : void *
536 : 0 : rte_gpu_mem_alloc(int16_t dev_id, size_t size, unsigned int align)
537 : : {
538 : : struct rte_gpu *dev;
539 : : void *ptr;
540 : : int ret;
541 : :
542 : 0 : dev = gpu_get_by_id(dev_id);
543 [ # # ]: 0 : if (dev == NULL) {
544 : 0 : GPU_LOG(ERR, "alloc mem for invalid device ID %d", dev_id);
545 : 0 : rte_errno = ENODEV;
546 : 0 : return NULL;
547 : : }
548 : :
549 [ # # ]: 0 : if (dev->ops.mem_alloc == NULL) {
550 : 0 : GPU_LOG(ERR, "mem allocation not supported");
551 : 0 : rte_errno = ENOTSUP;
552 : 0 : return NULL;
553 : : }
554 : :
555 [ # # ]: 0 : if (size == 0) /* dry-run */
556 : : return NULL;
557 : :
558 [ # # ]: 0 : if (align && !rte_is_power_of_2(align)) {
559 : 0 : GPU_LOG(ERR, "requested alignment is not a power of two %u", align);
560 : 0 : rte_errno = EINVAL;
561 : 0 : return NULL;
562 : : }
563 : :
564 : 0 : ret = dev->ops.mem_alloc(dev, size, align, &ptr);
565 : :
566 [ # # # ]: 0 : switch (ret) {
567 : 0 : case 0:
568 : 0 : return ptr;
569 : 0 : case -ENOMEM:
570 : : case -E2BIG:
571 : 0 : rte_errno = -ret;
572 : 0 : return NULL;
573 : 0 : default:
574 : 0 : rte_errno = -EPERM;
575 : 0 : return NULL;
576 : : }
577 : : }
578 : :
579 : : int
580 : 0 : rte_gpu_mem_free(int16_t dev_id, void *ptr)
581 : : {
582 : : struct rte_gpu *dev;
583 : :
584 : 0 : dev = gpu_get_by_id(dev_id);
585 [ # # ]: 0 : if (dev == NULL) {
586 : 0 : GPU_LOG(ERR, "free mem for invalid device ID %d", dev_id);
587 : 0 : rte_errno = ENODEV;
588 : 0 : return -rte_errno;
589 : : }
590 : :
591 [ # # ]: 0 : if (dev->ops.mem_free == NULL) {
592 : 0 : rte_errno = ENOTSUP;
593 : 0 : return -rte_errno;
594 : : }
595 : :
596 [ # # ]: 0 : if (ptr == NULL) /* dry-run */
597 : : return 0;
598 : :
599 [ # # ]: 0 : return GPU_DRV_RET(dev->ops.mem_free(dev, ptr));
600 : : }
601 : :
602 : : int
603 : 0 : rte_gpu_mem_register(int16_t dev_id, size_t size, void *ptr)
604 : : {
605 : : struct rte_gpu *dev;
606 : :
607 : 0 : dev = gpu_get_by_id(dev_id);
608 [ # # ]: 0 : if (dev == NULL) {
609 : 0 : GPU_LOG(ERR, "alloc mem for invalid device ID %d", dev_id);
610 : 0 : rte_errno = ENODEV;
611 : 0 : return -rte_errno;
612 : : }
613 : :
614 [ # # ]: 0 : if (dev->ops.mem_register == NULL) {
615 : 0 : GPU_LOG(ERR, "mem registration not supported");
616 : 0 : rte_errno = ENOTSUP;
617 : 0 : return -rte_errno;
618 : : }
619 : :
620 [ # # ]: 0 : if (ptr == NULL || size == 0) /* dry-run */
621 : : return 0;
622 : :
623 [ # # ]: 0 : return GPU_DRV_RET(dev->ops.mem_register(dev, size, ptr));
624 : : }
625 : :
626 : : int
627 : 0 : rte_gpu_mem_unregister(int16_t dev_id, void *ptr)
628 : : {
629 : : struct rte_gpu *dev;
630 : :
631 : 0 : dev = gpu_get_by_id(dev_id);
632 [ # # ]: 0 : if (dev == NULL) {
633 : 0 : GPU_LOG(ERR, "unregister mem for invalid device ID %d", dev_id);
634 : 0 : rte_errno = ENODEV;
635 : 0 : return -rte_errno;
636 : : }
637 : :
638 [ # # ]: 0 : if (dev->ops.mem_unregister == NULL) {
639 : 0 : rte_errno = ENOTSUP;
640 : 0 : return -rte_errno;
641 : : }
642 : :
643 [ # # ]: 0 : if (ptr == NULL) /* dry-run */
644 : : return 0;
645 : :
646 [ # # ]: 0 : return GPU_DRV_RET(dev->ops.mem_unregister(dev, ptr));
647 : : }
648 : :
649 : : void *
650 : 0 : rte_gpu_mem_cpu_map(int16_t dev_id, size_t size, void *ptr)
651 : : {
652 : : struct rte_gpu *dev;
653 : : void *ptr_out;
654 : : int ret;
655 : :
656 : 0 : dev = gpu_get_by_id(dev_id);
657 [ # # ]: 0 : if (dev == NULL) {
658 : 0 : GPU_LOG(ERR, "mem CPU map for invalid device ID %d", dev_id);
659 : 0 : rte_errno = ENODEV;
660 : 0 : return NULL;
661 : : }
662 : :
663 [ # # ]: 0 : if (dev->ops.mem_cpu_map == NULL) {
664 : 0 : GPU_LOG(ERR, "mem CPU map not supported");
665 : 0 : rte_errno = ENOTSUP;
666 : 0 : return NULL;
667 : : }
668 : :
669 [ # # ]: 0 : if (ptr == NULL || size == 0) /* dry-run */
670 : : return NULL;
671 : :
672 [ # # ]: 0 : ret = GPU_DRV_RET(dev->ops.mem_cpu_map(dev, size, ptr, &ptr_out));
673 : :
674 [ # # ]: 0 : switch (ret) {
675 : 0 : case 0:
676 : 0 : return ptr_out;
677 : : case -ENOMEM:
678 : : case -E2BIG:
679 : : rte_errno = -ret;
680 : : return NULL;
681 : 0 : default:
682 : 0 : rte_errno = -EPERM;
683 : 0 : return NULL;
684 : : }
685 : : }
686 : :
687 : : int
688 : 0 : rte_gpu_mem_cpu_unmap(int16_t dev_id, void *ptr)
689 : : {
690 : : struct rte_gpu *dev;
691 : :
692 : 0 : dev = gpu_get_by_id(dev_id);
693 [ # # ]: 0 : if (dev == NULL) {
694 : 0 : GPU_LOG(ERR, "cpu_unmap mem for invalid device ID %d", dev_id);
695 : 0 : rte_errno = ENODEV;
696 : 0 : return -rte_errno;
697 : : }
698 : :
699 [ # # ]: 0 : if (dev->ops.mem_cpu_unmap == NULL) {
700 : 0 : rte_errno = ENOTSUP;
701 : 0 : return -rte_errno;
702 : : }
703 : :
704 [ # # ]: 0 : if (ptr == NULL) /* dry-run */
705 : : return 0;
706 : :
707 [ # # ]: 0 : return GPU_DRV_RET(dev->ops.mem_cpu_unmap(dev, ptr));
708 : : }
709 : :
710 : : int
711 : 0 : rte_gpu_wmb(int16_t dev_id)
712 : : {
713 : : struct rte_gpu *dev;
714 : :
715 : 0 : dev = gpu_get_by_id(dev_id);
716 [ # # ]: 0 : if (dev == NULL) {
717 : 0 : GPU_LOG(ERR, "memory barrier for invalid device ID %d", dev_id);
718 : 0 : rte_errno = ENODEV;
719 : 0 : return -rte_errno;
720 : : }
721 : :
722 [ # # ]: 0 : if (dev->ops.wmb == NULL) {
723 : 0 : rte_errno = ENOTSUP;
724 : 0 : return -rte_errno;
725 : : }
726 [ # # ]: 0 : return GPU_DRV_RET(dev->ops.wmb(dev));
727 : : }
728 : :
729 : : int
730 : 0 : rte_gpu_comm_create_flag(uint16_t dev_id, struct rte_gpu_comm_flag *devflag,
731 : : enum rte_gpu_comm_flag_type mtype)
732 : : {
733 : : size_t flag_size;
734 : : int ret;
735 : :
736 [ # # ]: 0 : if (devflag == NULL) {
737 : 0 : rte_errno = EINVAL;
738 : 0 : return -rte_errno;
739 : : }
740 [ # # ]: 0 : if (mtype != RTE_GPU_COMM_FLAG_CPU) {
741 : 0 : rte_errno = EINVAL;
742 : 0 : return -rte_errno;
743 : : }
744 : :
745 : : flag_size = sizeof(uint32_t);
746 : :
747 : 0 : devflag->ptr = rte_zmalloc(NULL, flag_size, 0);
748 [ # # ]: 0 : if (devflag->ptr == NULL) {
749 : 0 : rte_errno = ENOMEM;
750 : 0 : return -rte_errno;
751 : : }
752 : :
753 : 0 : ret = rte_gpu_mem_register(dev_id, flag_size, devflag->ptr);
754 [ # # ]: 0 : if (ret < 0) {
755 : 0 : rte_errno = ENOMEM;
756 : 0 : return -rte_errno;
757 : : }
758 : :
759 : 0 : devflag->mtype = mtype;
760 : 0 : devflag->dev_id = dev_id;
761 : :
762 : 0 : return 0;
763 : : }
764 : :
765 : : int
766 : 0 : rte_gpu_comm_destroy_flag(struct rte_gpu_comm_flag *devflag)
767 : : {
768 : : int ret;
769 : :
770 [ # # ]: 0 : if (devflag == NULL) {
771 : 0 : rte_errno = EINVAL;
772 : 0 : return -rte_errno;
773 : : }
774 : :
775 : 0 : ret = rte_gpu_mem_unregister(devflag->dev_id, devflag->ptr);
776 [ # # ]: 0 : if (ret < 0) {
777 : 0 : rte_errno = EINVAL;
778 : 0 : return -1;
779 : : }
780 : :
781 : 0 : rte_free(devflag->ptr);
782 : :
783 : 0 : return 0;
784 : : }
785 : :
786 : : int
787 : 0 : rte_gpu_comm_set_flag(struct rte_gpu_comm_flag *devflag, uint32_t val)
788 : : {
789 [ # # ]: 0 : if (devflag == NULL) {
790 : 0 : rte_errno = EINVAL;
791 : 0 : return -rte_errno;
792 : : }
793 : :
794 [ # # ]: 0 : if (devflag->mtype != RTE_GPU_COMM_FLAG_CPU) {
795 : 0 : rte_errno = EINVAL;
796 : 0 : return -rte_errno;
797 : : }
798 : :
799 : 0 : RTE_GPU_VOLATILE(*devflag->ptr) = val;
800 : :
801 : 0 : return 0;
802 : : }
803 : :
804 : : int
805 : 0 : rte_gpu_comm_get_flag_value(struct rte_gpu_comm_flag *devflag, uint32_t *val)
806 : : {
807 [ # # ]: 0 : if (devflag == NULL) {
808 : 0 : rte_errno = EINVAL;
809 : 0 : return -rte_errno;
810 : : }
811 [ # # ]: 0 : if (devflag->mtype != RTE_GPU_COMM_FLAG_CPU) {
812 : 0 : rte_errno = EINVAL;
813 : 0 : return -rte_errno;
814 : : }
815 : :
816 : 0 : *val = RTE_GPU_VOLATILE(*devflag->ptr);
817 : :
818 : 0 : return 0;
819 : : }
820 : :
821 : : struct rte_gpu_comm_list *
822 : 0 : rte_gpu_comm_create_list(uint16_t dev_id,
823 : : uint32_t num_comm_items)
824 : : {
825 : : struct rte_gpu_comm_list *comm_list;
826 : : uint32_t idx_l;
827 : : int ret;
828 : : struct rte_gpu *dev;
829 : : struct rte_gpu_info info;
830 : :
831 [ # # ]: 0 : if (num_comm_items == 0) {
832 : 0 : rte_errno = EINVAL;
833 : 0 : return NULL;
834 : : }
835 : :
836 : 0 : dev = gpu_get_by_id(dev_id);
837 [ # # ]: 0 : if (dev == NULL) {
838 : 0 : GPU_LOG(ERR, "memory barrier for invalid device ID %d", dev_id);
839 : 0 : rte_errno = ENODEV;
840 : 0 : return NULL;
841 : : }
842 : :
843 : 0 : ret = rte_gpu_info_get(dev_id, &info);
844 [ # # ]: 0 : if (ret < 0) {
845 : 0 : rte_errno = ENODEV;
846 : 0 : return NULL;
847 : : }
848 : :
849 : 0 : comm_list = rte_zmalloc(NULL,
850 : : sizeof(struct rte_gpu_comm_list) * num_comm_items, 0);
851 [ # # ]: 0 : if (comm_list == NULL) {
852 : 0 : rte_errno = ENOMEM;
853 : 0 : return NULL;
854 : : }
855 : :
856 : 0 : ret = rte_gpu_mem_register(dev_id,
857 : : sizeof(struct rte_gpu_comm_list) * num_comm_items, comm_list);
858 [ # # ]: 0 : if (ret < 0) {
859 : 0 : rte_errno = ENOMEM;
860 : 0 : return NULL;
861 : : }
862 : :
863 : : /*
864 : : * Use GPU memory CPU map feature if enabled in the driver
865 : : * to allocate the status flags of the list.
866 : : * Allocating this flag in GPU memory will reduce
867 : : * the latency when GPU workload is polling this flag.
868 : : */
869 : 0 : comm_list[0].status_d = rte_gpu_mem_alloc(dev_id,
870 : : sizeof(enum rte_gpu_comm_list_status) * num_comm_items,
871 : 0 : info.page_size);
872 : : if (ret < 0) {
873 : : rte_errno = ENOMEM;
874 : : return NULL;
875 : : }
876 : :
877 : 0 : comm_list[0].status_h = rte_gpu_mem_cpu_map(dev_id,
878 : : sizeof(enum rte_gpu_comm_list_status) * num_comm_items,
879 : : comm_list[0].status_d);
880 [ # # ]: 0 : if (comm_list[0].status_h == NULL) {
881 : : /*
882 : : * If CPU mapping is not supported by driver
883 : : * use regular CPU registered memory.
884 : : */
885 : 0 : comm_list[0].status_h = rte_zmalloc(NULL,
886 : : sizeof(enum rte_gpu_comm_list_status) * num_comm_items, 0);
887 [ # # ]: 0 : if (comm_list[0].status_h == NULL) {
888 : 0 : rte_errno = ENOMEM;
889 : 0 : return NULL;
890 : : }
891 : :
892 : 0 : ret = rte_gpu_mem_register(dev_id,
893 : : sizeof(enum rte_gpu_comm_list_status) * num_comm_items,
894 : : comm_list[0].status_h);
895 [ # # ]: 0 : if (ret < 0) {
896 : 0 : rte_errno = ENOMEM;
897 : 0 : return NULL;
898 : : }
899 : :
900 : 0 : comm_list[0].status_d = comm_list[0].status_h;
901 : : }
902 : :
903 [ # # ]: 0 : for (idx_l = 0; idx_l < num_comm_items; idx_l++) {
904 : 0 : comm_list[idx_l].pkt_list = rte_zmalloc(NULL,
905 : : sizeof(struct rte_gpu_comm_pkt) * RTE_GPU_COMM_LIST_PKTS_MAX, 0);
906 [ # # ]: 0 : if (comm_list[idx_l].pkt_list == NULL) {
907 : 0 : rte_errno = ENOMEM;
908 : 0 : return NULL;
909 : : }
910 : :
911 : 0 : ret = rte_gpu_mem_register(dev_id,
912 : : sizeof(struct rte_gpu_comm_pkt) * RTE_GPU_COMM_LIST_PKTS_MAX,
913 : : comm_list[idx_l].pkt_list);
914 [ # # ]: 0 : if (ret < 0) {
915 : 0 : rte_errno = ENOMEM;
916 : 0 : return NULL;
917 : : }
918 : :
919 : 0 : comm_list[idx_l].num_pkts = 0;
920 : 0 : comm_list[idx_l].dev_id = dev_id;
921 : :
922 : 0 : comm_list[idx_l].mbufs = rte_zmalloc(NULL,
923 : : sizeof(struct rte_mbuf *) * RTE_GPU_COMM_LIST_PKTS_MAX, 0);
924 [ # # ]: 0 : if (comm_list[idx_l].mbufs == NULL) {
925 : 0 : rte_errno = ENOMEM;
926 : 0 : return NULL;
927 : : }
928 : :
929 [ # # ]: 0 : if (idx_l > 0) {
930 : 0 : comm_list[idx_l].status_h = &(comm_list[0].status_h[idx_l]);
931 : 0 : comm_list[idx_l].status_d = &(comm_list[0].status_d[idx_l]);
932 : :
933 : 0 : ret = rte_gpu_comm_set_status(&comm_list[idx_l], RTE_GPU_COMM_LIST_FREE);
934 [ # # ]: 0 : if (ret < 0) {
935 : 0 : rte_errno = ENOMEM;
936 : 0 : return NULL;
937 : : }
938 : : }
939 : : }
940 : :
941 : : return comm_list;
942 : : }
943 : :
944 : : int
945 : 0 : rte_gpu_comm_destroy_list(struct rte_gpu_comm_list *comm_list,
946 : : uint32_t num_comm_items)
947 : : {
948 : : uint32_t idx_l;
949 : : int ret;
950 : : uint16_t dev_id;
951 : :
952 [ # # ]: 0 : if (comm_list == NULL) {
953 : 0 : rte_errno = EINVAL;
954 : 0 : return -rte_errno;
955 : : }
956 : :
957 : 0 : dev_id = comm_list[0].dev_id;
958 : :
959 [ # # ]: 0 : for (idx_l = 0; idx_l < num_comm_items; idx_l++) {
960 : 0 : ret = rte_gpu_mem_unregister(dev_id, comm_list[idx_l].pkt_list);
961 [ # # ]: 0 : if (ret < 0) {
962 : 0 : rte_errno = EINVAL;
963 : 0 : return -1;
964 : : }
965 : :
966 : 0 : rte_free(comm_list[idx_l].pkt_list);
967 : 0 : rte_free(comm_list[idx_l].mbufs);
968 : : }
969 : :
970 : 0 : ret = rte_gpu_mem_unregister(dev_id, comm_list);
971 [ # # ]: 0 : if (ret < 0) {
972 : 0 : rte_errno = EINVAL;
973 : 0 : return -1;
974 : : }
975 : :
976 : 0 : ret = rte_gpu_mem_cpu_unmap(dev_id, comm_list[0].status_d);
977 [ # # ]: 0 : if (ret == 0) {
978 : 0 : rte_gpu_mem_free(dev_id, comm_list[0].status_d);
979 : : } else {
980 : 0 : rte_gpu_mem_unregister(dev_id, comm_list[0].status_h);
981 : 0 : rte_free(comm_list[0].status_h);
982 : : }
983 : :
984 : 0 : rte_free(comm_list);
985 : :
986 : 0 : return 0;
987 : : }
988 : :
989 : : int
990 : 0 : rte_gpu_comm_populate_list_pkts(struct rte_gpu_comm_list *comm_list_item,
991 : : struct rte_mbuf **mbufs, uint32_t num_mbufs)
992 : : {
993 : : uint32_t idx;
994 : : int ret;
995 : :
996 [ # # # # ]: 0 : if (comm_list_item == NULL || comm_list_item->pkt_list == NULL ||
997 [ # # ]: 0 : mbufs == NULL || num_mbufs > RTE_GPU_COMM_LIST_PKTS_MAX) {
998 : 0 : rte_errno = EINVAL;
999 : 0 : return -rte_errno;
1000 : : }
1001 : :
1002 [ # # ]: 0 : for (idx = 0; idx < num_mbufs; idx++) {
1003 : : /* support only unchained mbufs */
1004 [ # # # # : 0 : if (unlikely((mbufs[idx]->nb_segs > 1) ||
# # ]
1005 : : (mbufs[idx]->next != NULL) ||
1006 : : (mbufs[idx]->data_len != mbufs[idx]->pkt_len))) {
1007 : 0 : rte_errno = ENOTSUP;
1008 : 0 : return -rte_errno;
1009 : : }
1010 : 0 : comm_list_item->pkt_list[idx].addr =
1011 : 0 : rte_pktmbuf_mtod_offset(mbufs[idx], uintptr_t, 0);
1012 : 0 : comm_list_item->pkt_list[idx].size = mbufs[idx]->pkt_len;
1013 : 0 : comm_list_item->mbufs[idx] = mbufs[idx];
1014 : : }
1015 : :
1016 : 0 : RTE_GPU_VOLATILE(comm_list_item->num_pkts) = num_mbufs;
1017 : 0 : rte_gpu_wmb(comm_list_item->dev_id);
1018 : 0 : ret = rte_gpu_comm_set_status(comm_list_item, RTE_GPU_COMM_LIST_READY);
1019 [ # # ]: 0 : if (ret < 0) {
1020 : 0 : rte_errno = EINVAL;
1021 : 0 : return -rte_errno;
1022 : : }
1023 : :
1024 : : return 0;
1025 : : }
1026 : :
1027 : : int
1028 : 0 : rte_gpu_comm_set_status(struct rte_gpu_comm_list *comm_list_item,
1029 : : enum rte_gpu_comm_list_status status)
1030 : : {
1031 [ # # ]: 0 : if (comm_list_item == NULL) {
1032 : 0 : rte_errno = EINVAL;
1033 : 0 : return -rte_errno;
1034 : : }
1035 : :
1036 : 0 : RTE_GPU_VOLATILE(comm_list_item->status_h[0]) = status;
1037 : :
1038 : 0 : return 0;
1039 : : }
1040 : :
1041 : : int
1042 : 0 : rte_gpu_comm_get_status(struct rte_gpu_comm_list *comm_list_item,
1043 : : enum rte_gpu_comm_list_status *status)
1044 : : {
1045 [ # # ]: 0 : if (comm_list_item == NULL || status == NULL) {
1046 : 0 : rte_errno = EINVAL;
1047 : 0 : return -rte_errno;
1048 : : }
1049 : :
1050 : 0 : *status = RTE_GPU_VOLATILE(comm_list_item->status_h[0]);
1051 : :
1052 : 0 : return 0;
1053 : : }
1054 : :
1055 : : int
1056 : 0 : rte_gpu_comm_cleanup_list(struct rte_gpu_comm_list *comm_list_item)
1057 : : {
1058 : : uint32_t idx = 0;
1059 : : enum rte_gpu_comm_list_status status;
1060 : : int ret;
1061 : :
1062 [ # # ]: 0 : if (comm_list_item == NULL) {
1063 : 0 : rte_errno = EINVAL;
1064 : 0 : return -rte_errno;
1065 : : }
1066 : :
1067 : 0 : ret = rte_gpu_comm_get_status(comm_list_item, &status);
1068 [ # # ]: 0 : if (ret < 0) {
1069 : 0 : rte_errno = EINVAL;
1070 : 0 : return -rte_errno;
1071 : : }
1072 : :
1073 [ # # ]: 0 : if (status == RTE_GPU_COMM_LIST_READY) {
1074 : 0 : GPU_LOG(ERR, "packet list is still in progress");
1075 : 0 : rte_errno = EINVAL;
1076 : 0 : return -rte_errno;
1077 : : }
1078 : :
1079 [ # # ]: 0 : for (idx = 0; idx < RTE_GPU_COMM_LIST_PKTS_MAX; idx++) {
1080 [ # # ]: 0 : if (comm_list_item->pkt_list[idx].addr == 0)
1081 : : break;
1082 : :
1083 : 0 : comm_list_item->pkt_list[idx].addr = 0;
1084 : 0 : comm_list_item->pkt_list[idx].size = 0;
1085 : 0 : comm_list_item->mbufs[idx] = NULL;
1086 : : }
1087 : :
1088 : 0 : ret = rte_gpu_comm_set_status(comm_list_item, RTE_GPU_COMM_LIST_FREE);
1089 [ # # ]: 0 : if (ret < 0) {
1090 : 0 : rte_errno = EINVAL;
1091 : 0 : return -rte_errno;
1092 : : }
1093 : 0 : RTE_GPU_VOLATILE(comm_list_item->num_pkts) = 0;
1094 : : rte_mb();
1095 : :
1096 : 0 : return 0;
1097 : : }
|