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