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