1 /* SPDX-License-Identifier: BSD-3-Clause 2 * Copyright(c) 2010-2014 Intel Corporation 3 */ 4 5 #include <string.h> 6 #include <dirent.h> 7 8 #include <rte_log.h> 9 #include <rte_bus.h> 10 #include <rte_pci.h> 11 #include <rte_bus_pci.h> 12 #include <rte_eal_memconfig.h> 13 #include <rte_malloc.h> 14 #include <rte_devargs.h> 15 #include <rte_memcpy.h> 16 #include <rte_vfio.h> 17 18 #include "eal_private.h" 19 #include "eal_filesystem.h" 20 21 #include "private.h" 22 #include "pci_init.h" 23 24 /** 25 * @file 26 * PCI probing under linux 27 * 28 * This code is used to simulate a PCI probe by parsing information in sysfs. 29 * When a registered device matches a driver, it is then initialized with 30 * IGB_UIO driver (or doesn't initialize, if the device wasn't bound to it). 31 */ 32 33 extern struct rte_pci_bus rte_pci_bus; 34 35 static int 36 pci_get_kernel_driver_by_path(const char *filename, char *dri_name) 37 { 38 int count; 39 char path[PATH_MAX]; 40 char *name; 41 42 if (!filename || !dri_name) 43 return -1; 44 45 count = readlink(filename, path, PATH_MAX); 46 if (count >= PATH_MAX) 47 return -1; 48 49 /* For device does not have a driver */ 50 if (count < 0) 51 return 1; 52 53 path[count] = '\0'; 54 55 name = strrchr(path, '/'); 56 if (name) { 57 strncpy(dri_name, name + 1, strlen(name + 1) + 1); 58 return 0; 59 } 60 61 return -1; 62 } 63 64 /* Map pci device */ 65 int 66 rte_pci_map_device(struct rte_pci_device *dev) 67 { 68 int ret = -1; 69 70 /* try mapping the NIC resources using VFIO if it exists */ 71 switch (dev->kdrv) { 72 case RTE_KDRV_VFIO: 73 #ifdef VFIO_PRESENT 74 if (pci_vfio_is_enabled()) 75 ret = pci_vfio_map_resource(dev); 76 #endif 77 break; 78 case RTE_KDRV_IGB_UIO: 79 case RTE_KDRV_UIO_GENERIC: 80 if (rte_eal_using_phys_addrs()) { 81 /* map resources for devices that use uio */ 82 ret = pci_uio_map_resource(dev); 83 } 84 break; 85 default: 86 RTE_LOG(DEBUG, EAL, 87 " Not managed by a supported kernel driver, skipped\n"); 88 ret = 1; 89 break; 90 } 91 92 return ret; 93 } 94 95 /* Unmap pci device */ 96 void 97 rte_pci_unmap_device(struct rte_pci_device *dev) 98 { 99 /* try unmapping the NIC resources using VFIO if it exists */ 100 switch (dev->kdrv) { 101 case RTE_KDRV_VFIO: 102 #ifdef VFIO_PRESENT 103 if (pci_vfio_is_enabled()) 104 pci_vfio_unmap_resource(dev); 105 #endif 106 break; 107 case RTE_KDRV_IGB_UIO: 108 case RTE_KDRV_UIO_GENERIC: 109 /* unmap resources for devices that use uio */ 110 pci_uio_unmap_resource(dev); 111 break; 112 default: 113 RTE_LOG(DEBUG, EAL, 114 " Not managed by a supported kernel driver, skipped\n"); 115 break; 116 } 117 } 118 119 void * 120 pci_find_max_end_va(void) 121 { 122 const struct rte_memseg *seg = rte_eal_get_physmem_layout(); 123 const struct rte_memseg *last = seg; 124 unsigned i = 0; 125 126 for (i = 0; i < RTE_MAX_MEMSEG; i++, seg++) { 127 if (seg->addr == NULL) 128 break; 129 130 if (seg->addr > last->addr) 131 last = seg; 132 133 } 134 return RTE_PTR_ADD(last->addr, last->len); 135 } 136 137 /* parse one line of the "resource" sysfs file (note that the 'line' 138 * string is modified) 139 */ 140 int 141 pci_parse_one_sysfs_resource(char *line, size_t len, uint64_t *phys_addr, 142 uint64_t *end_addr, uint64_t *flags) 143 { 144 union pci_resource_info { 145 struct { 146 char *phys_addr; 147 char *end_addr; 148 char *flags; 149 }; 150 char *ptrs[PCI_RESOURCE_FMT_NVAL]; 151 } res_info; 152 153 if (rte_strsplit(line, len, res_info.ptrs, 3, ' ') != 3) { 154 RTE_LOG(ERR, EAL, 155 "%s(): bad resource format\n", __func__); 156 return -1; 157 } 158 errno = 0; 159 *phys_addr = strtoull(res_info.phys_addr, NULL, 16); 160 *end_addr = strtoull(res_info.end_addr, NULL, 16); 161 *flags = strtoull(res_info.flags, NULL, 16); 162 if (errno != 0) { 163 RTE_LOG(ERR, EAL, 164 "%s(): bad resource format\n", __func__); 165 return -1; 166 } 167 168 return 0; 169 } 170 171 /* parse the "resource" sysfs file */ 172 static int 173 pci_parse_sysfs_resource(const char *filename, struct rte_pci_device *dev) 174 { 175 FILE *f; 176 char buf[BUFSIZ]; 177 int i; 178 uint64_t phys_addr, end_addr, flags; 179 180 f = fopen(filename, "r"); 181 if (f == NULL) { 182 RTE_LOG(ERR, EAL, "Cannot open sysfs resource\n"); 183 return -1; 184 } 185 186 for (i = 0; i<PCI_MAX_RESOURCE; i++) { 187 188 if (fgets(buf, sizeof(buf), f) == NULL) { 189 RTE_LOG(ERR, EAL, 190 "%s(): cannot read resource\n", __func__); 191 goto error; 192 } 193 if (pci_parse_one_sysfs_resource(buf, sizeof(buf), &phys_addr, 194 &end_addr, &flags) < 0) 195 goto error; 196 197 if (flags & IORESOURCE_MEM) { 198 dev->mem_resource[i].phys_addr = phys_addr; 199 dev->mem_resource[i].len = end_addr - phys_addr + 1; 200 /* not mapped for now */ 201 dev->mem_resource[i].addr = NULL; 202 } 203 } 204 fclose(f); 205 return 0; 206 207 error: 208 fclose(f); 209 return -1; 210 } 211 212 /* Scan one pci sysfs entry, and fill the devices list from it. */ 213 static int 214 pci_scan_one(const char *dirname, const struct rte_pci_addr *addr) 215 { 216 char filename[PATH_MAX]; 217 unsigned long tmp; 218 struct rte_pci_device *dev; 219 char driver[PATH_MAX]; 220 int ret; 221 222 dev = malloc(sizeof(*dev)); 223 if (dev == NULL) 224 return -1; 225 226 memset(dev, 0, sizeof(*dev)); 227 dev->addr = *addr; 228 229 /* get vendor id */ 230 snprintf(filename, sizeof(filename), "%s/vendor", dirname); 231 if (eal_parse_sysfs_value(filename, &tmp) < 0) { 232 free(dev); 233 return -1; 234 } 235 dev->id.vendor_id = (uint16_t)tmp; 236 237 /* get device id */ 238 snprintf(filename, sizeof(filename), "%s/device", dirname); 239 if (eal_parse_sysfs_value(filename, &tmp) < 0) { 240 free(dev); 241 return -1; 242 } 243 dev->id.device_id = (uint16_t)tmp; 244 245 /* get subsystem_vendor id */ 246 snprintf(filename, sizeof(filename), "%s/subsystem_vendor", 247 dirname); 248 if (eal_parse_sysfs_value(filename, &tmp) < 0) { 249 free(dev); 250 return -1; 251 } 252 dev->id.subsystem_vendor_id = (uint16_t)tmp; 253 254 /* get subsystem_device id */ 255 snprintf(filename, sizeof(filename), "%s/subsystem_device", 256 dirname); 257 if (eal_parse_sysfs_value(filename, &tmp) < 0) { 258 free(dev); 259 return -1; 260 } 261 dev->id.subsystem_device_id = (uint16_t)tmp; 262 263 /* get class_id */ 264 snprintf(filename, sizeof(filename), "%s/class", 265 dirname); 266 if (eal_parse_sysfs_value(filename, &tmp) < 0) { 267 free(dev); 268 return -1; 269 } 270 /* the least 24 bits are valid: class, subclass, program interface */ 271 dev->id.class_id = (uint32_t)tmp & RTE_CLASS_ANY_ID; 272 273 /* get max_vfs */ 274 dev->max_vfs = 0; 275 snprintf(filename, sizeof(filename), "%s/max_vfs", dirname); 276 if (!access(filename, F_OK) && 277 eal_parse_sysfs_value(filename, &tmp) == 0) 278 dev->max_vfs = (uint16_t)tmp; 279 else { 280 /* for non igb_uio driver, need kernel version >= 3.8 */ 281 snprintf(filename, sizeof(filename), 282 "%s/sriov_numvfs", dirname); 283 if (!access(filename, F_OK) && 284 eal_parse_sysfs_value(filename, &tmp) == 0) 285 dev->max_vfs = (uint16_t)tmp; 286 } 287 288 /* get numa node, default to 0 if not present */ 289 snprintf(filename, sizeof(filename), "%s/numa_node", 290 dirname); 291 292 if (access(filename, F_OK) != -1) { 293 if (eal_parse_sysfs_value(filename, &tmp) == 0) 294 dev->device.numa_node = tmp; 295 else 296 dev->device.numa_node = -1; 297 } else { 298 dev->device.numa_node = 0; 299 } 300 301 pci_name_set(dev); 302 303 /* parse resources */ 304 snprintf(filename, sizeof(filename), "%s/resource", dirname); 305 if (pci_parse_sysfs_resource(filename, dev) < 0) { 306 RTE_LOG(ERR, EAL, "%s(): cannot parse resource\n", __func__); 307 free(dev); 308 return -1; 309 } 310 311 /* parse driver */ 312 snprintf(filename, sizeof(filename), "%s/driver", dirname); 313 ret = pci_get_kernel_driver_by_path(filename, driver); 314 if (ret < 0) { 315 RTE_LOG(ERR, EAL, "Fail to get kernel driver\n"); 316 free(dev); 317 return -1; 318 } 319 320 if (!ret) { 321 if (!strcmp(driver, "vfio-pci")) 322 dev->kdrv = RTE_KDRV_VFIO; 323 else if (!strcmp(driver, "igb_uio")) 324 dev->kdrv = RTE_KDRV_IGB_UIO; 325 else if (!strcmp(driver, "uio_pci_generic")) 326 dev->kdrv = RTE_KDRV_UIO_GENERIC; 327 else 328 dev->kdrv = RTE_KDRV_UNKNOWN; 329 } else 330 dev->kdrv = RTE_KDRV_NONE; 331 332 /* device is valid, add in list (sorted) */ 333 if (TAILQ_EMPTY(&rte_pci_bus.device_list)) { 334 rte_pci_add_device(dev); 335 } else { 336 struct rte_pci_device *dev2; 337 int ret; 338 339 TAILQ_FOREACH(dev2, &rte_pci_bus.device_list, next) { 340 ret = rte_pci_addr_cmp(&dev->addr, &dev2->addr); 341 if (ret > 0) 342 continue; 343 344 if (ret < 0) { 345 rte_pci_insert_device(dev2, dev); 346 } else { /* already registered */ 347 dev2->kdrv = dev->kdrv; 348 dev2->max_vfs = dev->max_vfs; 349 pci_name_set(dev2); 350 memmove(dev2->mem_resource, dev->mem_resource, 351 sizeof(dev->mem_resource)); 352 free(dev); 353 } 354 return 0; 355 } 356 357 rte_pci_add_device(dev); 358 } 359 360 return 0; 361 } 362 363 int 364 pci_update_device(const struct rte_pci_addr *addr) 365 { 366 char filename[PATH_MAX]; 367 368 snprintf(filename, sizeof(filename), "%s/" PCI_PRI_FMT, 369 rte_pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid, 370 addr->function); 371 372 return pci_scan_one(filename, addr); 373 } 374 375 /* 376 * split up a pci address into its constituent parts. 377 */ 378 static int 379 parse_pci_addr_format(const char *buf, int bufsize, struct rte_pci_addr *addr) 380 { 381 /* first split on ':' */ 382 union splitaddr { 383 struct { 384 char *domain; 385 char *bus; 386 char *devid; 387 char *function; 388 }; 389 char *str[PCI_FMT_NVAL]; /* last element-separator is "." not ":" */ 390 } splitaddr; 391 392 char *buf_copy = strndup(buf, bufsize); 393 if (buf_copy == NULL) 394 return -1; 395 396 if (rte_strsplit(buf_copy, bufsize, splitaddr.str, PCI_FMT_NVAL, ':') 397 != PCI_FMT_NVAL - 1) 398 goto error; 399 /* final split is on '.' between devid and function */ 400 splitaddr.function = strchr(splitaddr.devid,'.'); 401 if (splitaddr.function == NULL) 402 goto error; 403 *splitaddr.function++ = '\0'; 404 405 /* now convert to int values */ 406 errno = 0; 407 addr->domain = strtoul(splitaddr.domain, NULL, 16); 408 addr->bus = strtoul(splitaddr.bus, NULL, 16); 409 addr->devid = strtoul(splitaddr.devid, NULL, 16); 410 addr->function = strtoul(splitaddr.function, NULL, 10); 411 if (errno != 0) 412 goto error; 413 414 free(buf_copy); /* free the copy made with strdup */ 415 return 0; 416 error: 417 free(buf_copy); 418 return -1; 419 } 420 421 /* 422 * Scan the content of the PCI bus, and the devices in the devices 423 * list 424 */ 425 int 426 rte_pci_scan(void) 427 { 428 struct dirent *e; 429 DIR *dir; 430 char dirname[PATH_MAX]; 431 struct rte_pci_addr addr; 432 433 /* for debug purposes, PCI can be disabled */ 434 if (!rte_eal_has_pci()) 435 return 0; 436 437 #ifdef VFIO_PRESENT 438 if (!pci_vfio_is_enabled()) 439 RTE_LOG(DEBUG, EAL, "VFIO PCI modules not loaded\n"); 440 #endif 441 442 dir = opendir(rte_pci_get_sysfs_path()); 443 if (dir == NULL) { 444 RTE_LOG(ERR, EAL, "%s(): opendir failed: %s\n", 445 __func__, strerror(errno)); 446 return -1; 447 } 448 449 while ((e = readdir(dir)) != NULL) { 450 if (e->d_name[0] == '.') 451 continue; 452 453 if (parse_pci_addr_format(e->d_name, sizeof(e->d_name), &addr) != 0) 454 continue; 455 456 snprintf(dirname, sizeof(dirname), "%s/%s", 457 rte_pci_get_sysfs_path(), e->d_name); 458 459 if (pci_scan_one(dirname, &addr) < 0) 460 goto error; 461 } 462 closedir(dir); 463 return 0; 464 465 error: 466 closedir(dir); 467 return -1; 468 } 469 470 /* 471 * Is pci device bound to any kdrv 472 */ 473 static inline int 474 pci_one_device_is_bound(void) 475 { 476 struct rte_pci_device *dev = NULL; 477 int ret = 0; 478 479 FOREACH_DEVICE_ON_PCIBUS(dev) { 480 if (dev->kdrv == RTE_KDRV_UNKNOWN || 481 dev->kdrv == RTE_KDRV_NONE) { 482 continue; 483 } else { 484 ret = 1; 485 break; 486 } 487 } 488 return ret; 489 } 490 491 /* 492 * Any one of the device bound to uio 493 */ 494 static inline int 495 pci_one_device_bound_uio(void) 496 { 497 struct rte_pci_device *dev = NULL; 498 struct rte_devargs *devargs; 499 int need_check; 500 501 FOREACH_DEVICE_ON_PCIBUS(dev) { 502 devargs = dev->device.devargs; 503 504 need_check = 0; 505 switch (rte_pci_bus.bus.conf.scan_mode) { 506 case RTE_BUS_SCAN_WHITELIST: 507 if (devargs && devargs->policy == RTE_DEV_WHITELISTED) 508 need_check = 1; 509 break; 510 case RTE_BUS_SCAN_UNDEFINED: 511 case RTE_BUS_SCAN_BLACKLIST: 512 if (devargs == NULL || 513 devargs->policy != RTE_DEV_BLACKLISTED) 514 need_check = 1; 515 break; 516 } 517 518 if (!need_check) 519 continue; 520 521 if (dev->kdrv == RTE_KDRV_IGB_UIO || 522 dev->kdrv == RTE_KDRV_UIO_GENERIC) { 523 return 1; 524 } 525 } 526 return 0; 527 } 528 529 /* 530 * Any one of the device has iova as va 531 */ 532 static inline int 533 pci_one_device_has_iova_va(void) 534 { 535 struct rte_pci_device *dev = NULL; 536 struct rte_pci_driver *drv = NULL; 537 538 FOREACH_DRIVER_ON_PCIBUS(drv) { 539 if (drv && drv->drv_flags & RTE_PCI_DRV_IOVA_AS_VA) { 540 FOREACH_DEVICE_ON_PCIBUS(dev) { 541 if (dev->kdrv == RTE_KDRV_VFIO && 542 rte_pci_match(drv, dev)) 543 return 1; 544 } 545 } 546 } 547 return 0; 548 } 549 550 #if defined(RTE_ARCH_X86) 551 static bool 552 pci_one_device_iommu_support_va(struct rte_pci_device *dev) 553 { 554 #define VTD_CAP_MGAW_SHIFT 16 555 #define VTD_CAP_MGAW_MASK (0x3fULL << VTD_CAP_MGAW_SHIFT) 556 #define X86_VA_WIDTH 47 /* From Documentation/x86/x86_64/mm.txt */ 557 struct rte_pci_addr *addr = &dev->addr; 558 char filename[PATH_MAX]; 559 FILE *fp; 560 uint64_t mgaw, vtd_cap_reg = 0; 561 562 snprintf(filename, sizeof(filename), 563 "%s/" PCI_PRI_FMT "/iommu/intel-iommu/cap", 564 rte_pci_get_sysfs_path(), addr->domain, addr->bus, addr->devid, 565 addr->function); 566 if (access(filename, F_OK) == -1) { 567 /* We don't have an Intel IOMMU, assume VA supported*/ 568 return true; 569 } 570 571 /* We have an intel IOMMU */ 572 fp = fopen(filename, "r"); 573 if (fp == NULL) { 574 RTE_LOG(ERR, EAL, "%s(): can't open %s\n", __func__, filename); 575 return false; 576 } 577 578 if (fscanf(fp, "%" PRIx64, &vtd_cap_reg) != 1) { 579 RTE_LOG(ERR, EAL, "%s(): can't read %s\n", __func__, filename); 580 fclose(fp); 581 return false; 582 } 583 584 fclose(fp); 585 586 mgaw = ((vtd_cap_reg & VTD_CAP_MGAW_MASK) >> VTD_CAP_MGAW_SHIFT) + 1; 587 if (mgaw < X86_VA_WIDTH) 588 return false; 589 590 return true; 591 } 592 #elif defined(RTE_ARCH_PPC_64) 593 static bool 594 pci_one_device_iommu_support_va(__rte_unused struct rte_pci_device *dev) 595 { 596 return false; 597 } 598 #else 599 static bool 600 pci_one_device_iommu_support_va(__rte_unused struct rte_pci_device *dev) 601 { 602 return true; 603 } 604 #endif 605 606 /* 607 * All devices IOMMUs support VA as IOVA 608 */ 609 static bool 610 pci_devices_iommu_support_va(void) 611 { 612 struct rte_pci_device *dev = NULL; 613 struct rte_pci_driver *drv = NULL; 614 615 FOREACH_DRIVER_ON_PCIBUS(drv) { 616 FOREACH_DEVICE_ON_PCIBUS(dev) { 617 if (!rte_pci_match(drv, dev)) 618 continue; 619 if (!pci_one_device_iommu_support_va(dev)) 620 return false; 621 } 622 } 623 return true; 624 } 625 626 /* 627 * Get iommu class of PCI devices on the bus. 628 */ 629 enum rte_iova_mode 630 rte_pci_get_iommu_class(void) 631 { 632 bool is_bound; 633 bool is_vfio_noiommu_enabled = true; 634 bool has_iova_va; 635 bool is_bound_uio; 636 bool iommu_no_va; 637 638 is_bound = pci_one_device_is_bound(); 639 if (!is_bound) 640 return RTE_IOVA_DC; 641 642 has_iova_va = pci_one_device_has_iova_va(); 643 is_bound_uio = pci_one_device_bound_uio(); 644 iommu_no_va = !pci_devices_iommu_support_va(); 645 #ifdef VFIO_PRESENT 646 is_vfio_noiommu_enabled = rte_vfio_noiommu_is_enabled() == true ? 647 true : false; 648 #endif 649 650 if (has_iova_va && !is_bound_uio && !is_vfio_noiommu_enabled && 651 !iommu_no_va) 652 return RTE_IOVA_VA; 653 654 if (has_iova_va) { 655 RTE_LOG(WARNING, EAL, "Some devices want iova as va but pa will be used because.. "); 656 if (is_vfio_noiommu_enabled) 657 RTE_LOG(WARNING, EAL, "vfio-noiommu mode configured\n"); 658 if (is_bound_uio) 659 RTE_LOG(WARNING, EAL, "few device bound to UIO\n"); 660 if (iommu_no_va) 661 RTE_LOG(WARNING, EAL, "IOMMU does not support IOVA as VA\n"); 662 } 663 664 return RTE_IOVA_PA; 665 } 666 667 /* Read PCI config space. */ 668 int rte_pci_read_config(const struct rte_pci_device *device, 669 void *buf, size_t len, off_t offset) 670 { 671 const struct rte_intr_handle *intr_handle = &device->intr_handle; 672 673 switch (intr_handle->type) { 674 case RTE_INTR_HANDLE_UIO: 675 case RTE_INTR_HANDLE_UIO_INTX: 676 return pci_uio_read_config(intr_handle, buf, len, offset); 677 678 #ifdef VFIO_PRESENT 679 case RTE_INTR_HANDLE_VFIO_MSIX: 680 case RTE_INTR_HANDLE_VFIO_MSI: 681 case RTE_INTR_HANDLE_VFIO_LEGACY: 682 return pci_vfio_read_config(intr_handle, buf, len, offset); 683 #endif 684 default: 685 RTE_LOG(ERR, EAL, 686 "Unknown handle type of fd %d\n", 687 intr_handle->fd); 688 return -1; 689 } 690 } 691 692 /* Write PCI config space. */ 693 int rte_pci_write_config(const struct rte_pci_device *device, 694 const void *buf, size_t len, off_t offset) 695 { 696 const struct rte_intr_handle *intr_handle = &device->intr_handle; 697 698 switch (intr_handle->type) { 699 case RTE_INTR_HANDLE_UIO: 700 case RTE_INTR_HANDLE_UIO_INTX: 701 return pci_uio_write_config(intr_handle, buf, len, offset); 702 703 #ifdef VFIO_PRESENT 704 case RTE_INTR_HANDLE_VFIO_MSIX: 705 case RTE_INTR_HANDLE_VFIO_MSI: 706 case RTE_INTR_HANDLE_VFIO_LEGACY: 707 return pci_vfio_write_config(intr_handle, buf, len, offset); 708 #endif 709 default: 710 RTE_LOG(ERR, EAL, 711 "Unknown handle type of fd %d\n", 712 intr_handle->fd); 713 return -1; 714 } 715 } 716 717 #if defined(RTE_ARCH_X86) 718 static int 719 pci_ioport_map(struct rte_pci_device *dev, int bar __rte_unused, 720 struct rte_pci_ioport *p) 721 { 722 uint16_t start, end; 723 FILE *fp; 724 char *line = NULL; 725 char pci_id[16]; 726 int found = 0; 727 size_t linesz; 728 729 snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT, 730 dev->addr.domain, dev->addr.bus, 731 dev->addr.devid, dev->addr.function); 732 733 fp = fopen("/proc/ioports", "r"); 734 if (fp == NULL) { 735 RTE_LOG(ERR, EAL, "%s(): can't open ioports\n", __func__); 736 return -1; 737 } 738 739 while (getdelim(&line, &linesz, '\n', fp) > 0) { 740 char *ptr = line; 741 char *left; 742 int n; 743 744 n = strcspn(ptr, ":"); 745 ptr[n] = 0; 746 left = &ptr[n + 1]; 747 748 while (*left && isspace(*left)) 749 left++; 750 751 if (!strncmp(left, pci_id, strlen(pci_id))) { 752 found = 1; 753 754 while (*ptr && isspace(*ptr)) 755 ptr++; 756 757 sscanf(ptr, "%04hx-%04hx", &start, &end); 758 759 break; 760 } 761 } 762 763 free(line); 764 fclose(fp); 765 766 if (!found) 767 return -1; 768 769 p->base = start; 770 RTE_LOG(DEBUG, EAL, "PCI Port IO found start=0x%x\n", start); 771 772 return 0; 773 } 774 #endif 775 776 int 777 rte_pci_ioport_map(struct rte_pci_device *dev, int bar, 778 struct rte_pci_ioport *p) 779 { 780 int ret = -1; 781 782 switch (dev->kdrv) { 783 #ifdef VFIO_PRESENT 784 case RTE_KDRV_VFIO: 785 if (pci_vfio_is_enabled()) 786 ret = pci_vfio_ioport_map(dev, bar, p); 787 break; 788 #endif 789 case RTE_KDRV_IGB_UIO: 790 ret = pci_uio_ioport_map(dev, bar, p); 791 break; 792 case RTE_KDRV_UIO_GENERIC: 793 #if defined(RTE_ARCH_X86) 794 ret = pci_ioport_map(dev, bar, p); 795 #else 796 ret = pci_uio_ioport_map(dev, bar, p); 797 #endif 798 break; 799 case RTE_KDRV_NONE: 800 #if defined(RTE_ARCH_X86) 801 ret = pci_ioport_map(dev, bar, p); 802 #endif 803 break; 804 default: 805 break; 806 } 807 808 if (!ret) 809 p->dev = dev; 810 811 return ret; 812 } 813 814 void 815 rte_pci_ioport_read(struct rte_pci_ioport *p, 816 void *data, size_t len, off_t offset) 817 { 818 switch (p->dev->kdrv) { 819 #ifdef VFIO_PRESENT 820 case RTE_KDRV_VFIO: 821 pci_vfio_ioport_read(p, data, len, offset); 822 break; 823 #endif 824 case RTE_KDRV_IGB_UIO: 825 pci_uio_ioport_read(p, data, len, offset); 826 break; 827 case RTE_KDRV_UIO_GENERIC: 828 pci_uio_ioport_read(p, data, len, offset); 829 break; 830 case RTE_KDRV_NONE: 831 #if defined(RTE_ARCH_X86) 832 pci_uio_ioport_read(p, data, len, offset); 833 #endif 834 break; 835 default: 836 break; 837 } 838 } 839 840 void 841 rte_pci_ioport_write(struct rte_pci_ioport *p, 842 const void *data, size_t len, off_t offset) 843 { 844 switch (p->dev->kdrv) { 845 #ifdef VFIO_PRESENT 846 case RTE_KDRV_VFIO: 847 pci_vfio_ioport_write(p, data, len, offset); 848 break; 849 #endif 850 case RTE_KDRV_IGB_UIO: 851 pci_uio_ioport_write(p, data, len, offset); 852 break; 853 case RTE_KDRV_UIO_GENERIC: 854 pci_uio_ioport_write(p, data, len, offset); 855 break; 856 case RTE_KDRV_NONE: 857 #if defined(RTE_ARCH_X86) 858 pci_uio_ioport_write(p, data, len, offset); 859 #endif 860 break; 861 default: 862 break; 863 } 864 } 865 866 int 867 rte_pci_ioport_unmap(struct rte_pci_ioport *p) 868 { 869 int ret = -1; 870 871 switch (p->dev->kdrv) { 872 #ifdef VFIO_PRESENT 873 case RTE_KDRV_VFIO: 874 if (pci_vfio_is_enabled()) 875 ret = pci_vfio_ioport_unmap(p); 876 break; 877 #endif 878 case RTE_KDRV_IGB_UIO: 879 ret = pci_uio_ioport_unmap(p); 880 break; 881 case RTE_KDRV_UIO_GENERIC: 882 #if defined(RTE_ARCH_X86) 883 ret = 0; 884 #else 885 ret = pci_uio_ioport_unmap(p); 886 #endif 887 break; 888 case RTE_KDRV_NONE: 889 #if defined(RTE_ARCH_X86) 890 ret = 0; 891 #endif 892 break; 893 default: 894 break; 895 } 896 897 return ret; 898 } 899