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