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