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