]> git.proxmox.com Git - ceph.git/blame - ceph/src/spdk/dpdk/lib/librte_eal/common/eal_common_dev.c
import 15.2.0 Octopus source
[ceph.git] / ceph / src / spdk / dpdk / lib / librte_eal / common / eal_common_dev.c
CommitLineData
11fdf7f2
TL
1/* SPDX-License-Identifier: BSD-3-Clause
2 * Copyright(c) 2010-2014 Intel Corporation.
3 * Copyright(c) 2014 6WIND S.A.
4 */
5
6#include <stdio.h>
7#include <string.h>
8#include <inttypes.h>
9#include <sys/queue.h>
10
11#include <rte_compat.h>
12#include <rte_bus.h>
13#include <rte_class.h>
14#include <rte_dev.h>
15#include <rte_devargs.h>
16#include <rte_debug.h>
17#include <rte_errno.h>
18#include <rte_kvargs.h>
19#include <rte_log.h>
20#include <rte_spinlock.h>
21#include <rte_malloc.h>
9f95a23c 22#include <rte_string_fns.h>
11fdf7f2
TL
23
24#include "eal_private.h"
9f95a23c 25#include "hotplug_mp.h"
11fdf7f2
TL
26
27/**
28 * The device event callback description.
29 *
30 * It contains callback address to be registered by user application,
31 * the pointer to the parameters for callback, and the device name.
32 */
33struct dev_event_callback {
34 TAILQ_ENTRY(dev_event_callback) next; /**< Callbacks list */
35 rte_dev_event_cb_fn cb_fn; /**< Callback address */
36 void *cb_arg; /**< Callback parameter */
37 char *dev_name; /**< Callback device name, NULL is for all device */
38 uint32_t active; /**< Callback is executing */
39};
40
41/** @internal Structure to keep track of registered callbacks */
42TAILQ_HEAD(dev_event_cb_list, dev_event_callback);
43
44/* The device event callback list for all registered callbacks. */
45static struct dev_event_cb_list dev_event_cbs;
46
47/* spinlock for device callbacks */
48static rte_spinlock_t dev_event_lock = RTE_SPINLOCK_INITIALIZER;
49
50struct dev_next_ctx {
51 struct rte_dev_iterator *it;
52 const char *bus_str;
53 const char *cls_str;
54};
55
56#define CTX(it, bus_str, cls_str) \
57 (&(const struct dev_next_ctx){ \
58 .it = it, \
59 .bus_str = bus_str, \
60 .cls_str = cls_str, \
61 })
62
63#define ITCTX(ptr) \
64 (((struct dev_next_ctx *)(intptr_t)ptr)->it)
65
66#define BUSCTX(ptr) \
67 (((struct dev_next_ctx *)(intptr_t)ptr)->bus_str)
68
69#define CLSCTX(ptr) \
70 (((struct dev_next_ctx *)(intptr_t)ptr)->cls_str)
71
72static int cmp_dev_name(const struct rte_device *dev, const void *_name)
73{
74 const char *name = _name;
75
76 return strcmp(dev->name, name);
77}
78
9f95a23c
TL
79int
80rte_dev_is_probed(const struct rte_device *dev)
11fdf7f2 81{
9f95a23c
TL
82 /* The field driver should be set only when the probe is successful. */
83 return dev->driver != NULL;
84}
85
86/* helper function to build devargs, caller should free the memory */
87static int
88build_devargs(const char *busname, const char *devname,
89 const char *drvargs, char **devargs)
90{
91 int length;
11fdf7f2 92
9f95a23c
TL
93 length = snprintf(NULL, 0, "%s:%s,%s", busname, devname, drvargs);
94 if (length < 0)
11fdf7f2 95 return -EINVAL;
11fdf7f2 96
9f95a23c
TL
97 *devargs = malloc(length + 1);
98 if (*devargs == NULL)
99 return -ENOMEM;
100
101 length = snprintf(*devargs, length + 1, "%s:%s,%s",
102 busname, devname, drvargs);
103 if (length < 0) {
104 free(*devargs);
11fdf7f2
TL
105 return -EINVAL;
106 }
11fdf7f2 107
9f95a23c 108 return 0;
11fdf7f2
TL
109}
110
9f95a23c
TL
111int
112rte_eal_hotplug_add(const char *busname, const char *devname,
113 const char *drvargs)
11fdf7f2 114{
9f95a23c
TL
115
116 char *devargs;
11fdf7f2
TL
117 int ret;
118
9f95a23c
TL
119 ret = build_devargs(busname, devname, drvargs, &devargs);
120 if (ret != 0)
121 return ret;
11fdf7f2 122
9f95a23c
TL
123 ret = rte_dev_probe(devargs);
124 free(devargs);
11fdf7f2 125
11fdf7f2
TL
126 return ret;
127}
128
9f95a23c
TL
129/* probe device at local process. */
130int
131local_dev_probe(const char *devargs, struct rte_device **new_dev)
11fdf7f2 132{
11fdf7f2
TL
133 struct rte_device *dev;
134 struct rte_devargs *da;
135 int ret;
136
9f95a23c 137 *new_dev = NULL;
11fdf7f2
TL
138 da = calloc(1, sizeof(*da));
139 if (da == NULL)
140 return -ENOMEM;
141
9f95a23c 142 ret = rte_devargs_parse(da, devargs);
11fdf7f2
TL
143 if (ret)
144 goto err_devarg;
145
9f95a23c
TL
146 if (da->bus->plug == NULL) {
147 RTE_LOG(ERR, EAL, "Function plug not supported by bus (%s)\n",
148 da->bus->name);
149 ret = -ENOTSUP;
150 goto err_devarg;
151 }
152
153 ret = rte_devargs_insert(&da);
11fdf7f2
TL
154 if (ret)
155 goto err_devarg;
156
9f95a23c
TL
157 /* the rte_devargs will be referenced in the matching rte_device */
158 ret = da->bus->scan();
11fdf7f2
TL
159 if (ret)
160 goto err_devarg;
161
9f95a23c 162 dev = da->bus->find_device(NULL, cmp_dev_name, da->name);
11fdf7f2
TL
163 if (dev == NULL) {
164 RTE_LOG(ERR, EAL, "Cannot find device (%s)\n",
9f95a23c 165 da->name);
11fdf7f2
TL
166 ret = -ENODEV;
167 goto err_devarg;
168 }
9f95a23c
TL
169 /* Since there is a matching device, it is now its responsibility
170 * to manage the devargs we've just inserted. From this point
171 * those devargs shouldn't be removed manually anymore.
172 */
11fdf7f2 173
9f95a23c
TL
174 ret = dev->bus->plug(dev);
175 if (ret && !rte_dev_is_probed(dev)) { /* if hasn't ever succeeded */
11fdf7f2
TL
176 RTE_LOG(ERR, EAL, "Driver cannot attach the device (%s)\n",
177 dev->name);
9f95a23c 178 return ret;
11fdf7f2 179 }
9f95a23c
TL
180
181 *new_dev = dev;
182 return ret;
11fdf7f2
TL
183
184err_devarg:
9f95a23c 185 if (rte_devargs_remove(da) != 0) {
11fdf7f2
TL
186 free(da->args);
187 free(da);
188 }
189 return ret;
190}
191
9f95a23c
TL
192int
193rte_dev_probe(const char *devargs)
11fdf7f2 194{
9f95a23c 195 struct eal_dev_mp_req req;
11fdf7f2
TL
196 struct rte_device *dev;
197 int ret;
198
9f95a23c
TL
199 memset(&req, 0, sizeof(req));
200 req.t = EAL_DEV_REQ_TYPE_ATTACH;
201 strlcpy(req.devargs, devargs, EAL_DEV_MP_DEV_ARGS_MAX_LEN);
202
203 if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
204 /**
205 * If in secondary process, just send IPC request to
206 * primary process.
207 */
208 ret = eal_dev_hotplug_request_to_primary(&req);
209 if (ret != 0) {
210 RTE_LOG(ERR, EAL,
211 "Failed to send hotplug request to primary\n");
212 return -ENOMSG;
213 }
214 if (req.result != 0)
215 RTE_LOG(ERR, EAL,
216 "Failed to hotplug add device\n");
217 return req.result;
218 }
219
220 /* attach a shared device from primary start from here: */
221
222 /* primary attach the new device itself. */
223 ret = local_dev_probe(devargs, &dev);
224
225 if (ret != 0) {
226 RTE_LOG(ERR, EAL,
227 "Failed to attach device on primary process\n");
228
229 /**
230 * it is possible that secondary process failed to attached a
231 * device that primary process have during initialization,
232 * so for -EEXIST case, we still need to sync with secondary
233 * process.
234 */
235 if (ret != -EEXIST)
236 return ret;
237 }
238
239 /* primary send attach sync request to secondary. */
240 ret = eal_dev_hotplug_request_to_secondary(&req);
241
242 /* if any communication error, we need to rollback. */
243 if (ret != 0) {
244 RTE_LOG(ERR, EAL,
245 "Failed to send hotplug add request to secondary\n");
246 ret = -ENOMSG;
247 goto rollback;
248 }
249
250 /**
251 * if any secondary failed to attach, we need to consider if rollback
252 * is necessary.
253 */
254 if (req.result != 0) {
255 RTE_LOG(ERR, EAL,
256 "Failed to attach device on secondary process\n");
257 ret = req.result;
258
259 /* for -EEXIST, we don't need to rollback. */
260 if (ret == -EEXIST)
261 return ret;
262 goto rollback;
263 }
264
265 return 0;
266
267rollback:
268 req.t = EAL_DEV_REQ_TYPE_ATTACH_ROLLBACK;
269
270 /* primary send rollback request to secondary. */
271 if (eal_dev_hotplug_request_to_secondary(&req) != 0)
272 RTE_LOG(WARNING, EAL,
273 "Failed to rollback device attach on secondary."
274 "Devices in secondary may not sync with primary\n");
275
276 /* primary rollback itself. */
277 if (local_dev_remove(dev) != 0)
278 RTE_LOG(WARNING, EAL,
279 "Failed to rollback device attach on primary."
280 "Devices in secondary may not sync with primary\n");
281
282 return ret;
283}
284
285int
286rte_eal_hotplug_remove(const char *busname, const char *devname)
287{
288 struct rte_device *dev;
289 struct rte_bus *bus;
290
11fdf7f2
TL
291 bus = rte_bus_find_by_name(busname);
292 if (bus == NULL) {
293 RTE_LOG(ERR, EAL, "Cannot find bus (%s)\n", busname);
294 return -ENOENT;
295 }
296
11fdf7f2
TL
297 dev = bus->find_device(NULL, cmp_dev_name, devname);
298 if (dev == NULL) {
299 RTE_LOG(ERR, EAL, "Cannot find plugged device (%s)\n", devname);
300 return -EINVAL;
301 }
302
9f95a23c
TL
303 return rte_dev_remove(dev);
304}
305
306/* remove device at local process. */
307int
308local_dev_remove(struct rte_device *dev)
309{
310 int ret;
311
312 if (dev->bus->unplug == NULL) {
313 RTE_LOG(ERR, EAL, "Function unplug not supported by bus (%s)\n",
314 dev->bus->name);
315 return -ENOTSUP;
11fdf7f2
TL
316 }
317
9f95a23c
TL
318 ret = dev->bus->unplug(dev);
319 if (ret) {
11fdf7f2
TL
320 RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n",
321 dev->name);
9f95a23c
TL
322 return ret;
323 }
324
325 return 0;
326}
327
328int
329rte_dev_remove(struct rte_device *dev)
330{
331 struct eal_dev_mp_req req;
332 char *devargs;
333 int ret;
334
335 if (!rte_dev_is_probed(dev)) {
336 RTE_LOG(ERR, EAL, "Device is not probed\n");
337 return -ENOENT;
338 }
339
340 ret = build_devargs(dev->bus->name, dev->name, "", &devargs);
341 if (ret != 0)
342 return ret;
343
344 memset(&req, 0, sizeof(req));
345 req.t = EAL_DEV_REQ_TYPE_DETACH;
346 strlcpy(req.devargs, devargs, EAL_DEV_MP_DEV_ARGS_MAX_LEN);
347 free(devargs);
348
349 if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
350 /**
351 * If in secondary process, just send IPC request to
352 * primary process.
353 */
354 ret = eal_dev_hotplug_request_to_primary(&req);
355 if (ret != 0) {
356 RTE_LOG(ERR, EAL,
357 "Failed to send hotplug request to primary\n");
358 return -ENOMSG;
359 }
360 if (req.result != 0)
361 RTE_LOG(ERR, EAL,
362 "Failed to hotplug remove device\n");
363 return req.result;
364 }
365
366 /* detach a device from primary start from here: */
367
368 /* primary send detach sync request to secondary */
369 ret = eal_dev_hotplug_request_to_secondary(&req);
370
371 /**
372 * if communication error, we need to rollback, because it is possible
373 * part of the secondary processes still detached it successfully.
374 */
375 if (ret != 0) {
376 RTE_LOG(ERR, EAL,
377 "Failed to send device detach request to secondary\n");
378 ret = -ENOMSG;
379 goto rollback;
380 }
381
382 /**
383 * if any secondary failed to detach, we need to consider if rollback
384 * is necessary.
385 */
386 if (req.result != 0) {
387 RTE_LOG(ERR, EAL,
388 "Failed to detach device on secondary process\n");
389 ret = req.result;
390 /**
391 * if -ENOENT, we don't need to rollback, since devices is
392 * already detached on secondary process.
393 */
394 if (ret != -ENOENT)
395 goto rollback;
396 }
397
398 /* primary detach the device itself. */
399 ret = local_dev_remove(dev);
400
401 /* if primary failed, still need to consider if rollback is necessary */
402 if (ret != 0) {
403 RTE_LOG(ERR, EAL,
404 "Failed to detach device on primary process\n");
405 /* if -ENOENT, we don't need to rollback */
406 if (ret == -ENOENT)
407 return ret;
408 goto rollback;
409 }
410
411 return 0;
412
413rollback:
414 req.t = EAL_DEV_REQ_TYPE_DETACH_ROLLBACK;
415
416 /* primary send rollback request to secondary. */
417 if (eal_dev_hotplug_request_to_secondary(&req) != 0)
418 RTE_LOG(WARNING, EAL,
419 "Failed to rollback device detach on secondary."
420 "Devices in secondary may not sync with primary\n");
421
11fdf7f2
TL
422 return ret;
423}
424
425int __rte_experimental
426rte_dev_event_callback_register(const char *device_name,
427 rte_dev_event_cb_fn cb_fn,
428 void *cb_arg)
429{
430 struct dev_event_callback *event_cb;
431 int ret;
432
433 if (!cb_fn)
434 return -EINVAL;
435
436 rte_spinlock_lock(&dev_event_lock);
437
438 if (TAILQ_EMPTY(&dev_event_cbs))
439 TAILQ_INIT(&dev_event_cbs);
440
441 TAILQ_FOREACH(event_cb, &dev_event_cbs, next) {
442 if (event_cb->cb_fn == cb_fn && event_cb->cb_arg == cb_arg) {
443 if (device_name == NULL && event_cb->dev_name == NULL)
444 break;
445 if (device_name == NULL || event_cb->dev_name == NULL)
446 continue;
447 if (!strcmp(event_cb->dev_name, device_name))
448 break;
449 }
450 }
451
452 /* create a new callback. */
453 if (event_cb == NULL) {
454 event_cb = malloc(sizeof(struct dev_event_callback));
455 if (event_cb != NULL) {
456 event_cb->cb_fn = cb_fn;
457 event_cb->cb_arg = cb_arg;
458 event_cb->active = 0;
459 if (!device_name) {
460 event_cb->dev_name = NULL;
461 } else {
462 event_cb->dev_name = strdup(device_name);
463 if (event_cb->dev_name == NULL) {
464 ret = -ENOMEM;
465 goto error;
466 }
467 }
468 TAILQ_INSERT_TAIL(&dev_event_cbs, event_cb, next);
469 } else {
470 RTE_LOG(ERR, EAL,
471 "Failed to allocate memory for device "
472 "event callback.");
473 ret = -ENOMEM;
474 goto error;
475 }
476 } else {
477 RTE_LOG(ERR, EAL,
478 "The callback is already exist, no need "
479 "to register again.\n");
480 ret = -EEXIST;
481 }
482
483 rte_spinlock_unlock(&dev_event_lock);
484 return 0;
485error:
486 free(event_cb);
487 rte_spinlock_unlock(&dev_event_lock);
488 return ret;
489}
490
491int __rte_experimental
492rte_dev_event_callback_unregister(const char *device_name,
493 rte_dev_event_cb_fn cb_fn,
494 void *cb_arg)
495{
496 int ret = 0;
497 struct dev_event_callback *event_cb, *next;
498
499 if (!cb_fn)
500 return -EINVAL;
501
502 rte_spinlock_lock(&dev_event_lock);
503 /*walk through the callbacks and remove all that match. */
504 for (event_cb = TAILQ_FIRST(&dev_event_cbs); event_cb != NULL;
505 event_cb = next) {
506
507 next = TAILQ_NEXT(event_cb, next);
508
509 if (device_name != NULL && event_cb->dev_name != NULL) {
510 if (!strcmp(event_cb->dev_name, device_name)) {
511 if (event_cb->cb_fn != cb_fn ||
512 (cb_arg != (void *)-1 &&
513 event_cb->cb_arg != cb_arg))
514 continue;
515 }
516 } else if (device_name != NULL) {
517 continue;
518 }
519
520 /*
521 * if this callback is not executing right now,
522 * then remove it.
523 */
524 if (event_cb->active == 0) {
525 TAILQ_REMOVE(&dev_event_cbs, event_cb, next);
526 free(event_cb);
527 ret++;
528 } else {
529 continue;
530 }
531 }
532 rte_spinlock_unlock(&dev_event_lock);
533 return ret;
534}
535
9f95a23c
TL
536void __rte_experimental
537rte_dev_event_callback_process(const char *device_name,
538 enum rte_dev_event_type event)
11fdf7f2
TL
539{
540 struct dev_event_callback *cb_lst;
541
542 if (device_name == NULL)
543 return;
544
545 rte_spinlock_lock(&dev_event_lock);
546
547 TAILQ_FOREACH(cb_lst, &dev_event_cbs, next) {
548 if (cb_lst->dev_name) {
549 if (strcmp(cb_lst->dev_name, device_name))
550 continue;
551 }
552 cb_lst->active = 1;
553 rte_spinlock_unlock(&dev_event_lock);
554 cb_lst->cb_fn(device_name, event,
555 cb_lst->cb_arg);
556 rte_spinlock_lock(&dev_event_lock);
557 cb_lst->active = 0;
558 }
559 rte_spinlock_unlock(&dev_event_lock);
560}
561
562__rte_experimental
563int
564rte_dev_iterator_init(struct rte_dev_iterator *it,
565 const char *dev_str)
566{
567 struct rte_devargs devargs;
568 struct rte_class *cls = NULL;
569 struct rte_bus *bus = NULL;
570
571 /* Having both bus_str and cls_str NULL is illegal,
572 * marking this iterator as invalid unless
573 * everything goes well.
574 */
575 it->bus_str = NULL;
576 it->cls_str = NULL;
577
578 devargs.data = dev_str;
579 if (rte_devargs_layers_parse(&devargs, dev_str))
580 goto get_out;
581
582 bus = devargs.bus;
583 cls = devargs.cls;
584 /* The string should have at least
585 * one layer specified.
586 */
587 if (bus == NULL && cls == NULL) {
588 RTE_LOG(ERR, EAL,
589 "Either bus or class must be specified.\n");
590 rte_errno = EINVAL;
591 goto get_out;
592 }
593 if (bus != NULL && bus->dev_iterate == NULL) {
594 RTE_LOG(ERR, EAL, "Bus %s not supported\n", bus->name);
595 rte_errno = ENOTSUP;
596 goto get_out;
597 }
598 if (cls != NULL && cls->dev_iterate == NULL) {
599 RTE_LOG(ERR, EAL, "Class %s not supported\n", cls->name);
600 rte_errno = ENOTSUP;
601 goto get_out;
602 }
603 it->bus_str = devargs.bus_str;
604 it->cls_str = devargs.cls_str;
605 it->dev_str = dev_str;
606 it->bus = bus;
607 it->cls = cls;
608 it->device = NULL;
609 it->class_device = NULL;
610get_out:
611 return -rte_errno;
612}
613
614static char *
615dev_str_sane_copy(const char *str)
616{
617 size_t end;
618 char *copy;
619
620 end = strcspn(str, ",/");
621 if (str[end] == ',') {
622 copy = strdup(&str[end + 1]);
623 } else {
624 /* '/' or '\0' */
625 copy = strdup("");
626 }
627 if (copy == NULL) {
628 rte_errno = ENOMEM;
629 } else {
630 char *slash;
631
632 slash = strchr(copy, '/');
633 if (slash != NULL)
634 slash[0] = '\0';
635 }
636 return copy;
637}
638
639static int
640class_next_dev_cmp(const struct rte_class *cls,
641 const void *ctx)
642{
643 struct rte_dev_iterator *it;
644 const char *cls_str = NULL;
645 void *dev;
646
647 if (cls->dev_iterate == NULL)
648 return 1;
649 it = ITCTX(ctx);
650 cls_str = CLSCTX(ctx);
651 dev = it->class_device;
652 /* it->cls_str != NULL means a class
653 * was specified in the devstr.
654 */
655 if (it->cls_str != NULL && cls != it->cls)
656 return 1;
657 /* If an error occurred previously,
658 * no need to test further.
659 */
660 if (rte_errno != 0)
661 return -1;
662 dev = cls->dev_iterate(dev, cls_str, it);
663 it->class_device = dev;
664 return dev == NULL;
665}
666
667static int
668bus_next_dev_cmp(const struct rte_bus *bus,
669 const void *ctx)
670{
671 struct rte_device *dev = NULL;
672 struct rte_class *cls = NULL;
673 struct rte_dev_iterator *it;
674 const char *bus_str = NULL;
675
676 if (bus->dev_iterate == NULL)
677 return 1;
678 it = ITCTX(ctx);
679 bus_str = BUSCTX(ctx);
680 dev = it->device;
681 /* it->bus_str != NULL means a bus
682 * was specified in the devstr.
683 */
684 if (it->bus_str != NULL && bus != it->bus)
685 return 1;
686 /* If an error occurred previously,
687 * no need to test further.
688 */
689 if (rte_errno != 0)
690 return -1;
691 if (it->cls_str == NULL) {
692 dev = bus->dev_iterate(dev, bus_str, it);
693 goto end;
694 }
695 /* cls_str != NULL */
696 if (dev == NULL) {
697next_dev_on_bus:
698 dev = bus->dev_iterate(dev, bus_str, it);
699 it->device = dev;
700 }
701 if (dev == NULL)
702 return 1;
703 if (it->cls != NULL)
704 cls = TAILQ_PREV(it->cls, rte_class_list, next);
705 cls = rte_class_find(cls, class_next_dev_cmp, ctx);
706 if (cls != NULL) {
707 it->cls = cls;
708 goto end;
709 }
710 goto next_dev_on_bus;
711end:
712 it->device = dev;
713 return dev == NULL;
714}
715__rte_experimental
716struct rte_device *
717rte_dev_iterator_next(struct rte_dev_iterator *it)
718{
719 struct rte_bus *bus = NULL;
720 int old_errno = rte_errno;
721 char *bus_str = NULL;
722 char *cls_str = NULL;
723
724 rte_errno = 0;
725 if (it->bus_str == NULL && it->cls_str == NULL) {
726 /* Invalid iterator. */
727 rte_errno = EINVAL;
728 return NULL;
729 }
730 if (it->bus != NULL)
731 bus = TAILQ_PREV(it->bus, rte_bus_list, next);
732 if (it->bus_str != NULL) {
733 bus_str = dev_str_sane_copy(it->bus_str);
734 if (bus_str == NULL)
735 goto out;
736 }
737 if (it->cls_str != NULL) {
738 cls_str = dev_str_sane_copy(it->cls_str);
739 if (cls_str == NULL)
740 goto out;
741 }
742 while ((bus = rte_bus_find(bus, bus_next_dev_cmp,
743 CTX(it, bus_str, cls_str)))) {
744 if (it->device != NULL) {
745 it->bus = bus;
746 goto out;
747 }
748 if (it->bus_str != NULL ||
749 rte_errno != 0)
750 break;
751 }
752 if (rte_errno == 0)
753 rte_errno = old_errno;
754out:
755 free(bus_str);
756 free(cls_str);
757 return it->device;
758}
9f95a23c
TL
759
760int
761rte_dev_dma_map(struct rte_device *dev, void *addr, uint64_t iova,
762 size_t len)
763{
764 if (dev->bus->dma_map == NULL || len == 0) {
765 rte_errno = ENOTSUP;
766 return -1;
767 }
768 /* Memory must be registered through rte_extmem_* APIs */
769 if (rte_mem_virt2memseg_list(addr) == NULL) {
770 rte_errno = EINVAL;
771 return -1;
772 }
773
774 return dev->bus->dma_map(dev, addr, iova, len);
775}
776
777int
778rte_dev_dma_unmap(struct rte_device *dev, void *addr, uint64_t iova,
779 size_t len)
780{
781 if (dev->bus->dma_unmap == NULL || len == 0) {
782 rte_errno = ENOTSUP;
783 return -1;
784 }
785 /* Memory must be registered through rte_extmem_* APIs */
786 if (rte_mem_virt2memseg_list(addr) == NULL) {
787 rte_errno = EINVAL;
788 return -1;
789 }
790
791 return dev->bus->dma_unmap(dev, addr, iova, len);
792}