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