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