xref: /dpdk/lib/eal/common/eal_common_dev.c (revision 448e01f1b5848b20cb0300d339100dd82f4459e9)
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 		free(da);
186 	}
187 	return ret;
188 }
189 
190 int
191 rte_dev_probe(const char *devargs)
192 {
193 	struct eal_dev_mp_req req;
194 	struct rte_device *dev;
195 	int ret;
196 
197 	memset(&req, 0, sizeof(req));
198 	req.t = EAL_DEV_REQ_TYPE_ATTACH;
199 	strlcpy(req.devargs, devargs, EAL_DEV_MP_DEV_ARGS_MAX_LEN);
200 
201 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
202 		/**
203 		 * If in secondary process, just send IPC request to
204 		 * primary process.
205 		 */
206 		ret = eal_dev_hotplug_request_to_primary(&req);
207 		if (ret != 0) {
208 			RTE_LOG(ERR, EAL,
209 				"Failed to send hotplug request to primary\n");
210 			return -ENOMSG;
211 		}
212 		if (req.result != 0)
213 			RTE_LOG(ERR, EAL,
214 				"Failed to hotplug add device\n");
215 		return req.result;
216 	}
217 
218 	/* attach a shared device from primary start from here: */
219 
220 	/* primary attach the new device itself. */
221 	ret = local_dev_probe(devargs, &dev);
222 
223 	if (ret != 0) {
224 		RTE_LOG(ERR, EAL,
225 			"Failed to attach device on primary process\n");
226 
227 		/**
228 		 * it is possible that secondary process failed to attached a
229 		 * device that primary process have during initialization,
230 		 * so for -EEXIST case, we still need to sync with secondary
231 		 * process.
232 		 */
233 		if (ret != -EEXIST)
234 			return ret;
235 	}
236 
237 	/* primary send attach sync request to secondary. */
238 	ret = eal_dev_hotplug_request_to_secondary(&req);
239 
240 	/* if any communication error, we need to rollback. */
241 	if (ret != 0) {
242 		RTE_LOG(ERR, EAL,
243 			"Failed to send hotplug add request to secondary\n");
244 		ret = -ENOMSG;
245 		goto rollback;
246 	}
247 
248 	/**
249 	 * if any secondary failed to attach, we need to consider if rollback
250 	 * is necessary.
251 	 */
252 	if (req.result != 0) {
253 		RTE_LOG(ERR, EAL,
254 			"Failed to attach device on secondary process\n");
255 		ret = req.result;
256 
257 		/* for -EEXIST, we don't need to rollback. */
258 		if (ret == -EEXIST)
259 			return ret;
260 		goto rollback;
261 	}
262 
263 	return 0;
264 
265 rollback:
266 	req.t = EAL_DEV_REQ_TYPE_ATTACH_ROLLBACK;
267 
268 	/* primary send rollback request to secondary. */
269 	if (eal_dev_hotplug_request_to_secondary(&req) != 0)
270 		RTE_LOG(WARNING, EAL,
271 			"Failed to rollback device attach on secondary."
272 			"Devices in secondary may not sync with primary\n");
273 
274 	/* primary rollback itself. */
275 	if (local_dev_remove(dev) != 0)
276 		RTE_LOG(WARNING, EAL,
277 			"Failed to rollback device attach on primary."
278 			"Devices in secondary may not sync with primary\n");
279 
280 	return ret;
281 }
282 
283 int
284 rte_eal_hotplug_remove(const char *busname, const char *devname)
285 {
286 	struct rte_device *dev;
287 	struct rte_bus *bus;
288 
289 	bus = rte_bus_find_by_name(busname);
290 	if (bus == NULL) {
291 		RTE_LOG(ERR, EAL, "Cannot find bus (%s)\n", busname);
292 		return -ENOENT;
293 	}
294 
295 	dev = bus->find_device(NULL, cmp_dev_name, devname);
296 	if (dev == NULL) {
297 		RTE_LOG(ERR, EAL, "Cannot find plugged device (%s)\n", devname);
298 		return -EINVAL;
299 	}
300 
301 	return rte_dev_remove(dev);
302 }
303 
304 /* remove device at local process. */
305 int
306 local_dev_remove(struct rte_device *dev)
307 {
308 	int ret;
309 
310 	if (dev->bus->unplug == NULL) {
311 		RTE_LOG(ERR, EAL, "Function unplug not supported by bus (%s)\n",
312 			dev->bus->name);
313 		return -ENOTSUP;
314 	}
315 
316 	ret = dev->bus->unplug(dev);
317 	if (ret) {
318 		RTE_LOG(ERR, EAL, "Driver cannot detach the device (%s)\n",
319 			dev->name);
320 		return (ret < 0) ? ret : -ENOENT;
321 	}
322 
323 	return 0;
324 }
325 
326 int
327 rte_dev_remove(struct rte_device *dev)
328 {
329 	struct eal_dev_mp_req req;
330 	char *devargs;
331 	int ret;
332 
333 	if (!rte_dev_is_probed(dev)) {
334 		RTE_LOG(ERR, EAL, "Device is not probed\n");
335 		return -ENOENT;
336 	}
337 
338 	ret = build_devargs(dev->bus->name, dev->name, "", &devargs);
339 	if (ret != 0)
340 		return ret;
341 
342 	memset(&req, 0, sizeof(req));
343 	req.t = EAL_DEV_REQ_TYPE_DETACH;
344 	strlcpy(req.devargs, devargs, EAL_DEV_MP_DEV_ARGS_MAX_LEN);
345 	free(devargs);
346 
347 	if (rte_eal_process_type() != RTE_PROC_PRIMARY) {
348 		/**
349 		 * If in secondary process, just send IPC request to
350 		 * primary process.
351 		 */
352 		ret = eal_dev_hotplug_request_to_primary(&req);
353 		if (ret != 0) {
354 			RTE_LOG(ERR, EAL,
355 				"Failed to send hotplug request to primary\n");
356 			return -ENOMSG;
357 		}
358 		if (req.result != 0)
359 			RTE_LOG(ERR, EAL,
360 				"Failed to hotplug remove device\n");
361 		return req.result;
362 	}
363 
364 	/* detach a device from primary start from here: */
365 
366 	/* primary send detach sync request to secondary */
367 	ret = eal_dev_hotplug_request_to_secondary(&req);
368 
369 	/**
370 	 * if communication error, we need to rollback, because it is possible
371 	 * part of the secondary processes still detached it successfully.
372 	 */
373 	if (ret != 0) {
374 		RTE_LOG(ERR, EAL,
375 			"Failed to send device detach request to secondary\n");
376 		ret = -ENOMSG;
377 		goto rollback;
378 	}
379 
380 	/**
381 	 * if any secondary failed to detach, we need to consider if rollback
382 	 * is necessary.
383 	 */
384 	if (req.result != 0) {
385 		RTE_LOG(ERR, EAL,
386 			"Failed to detach device on secondary process\n");
387 		ret = req.result;
388 		/**
389 		 * if -ENOENT, we don't need to rollback, since devices is
390 		 * already detached on secondary process.
391 		 */
392 		if (ret != -ENOENT)
393 			goto rollback;
394 	}
395 
396 	/* primary detach the device itself. */
397 	ret = local_dev_remove(dev);
398 
399 	/* if primary failed, still need to consider if rollback is necessary */
400 	if (ret != 0) {
401 		RTE_LOG(ERR, EAL,
402 			"Failed to detach device on primary process\n");
403 		/* if -ENOENT, we don't need to rollback */
404 		if (ret == -ENOENT)
405 			return ret;
406 		goto rollback;
407 	}
408 
409 	return 0;
410 
411 rollback:
412 	req.t = EAL_DEV_REQ_TYPE_DETACH_ROLLBACK;
413 
414 	/* primary send rollback request to secondary. */
415 	if (eal_dev_hotplug_request_to_secondary(&req) != 0)
416 		RTE_LOG(WARNING, EAL,
417 			"Failed to rollback device detach on secondary."
418 			"Devices in secondary may not sync with primary\n");
419 
420 	return ret;
421 }
422 
423 int
424 rte_dev_event_callback_register(const char *device_name,
425 				rte_dev_event_cb_fn cb_fn,
426 				void *cb_arg)
427 {
428 	struct dev_event_callback *event_cb;
429 	int ret;
430 
431 	if (!cb_fn)
432 		return -EINVAL;
433 
434 	rte_spinlock_lock(&dev_event_lock);
435 
436 	if (TAILQ_EMPTY(&dev_event_cbs))
437 		TAILQ_INIT(&dev_event_cbs);
438 
439 	TAILQ_FOREACH(event_cb, &dev_event_cbs, next) {
440 		if (event_cb->cb_fn == cb_fn && event_cb->cb_arg == cb_arg) {
441 			if (device_name == NULL && event_cb->dev_name == NULL)
442 				break;
443 			if (device_name == NULL || event_cb->dev_name == NULL)
444 				continue;
445 			if (!strcmp(event_cb->dev_name, device_name))
446 				break;
447 		}
448 	}
449 
450 	/* create a new callback. */
451 	if (event_cb == NULL) {
452 		event_cb = malloc(sizeof(struct dev_event_callback));
453 		if (event_cb != NULL) {
454 			event_cb->cb_fn = cb_fn;
455 			event_cb->cb_arg = cb_arg;
456 			event_cb->active = 0;
457 			if (!device_name) {
458 				event_cb->dev_name = NULL;
459 			} else {
460 				event_cb->dev_name = strdup(device_name);
461 				if (event_cb->dev_name == NULL) {
462 					ret = -ENOMEM;
463 					goto error;
464 				}
465 			}
466 			TAILQ_INSERT_TAIL(&dev_event_cbs, event_cb, next);
467 		} else {
468 			RTE_LOG(ERR, EAL,
469 				"Failed to allocate memory for device "
470 				"event callback.");
471 			ret = -ENOMEM;
472 			goto error;
473 		}
474 	} else {
475 		RTE_LOG(ERR, EAL,
476 			"The callback is already exist, no need "
477 			"to register again.\n");
478 		event_cb = NULL;
479 		ret = -EEXIST;
480 		goto error;
481 	}
482 
483 	rte_spinlock_unlock(&dev_event_lock);
484 	return 0;
485 error:
486 	free(event_cb);
487 	rte_spinlock_unlock(&dev_event_lock);
488 	return ret;
489 }
490 
491 int
492 rte_dev_event_callback_unregister(const char *device_name,
493 				  rte_dev_event_cb_fn cb_fn,
494 				  void *cb_arg)
495 {
496 	int ret = 0;
497 	struct dev_event_callback *event_cb, *next;
498 
499 	if (!cb_fn)
500 		return -EINVAL;
501 
502 	rte_spinlock_lock(&dev_event_lock);
503 	/*walk through the callbacks and remove all that match. */
504 	for (event_cb = TAILQ_FIRST(&dev_event_cbs); event_cb != NULL;
505 	     event_cb = next) {
506 
507 		next = TAILQ_NEXT(event_cb, next);
508 
509 		if (device_name != NULL && event_cb->dev_name != NULL) {
510 			if (!strcmp(event_cb->dev_name, device_name)) {
511 				if (event_cb->cb_fn != cb_fn ||
512 				    (cb_arg != (void *)-1 &&
513 				    event_cb->cb_arg != cb_arg))
514 					continue;
515 			}
516 		} else if (device_name != NULL) {
517 			continue;
518 		}
519 
520 		/*
521 		 * if this callback is not executing right now,
522 		 * then remove it.
523 		 */
524 		if (event_cb->active == 0) {
525 			TAILQ_REMOVE(&dev_event_cbs, event_cb, next);
526 			free(event_cb->dev_name);
527 			free(event_cb);
528 			ret++;
529 		} else {
530 			ret = -EAGAIN;
531 			break;
532 		}
533 	}
534 
535 	/* this callback is not be registered */
536 	if (ret == 0)
537 		ret = -ENOENT;
538 
539 	rte_spinlock_unlock(&dev_event_lock);
540 	return ret;
541 }
542 
543 void
544 rte_dev_event_callback_process(const char *device_name,
545 			       enum rte_dev_event_type event)
546 {
547 	struct dev_event_callback *cb_lst;
548 
549 	if (device_name == NULL)
550 		return;
551 
552 	rte_spinlock_lock(&dev_event_lock);
553 
554 	TAILQ_FOREACH(cb_lst, &dev_event_cbs, next) {
555 		if (cb_lst->dev_name) {
556 			if (strcmp(cb_lst->dev_name, device_name))
557 				continue;
558 		}
559 		cb_lst->active = 1;
560 		rte_spinlock_unlock(&dev_event_lock);
561 		cb_lst->cb_fn(device_name, event,
562 				cb_lst->cb_arg);
563 		rte_spinlock_lock(&dev_event_lock);
564 		cb_lst->active = 0;
565 	}
566 	rte_spinlock_unlock(&dev_event_lock);
567 }
568 
569 int
570 rte_dev_iterator_init(struct rte_dev_iterator *it,
571 		      const char *dev_str)
572 {
573 	struct rte_devargs devargs = { .bus = NULL };
574 	struct rte_class *cls = NULL;
575 	struct rte_bus *bus = NULL;
576 
577 	/* Having both bus_str and cls_str NULL is illegal,
578 	 * marking this iterator as invalid unless
579 	 * everything goes well.
580 	 */
581 	it->bus_str = NULL;
582 	it->cls_str = NULL;
583 
584 	/* Setting data field implies no malloc in parsing. */
585 	devargs.data = (void *)(intptr_t)dev_str;
586 	if (rte_devargs_layers_parse(&devargs, dev_str))
587 		goto get_out;
588 
589 	bus = devargs.bus;
590 	cls = devargs.cls;
591 	/* The string should have at least
592 	 * one layer specified.
593 	 */
594 	if (bus == NULL && cls == NULL) {
595 		RTE_LOG(ERR, EAL,
596 			"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(ERR, 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(ERR, 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