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