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