32e872da5209019081f0236be8225af66bc1c492
[dpdk.git] / drivers / bus / dpaa / dpaa_bus.c
1 /* SPDX-License-Identifier: BSD-3-Clause
2  *
3  *   Copyright 2017-2020 NXP
4  *
5  */
6 /* System headers */
7 #include <stdio.h>
8 #include <inttypes.h>
9 #include <unistd.h>
10 #include <limits.h>
11 #include <sched.h>
12 #include <signal.h>
13 #include <pthread.h>
14 #include <sys/types.h>
15 #include <sys/syscall.h>
16 #include <sys/eventfd.h>
17
18 #include <rte_byteorder.h>
19 #include <rte_common.h>
20 #include <rte_interrupts.h>
21 #include <rte_log.h>
22 #include <rte_debug.h>
23 #include <rte_atomic.h>
24 #include <rte_branch_prediction.h>
25 #include <rte_memory.h>
26 #include <rte_tailq.h>
27 #include <rte_eal.h>
28 #include <rte_alarm.h>
29 #include <rte_ether.h>
30 #include <rte_ethdev_driver.h>
31 #include <rte_malloc.h>
32 #include <rte_ring.h>
33 #include <rte_bus.h>
34 #include <rte_mbuf_pool_ops.h>
35
36 #include <dpaa_of.h>
37 #include <rte_dpaa_bus.h>
38 #include <rte_dpaa_logs.h>
39 #include <dpaax_iova_table.h>
40
41 #include <fsl_usd.h>
42 #include <fsl_qman.h>
43 #include <fsl_bman.h>
44 #include <netcfg.h>
45
46 static struct rte_dpaa_bus rte_dpaa_bus;
47 struct netcfg_info *dpaa_netcfg;
48
49 /* define a variable to hold the portal_key, once created.*/
50 static pthread_key_t dpaa_portal_key;
51
52 unsigned int dpaa_svr_family;
53
54 #define FSL_DPAA_BUS_NAME       dpaa_bus
55
56 RTE_DEFINE_PER_LCORE(struct dpaa_portal *, dpaa_io);
57
58 struct fm_eth_port_cfg *
59 dpaa_get_eth_port_cfg(int dev_id)
60 {
61         return &dpaa_netcfg->port_cfg[dev_id];
62 }
63
64 static int
65 compare_dpaa_devices(struct rte_dpaa_device *dev1,
66                      struct rte_dpaa_device *dev2)
67 {
68         int comp = 0;
69
70         /* Segragating ETH from SEC devices */
71         if (dev1->device_type > dev2->device_type)
72                 comp = 1;
73         else if (dev1->device_type < dev2->device_type)
74                 comp = -1;
75         else
76                 comp = 0;
77
78         if ((comp != 0) || (dev1->device_type != FSL_DPAA_ETH))
79                 return comp;
80
81         if (dev1->id.fman_id > dev2->id.fman_id) {
82                 comp = 1;
83         } else if (dev1->id.fman_id < dev2->id.fman_id) {
84                 comp = -1;
85         } else {
86                 /* FMAN ids match, check for mac_id */
87                 if (dev1->id.mac_id > dev2->id.mac_id)
88                         comp = 1;
89                 else if (dev1->id.mac_id < dev2->id.mac_id)
90                         comp = -1;
91                 else
92                         comp = 0;
93         }
94
95         return comp;
96 }
97
98 static inline void
99 dpaa_add_to_device_list(struct rte_dpaa_device *newdev)
100 {
101         int comp, inserted = 0;
102         struct rte_dpaa_device *dev = NULL;
103         struct rte_dpaa_device *tdev = NULL;
104
105         TAILQ_FOREACH_SAFE(dev, &rte_dpaa_bus.device_list, next, tdev) {
106                 comp = compare_dpaa_devices(newdev, dev);
107                 if (comp < 0) {
108                         TAILQ_INSERT_BEFORE(dev, newdev, next);
109                         inserted = 1;
110                         break;
111                 }
112         }
113
114         if (!inserted)
115                 TAILQ_INSERT_TAIL(&rte_dpaa_bus.device_list, newdev, next);
116 }
117
118 /*
119  * Reads the SEC device from DTS
120  * Returns -1 if SEC devices not available, 0 otherwise
121  */
122 static inline int
123 dpaa_sec_available(void)
124 {
125         const struct device_node *caam_node;
126
127         for_each_compatible_node(caam_node, NULL, "fsl,sec-v4.0") {
128                 return 0;
129         }
130
131         return -1;
132 }
133
134 static void dpaa_clean_device_list(void);
135
136 static struct rte_devargs *
137 dpaa_devargs_lookup(struct rte_dpaa_device *dev)
138 {
139         struct rte_devargs *devargs;
140         char dev_name[32];
141
142         RTE_EAL_DEVARGS_FOREACH("dpaa_bus", devargs) {
143                 devargs->bus->parse(devargs->name, &dev_name);
144                 if (strcmp(dev_name, dev->device.name) == 0) {
145                         DPAA_BUS_INFO("**Devargs matched %s", dev_name);
146                         return devargs;
147                 }
148         }
149         return NULL;
150 }
151
152 static int
153 dpaa_create_device_list(void)
154 {
155         int i;
156         int ret;
157         struct rte_dpaa_device *dev;
158         struct fm_eth_port_cfg *cfg;
159         struct fman_if *fman_intf;
160
161         /* Creating Ethernet Devices */
162         for (i = 0; i < dpaa_netcfg->num_ethports; i++) {
163                 dev = calloc(1, sizeof(struct rte_dpaa_device));
164                 if (!dev) {
165                         DPAA_BUS_LOG(ERR, "Failed to allocate ETH devices");
166                         ret = -ENOMEM;
167                         goto cleanup;
168                 }
169
170                 dev->device.bus = &rte_dpaa_bus.bus;
171
172                 cfg = &dpaa_netcfg->port_cfg[i];
173                 fman_intf = cfg->fman_if;
174
175                 /* Device identifiers */
176                 dev->id.fman_id = fman_intf->fman_idx + 1;
177                 dev->id.mac_id = fman_intf->mac_idx;
178                 dev->device_type = FSL_DPAA_ETH;
179                 dev->id.dev_id = i;
180
181                 /* Create device name */
182                 memset(dev->name, 0, RTE_ETH_NAME_MAX_LEN);
183                 sprintf(dev->name, "fm%d-mac%d", (fman_intf->fman_idx + 1),
184                         fman_intf->mac_idx);
185                 DPAA_BUS_LOG(INFO, "%s netdev added", dev->name);
186                 dev->device.name = dev->name;
187                 dev->device.devargs = dpaa_devargs_lookup(dev);
188
189                 dpaa_add_to_device_list(dev);
190         }
191
192         rte_dpaa_bus.device_count = i;
193
194         /* Unlike case of ETH, RTE_LIBRTE_DPAA_MAX_CRYPTODEV SEC devices are
195          * constantly created only if "sec" property is found in the device
196          * tree. Logically there is no limit for number of devices (QI
197          * interfaces) that can be created.
198          */
199
200         if (dpaa_sec_available()) {
201                 DPAA_BUS_LOG(INFO, "DPAA SEC devices are not available");
202                 return 0;
203         }
204
205         /* Creating SEC Devices */
206         for (i = 0; i < RTE_LIBRTE_DPAA_MAX_CRYPTODEV; i++) {
207                 dev = calloc(1, sizeof(struct rte_dpaa_device));
208                 if (!dev) {
209                         DPAA_BUS_LOG(ERR, "Failed to allocate SEC devices");
210                         ret = -1;
211                         goto cleanup;
212                 }
213
214                 dev->device_type = FSL_DPAA_CRYPTO;
215                 dev->id.dev_id = rte_dpaa_bus.device_count + i;
216
217                 /* Even though RTE_CRYPTODEV_NAME_MAX_LEN is valid length of
218                  * crypto PMD, using RTE_ETH_NAME_MAX_LEN as that is the size
219                  * allocated for dev->name/
220                  */
221                 memset(dev->name, 0, RTE_ETH_NAME_MAX_LEN);
222                 sprintf(dev->name, "dpaa_sec-%d", i+1);
223                 DPAA_BUS_LOG(INFO, "%s cryptodev added", dev->name);
224                 dev->device.name = dev->name;
225                 dev->device.devargs = dpaa_devargs_lookup(dev);
226
227                 dpaa_add_to_device_list(dev);
228         }
229
230         rte_dpaa_bus.device_count += i;
231
232         return 0;
233
234 cleanup:
235         dpaa_clean_device_list();
236         return ret;
237 }
238
239 static void
240 dpaa_clean_device_list(void)
241 {
242         struct rte_dpaa_device *dev = NULL;
243         struct rte_dpaa_device *tdev = NULL;
244
245         TAILQ_FOREACH_SAFE(dev, &rte_dpaa_bus.device_list, next, tdev) {
246                 TAILQ_REMOVE(&rte_dpaa_bus.device_list, dev, next);
247                 free(dev);
248                 dev = NULL;
249         }
250 }
251
252 int rte_dpaa_portal_init(void *arg)
253 {
254         unsigned int cpu, lcore = rte_lcore_id();
255         int ret;
256
257         BUS_INIT_FUNC_TRACE();
258
259         if ((size_t)arg == 1 || lcore == LCORE_ID_ANY)
260                 lcore = rte_get_master_lcore();
261         else
262                 if (lcore >= RTE_MAX_LCORE)
263                         return -1;
264
265         cpu = rte_lcore_to_cpu_id(lcore);
266
267         /* Initialise bman thread portals */
268         ret = bman_thread_init();
269         if (ret) {
270                 DPAA_BUS_LOG(ERR, "bman_thread_init failed on core %u"
271                              " (lcore=%u) with ret: %d", cpu, lcore, ret);
272                 return ret;
273         }
274
275         DPAA_BUS_LOG(DEBUG, "BMAN thread initialized - CPU=%d lcore=%d",
276                      cpu, lcore);
277
278         /* Initialise qman thread portals */
279         ret = qman_thread_init();
280         if (ret) {
281                 DPAA_BUS_LOG(ERR, "qman_thread_init failed on core %u"
282                             " (lcore=%u) with ret: %d", cpu, lcore, ret);
283                 bman_thread_finish();
284                 return ret;
285         }
286
287         DPAA_BUS_LOG(DEBUG, "QMAN thread initialized - CPU=%d lcore=%d",
288                      cpu, lcore);
289
290         DPAA_PER_LCORE_PORTAL = rte_malloc(NULL, sizeof(struct dpaa_portal),
291                                     RTE_CACHE_LINE_SIZE);
292         if (!DPAA_PER_LCORE_PORTAL) {
293                 DPAA_BUS_LOG(ERR, "Unable to allocate memory");
294                 bman_thread_finish();
295                 qman_thread_finish();
296                 return -ENOMEM;
297         }
298
299         DPAA_PER_LCORE_PORTAL->qman_idx = qman_get_portal_index();
300         DPAA_PER_LCORE_PORTAL->bman_idx = bman_get_portal_index();
301         DPAA_PER_LCORE_PORTAL->tid = syscall(SYS_gettid);
302
303         ret = pthread_setspecific(dpaa_portal_key,
304                                   (void *)DPAA_PER_LCORE_PORTAL);
305         if (ret) {
306                 DPAA_BUS_LOG(ERR, "pthread_setspecific failed on core %u"
307                              " (lcore=%u) with ret: %d", cpu, lcore, ret);
308                 dpaa_portal_finish(NULL);
309
310                 return ret;
311         }
312
313         DPAA_BUS_LOG(DEBUG, "QMAN thread initialized");
314
315         return 0;
316 }
317
318 int
319 rte_dpaa_portal_fq_init(void *arg, struct qman_fq *fq)
320 {
321         /* Affine above created portal with channel*/
322         u32 sdqcr;
323         int ret;
324
325         if (unlikely(!DPAA_PER_LCORE_PORTAL)) {
326                 ret = rte_dpaa_portal_init(arg);
327                 if (ret < 0) {
328                         DPAA_BUS_LOG(ERR, "portal initialization failure");
329                         return ret;
330                 }
331         }
332
333         /* Initialise qman specific portals */
334         ret = fsl_qman_fq_portal_init(fq->qp);
335         if (ret) {
336                 DPAA_BUS_LOG(ERR, "Unable to init fq portal");
337                 return -1;
338         }
339
340         sdqcr = QM_SDQCR_CHANNELS_POOL_CONV(fq->ch_id);
341         qman_static_dequeue_add(sdqcr, fq->qp);
342
343         return 0;
344 }
345
346 int rte_dpaa_portal_fq_close(struct qman_fq *fq)
347 {
348         return fsl_qman_fq_portal_destroy(fq->qp);
349 }
350
351 void
352 dpaa_portal_finish(void *arg)
353 {
354         struct dpaa_portal *dpaa_io_portal = (struct dpaa_portal *)arg;
355
356         if (!dpaa_io_portal) {
357                 DPAA_BUS_LOG(DEBUG, "Portal already cleaned");
358                 return;
359         }
360
361         bman_thread_finish();
362         qman_thread_finish();
363
364         pthread_setspecific(dpaa_portal_key, NULL);
365
366         rte_free(dpaa_io_portal);
367         dpaa_io_portal = NULL;
368         DPAA_PER_LCORE_PORTAL = NULL;
369 }
370
371 static int
372 rte_dpaa_bus_parse(const char *name, void *out_name)
373 {
374         int i, j;
375         int max_fman = 2, max_macs = 16;
376         char *dup_name;
377         char *sep = NULL;
378
379         /* There are two ways of passing device name, with and without
380          * separator. "dpaa_bus:fm1-mac3" with separator, and "fm1-mac3"
381          * without separator. Both need to be handled.
382          * It is also possible that "name=fm1-mac3" is passed along.
383          */
384         DPAA_BUS_DEBUG("Parse device name (%s)", name);
385
386         /* Check for dpaa_bus:fm1-mac3 style */
387         dup_name = strdup(name);
388         sep = strchr(dup_name, ':');
389         if (!sep)
390                 /* If not, check for name=fm1-mac3 style */
391                 sep = strchr(dup_name, '=');
392
393         if (sep)
394                 /* jump over the seprator */
395                 sep = (char *) (sep + 1);
396         else
397                 sep = dup_name;
398
399         for (i = 0; i < max_fman; i++) {
400                 for (j = 0; j < max_macs; j++) {
401                         char fm_name[16];
402                         snprintf(fm_name, 16, "fm%d-mac%d", i, j);
403                         if (strcmp(fm_name, sep) == 0) {
404                                 if (out_name)
405                                         strcpy(out_name, sep);
406                                 free(dup_name);
407                                 return 0;
408                         }
409                 }
410         }
411
412         for (i = 0; i < RTE_LIBRTE_DPAA_MAX_CRYPTODEV; i++) {
413                 char sec_name[16];
414
415                 snprintf(sec_name, 16, "dpaa_sec-%d", i+1);
416                 if (strcmp(sec_name, sep) == 0) {
417                         if (out_name)
418                                 strcpy(out_name, sep);
419                         free(dup_name);
420                         return 0;
421                 }
422         }
423
424         free(dup_name);
425         return -EINVAL;
426 }
427
428 #define DPAA_DEV_PATH1 "/sys/devices/platform/soc/soc:fsl,dpaa"
429 #define DPAA_DEV_PATH2 "/sys/devices/platform/fsl,dpaa"
430
431 static int
432 rte_dpaa_bus_scan(void)
433 {
434         int ret;
435
436         BUS_INIT_FUNC_TRACE();
437
438         if ((access(DPAA_DEV_PATH1, F_OK) != 0) &&
439             (access(DPAA_DEV_PATH2, F_OK) != 0)) {
440                 RTE_LOG(DEBUG, EAL, "DPAA Bus not present. Skipping.\n");
441                 return 0;
442         }
443
444         if (rte_dpaa_bus.detected)
445                 return 0;
446
447         rte_dpaa_bus.detected = 1;
448
449         /* create the key, supplying a function that'll be invoked
450          * when a portal affined thread will be deleted.
451          */
452         ret = pthread_key_create(&dpaa_portal_key, dpaa_portal_finish);
453         if (ret) {
454                 DPAA_BUS_LOG(DEBUG, "Unable to create pthread key. (%d)", ret);
455                 dpaa_clean_device_list();
456                 return ret;
457         }
458
459         return 0;
460 }
461
462 /* register a dpaa bus based dpaa driver */
463 void
464 rte_dpaa_driver_register(struct rte_dpaa_driver *driver)
465 {
466         RTE_VERIFY(driver);
467
468         BUS_INIT_FUNC_TRACE();
469
470         TAILQ_INSERT_TAIL(&rte_dpaa_bus.driver_list, driver, next);
471         /* Update Bus references */
472         driver->dpaa_bus = &rte_dpaa_bus;
473 }
474
475 /* un-register a dpaa bus based dpaa driver */
476 void
477 rte_dpaa_driver_unregister(struct rte_dpaa_driver *driver)
478 {
479         struct rte_dpaa_bus *dpaa_bus;
480
481         BUS_INIT_FUNC_TRACE();
482
483         dpaa_bus = driver->dpaa_bus;
484
485         TAILQ_REMOVE(&dpaa_bus->driver_list, driver, next);
486         /* Update Bus references */
487         driver->dpaa_bus = NULL;
488 }
489
490 static int
491 rte_dpaa_device_match(struct rte_dpaa_driver *drv,
492                       struct rte_dpaa_device *dev)
493 {
494         if (!drv || !dev) {
495                 DPAA_BUS_DEBUG("Invalid drv or dev received.");
496                 return -1;
497         }
498
499         if (drv->drv_type == dev->device_type)
500                 return 0;
501
502         return -1;
503 }
504
505 static int
506 rte_dpaa_bus_dev_build(void)
507 {
508         int ret;
509
510         /* Load the device-tree driver */
511         ret = of_init();
512         if (ret) {
513                 DPAA_BUS_LOG(ERR, "of_init failed with ret: %d", ret);
514                 return -1;
515         }
516
517         /* Get the interface configurations from device-tree */
518         dpaa_netcfg = netcfg_acquire();
519         if (!dpaa_netcfg) {
520                 DPAA_BUS_LOG(ERR, "netcfg_acquire failed");
521                 return -EINVAL;
522         }
523
524         RTE_LOG(NOTICE, EAL, "DPAA Bus Detected\n");
525
526         if (!dpaa_netcfg->num_ethports) {
527                 DPAA_BUS_LOG(INFO, "no network interfaces available");
528                 /* This is not an error */
529                 return 0;
530         }
531
532 #ifdef RTE_LIBRTE_DPAA_DEBUG_DRIVER
533         dump_netcfg(dpaa_netcfg);
534 #endif
535
536         DPAA_BUS_LOG(DEBUG, "Number of ethernet devices = %d",
537                      dpaa_netcfg->num_ethports);
538         ret = dpaa_create_device_list();
539         if (ret) {
540                 DPAA_BUS_LOG(ERR, "Unable to create device list. (%d)", ret);
541                 return ret;
542         }
543         return 0;
544 }
545
546 static int rte_dpaa_setup_intr(struct rte_intr_handle *intr_handle)
547 {
548         int fd;
549
550         fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
551         if (fd < 0) {
552                 DPAA_BUS_ERR("Cannot set up eventfd, error %i (%s)",
553                              errno, strerror(errno));
554                 return errno;
555         }
556
557         intr_handle->fd = fd;
558         intr_handle->type = RTE_INTR_HANDLE_EXT;
559
560         return 0;
561 }
562
563 static int
564 rte_dpaa_bus_probe(void)
565 {
566         int ret = -1;
567         struct rte_dpaa_device *dev;
568         struct rte_dpaa_driver *drv;
569         FILE *svr_file = NULL;
570         unsigned int svr_ver;
571         int probe_all = rte_dpaa_bus.bus.conf.scan_mode != RTE_BUS_SCAN_WHITELIST;
572         static int process_once;
573
574         /* If DPAA bus is not present nothing needs to be done */
575         if (!rte_dpaa_bus.detected)
576                 return 0;
577
578         /* Device list creation is only done once */
579         if (!process_once) {
580                 rte_dpaa_bus_dev_build();
581                 if (rte_eal_process_type() == RTE_PROC_PRIMARY) {
582                         /* One time load of Qman/Bman drivers */
583                         ret = qman_global_init();
584                         if (ret) {
585                                 DPAA_BUS_ERR("QMAN initialization failed: %d",
586                                              ret);
587                                 return ret;
588                         }
589                         ret = bman_global_init();
590                         if (ret) {
591                                 DPAA_BUS_ERR("BMAN initialization failed: %d",
592                                              ret);
593                                 return ret;
594                         }
595                 }
596         }
597         process_once = 1;
598
599         /* If no device present on DPAA bus nothing needs to be done */
600         if (TAILQ_EMPTY(&rte_dpaa_bus.device_list))
601                 return 0;
602
603         svr_file = fopen(DPAA_SOC_ID_FILE, "r");
604         if (svr_file) {
605                 if (fscanf(svr_file, "svr:%x", &svr_ver) > 0)
606                         dpaa_svr_family = svr_ver & SVR_MASK;
607                 fclose(svr_file);
608         }
609
610         TAILQ_FOREACH(dev, &rte_dpaa_bus.device_list, next) {
611                 if (dev->device_type == FSL_DPAA_ETH) {
612                         ret = rte_dpaa_setup_intr(&dev->intr_handle);
613                         if (ret)
614                                 DPAA_BUS_ERR("Error setting up interrupt.\n");
615                 }
616         }
617
618         /* And initialize the PA->VA translation table */
619         dpaax_iova_table_populate();
620
621         /* For each registered driver, and device, call the driver->probe */
622         TAILQ_FOREACH(dev, &rte_dpaa_bus.device_list, next) {
623                 TAILQ_FOREACH(drv, &rte_dpaa_bus.driver_list, next) {
624                         ret = rte_dpaa_device_match(drv, dev);
625                         if (ret)
626                                 continue;
627
628                         if (rte_dev_is_probed(&dev->device))
629                                 continue;
630
631                         if (!drv->probe ||
632                             (dev->device.devargs &&
633                             dev->device.devargs->policy == RTE_DEV_BLACKLISTED))
634                                 continue;
635
636                         if (probe_all ||
637                             (dev->device.devargs &&
638                             dev->device.devargs->policy ==
639                             RTE_DEV_WHITELISTED)) {
640                                 ret = drv->probe(drv, dev);
641                                 if (ret) {
642                                         DPAA_BUS_ERR("unable to probe:%s",
643                                                      dev->name);
644                                 } else {
645                                         dev->driver = drv;
646                                         dev->device.driver = &drv->driver;
647                                 }
648                         }
649                         break;
650                 }
651         }
652
653         /* Register DPAA mempool ops only if any DPAA device has
654          * been detected.
655          */
656         rte_mbuf_set_platform_mempool_ops(DPAA_MEMPOOL_OPS_NAME);
657
658         return 0;
659 }
660
661 static struct rte_device *
662 rte_dpaa_find_device(const struct rte_device *start, rte_dev_cmp_t cmp,
663                      const void *data)
664 {
665         struct rte_dpaa_device *dev;
666         const struct rte_dpaa_device *dstart;
667
668         /* find_device is called with 'data' as an opaque object - just call
669          * cmp with this and each device object on bus.
670          */
671
672         if (start != NULL) {
673                 dstart = RTE_DEV_TO_DPAA_CONST(start);
674                 dev = TAILQ_NEXT(dstart, next);
675         } else {
676                 dev = TAILQ_FIRST(&rte_dpaa_bus.device_list);
677         }
678
679         while (dev != NULL) {
680                 if (cmp(&dev->device, data) == 0) {
681                         DPAA_BUS_DEBUG("Found dev=(%s)\n", dev->device.name);
682                         return &dev->device;
683                 }
684                 dev = TAILQ_NEXT(dev, next);
685         }
686
687         DPAA_BUS_DEBUG("Unable to find any device\n");
688         return NULL;
689 }
690
691 /*
692  * Get iommu class of DPAA2 devices on the bus.
693  */
694 static enum rte_iova_mode
695 rte_dpaa_get_iommu_class(void)
696 {
697         if ((access(DPAA_DEV_PATH1, F_OK) != 0) &&
698             (access(DPAA_DEV_PATH2, F_OK) != 0)) {
699                 return RTE_IOVA_DC;
700         }
701         return RTE_IOVA_PA;
702 }
703
704 static int
705 dpaa_bus_plug(struct rte_device *dev __rte_unused)
706 {
707         /* No operation is performed while plugging the device */
708         return 0;
709 }
710
711 static int
712 dpaa_bus_unplug(struct rte_device *dev __rte_unused)
713 {
714         /* No operation is performed while unplugging the device */
715         return 0;
716 }
717
718 static void *
719 dpaa_bus_dev_iterate(const void *start, const char *str,
720                      const struct rte_dev_iterator *it __rte_unused)
721 {
722         const struct rte_dpaa_device *dstart;
723         struct rte_dpaa_device *dev;
724         char *dup, *dev_name = NULL;
725
726         if (str == NULL) {
727                 DPAA_BUS_DEBUG("No device string");
728                 return NULL;
729         }
730
731         /* Expectation is that device would be name=device_name */
732         if (strncmp(str, "name=", 5) != 0) {
733                 DPAA_BUS_DEBUG("Invalid device string (%s)\n", str);
734                 return NULL;
735         }
736
737         /* Now that name=device_name format is available, split */
738         dup = strdup(str);
739         dev_name = dup + strlen("name=");
740
741         if (start != NULL) {
742                 dstart = RTE_DEV_TO_DPAA_CONST(start);
743                 dev = TAILQ_NEXT(dstart, next);
744         } else {
745                 dev = TAILQ_FIRST(&rte_dpaa_bus.device_list);
746         }
747
748         while (dev != NULL) {
749                 if (strcmp(dev->device.name, dev_name) == 0) {
750                         free(dup);
751                         return &dev->device;
752                 }
753                 dev = TAILQ_NEXT(dev, next);
754         }
755
756         free(dup);
757         return NULL;
758 }
759
760 static struct rte_dpaa_bus rte_dpaa_bus = {
761         .bus = {
762                 .scan = rte_dpaa_bus_scan,
763                 .probe = rte_dpaa_bus_probe,
764                 .parse = rte_dpaa_bus_parse,
765                 .find_device = rte_dpaa_find_device,
766                 .get_iommu_class = rte_dpaa_get_iommu_class,
767                 .plug = dpaa_bus_plug,
768                 .unplug = dpaa_bus_unplug,
769                 .dev_iterate = dpaa_bus_dev_iterate,
770         },
771         .device_list = TAILQ_HEAD_INITIALIZER(rte_dpaa_bus.device_list),
772         .driver_list = TAILQ_HEAD_INITIALIZER(rte_dpaa_bus.driver_list),
773         .device_count = 0,
774 };
775
776 RTE_REGISTER_BUS(FSL_DPAA_BUS_NAME, rte_dpaa_bus.bus);
777 RTE_LOG_REGISTER(dpaa_logtype_bus, bus.dpaa, NOTICE);