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 = 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 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(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 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 590 is_bound = pci_one_device_is_bound(); 591 if (!is_bound) 592 return RTE_IOVA_DC; 593 594 has_iova_va = pci_one_device_has_iova_va(); 595 is_bound_uio = pci_one_device_bound_uio(); 596 #ifdef VFIO_PRESENT 597 is_vfio_noiommu_enabled = vfio_noiommu_is_enabled() == true ? 598 true : false; 599 #endif 600 601 if (has_iova_va && !is_bound_uio && !is_vfio_noiommu_enabled) 602 return RTE_IOVA_VA; 603 604 if (has_iova_va) { 605 RTE_LOG(WARNING, EAL, "Some devices want iova as va but pa will be used because.. "); 606 if (is_vfio_noiommu_enabled) 607 RTE_LOG(WARNING, EAL, "vfio-noiommu mode configured\n"); 608 if (is_bound_uio) 609 RTE_LOG(WARNING, EAL, "few device bound to UIO\n"); 610 } 611 612 return RTE_IOVA_PA; 613 } 614 615 /* Read PCI config space. */ 616 int rte_pci_read_config(const struct rte_pci_device *device, 617 void *buf, size_t len, off_t offset) 618 { 619 const struct rte_intr_handle *intr_handle = &device->intr_handle; 620 621 switch (intr_handle->type) { 622 case RTE_INTR_HANDLE_UIO: 623 case RTE_INTR_HANDLE_UIO_INTX: 624 return pci_uio_read_config(intr_handle, buf, len, offset); 625 626 #ifdef VFIO_PRESENT 627 case RTE_INTR_HANDLE_VFIO_MSIX: 628 case RTE_INTR_HANDLE_VFIO_MSI: 629 case RTE_INTR_HANDLE_VFIO_LEGACY: 630 return pci_vfio_read_config(intr_handle, buf, len, offset); 631 #endif 632 default: 633 RTE_LOG(ERR, EAL, 634 "Unknown handle type of fd %d\n", 635 intr_handle->fd); 636 return -1; 637 } 638 } 639 640 /* Write PCI config space. */ 641 int rte_pci_write_config(const struct rte_pci_device *device, 642 const void *buf, size_t len, off_t offset) 643 { 644 const struct rte_intr_handle *intr_handle = &device->intr_handle; 645 646 switch (intr_handle->type) { 647 case RTE_INTR_HANDLE_UIO: 648 case RTE_INTR_HANDLE_UIO_INTX: 649 return pci_uio_write_config(intr_handle, buf, len, offset); 650 651 #ifdef VFIO_PRESENT 652 case RTE_INTR_HANDLE_VFIO_MSIX: 653 case RTE_INTR_HANDLE_VFIO_MSI: 654 case RTE_INTR_HANDLE_VFIO_LEGACY: 655 return pci_vfio_write_config(intr_handle, buf, len, offset); 656 #endif 657 default: 658 RTE_LOG(ERR, EAL, 659 "Unknown handle type of fd %d\n", 660 intr_handle->fd); 661 return -1; 662 } 663 } 664 665 #if defined(RTE_ARCH_X86) 666 static int 667 pci_ioport_map(struct rte_pci_device *dev, int bar __rte_unused, 668 struct rte_pci_ioport *p) 669 { 670 uint16_t start, end; 671 FILE *fp; 672 char *line = NULL; 673 char pci_id[16]; 674 int found = 0; 675 size_t linesz; 676 677 snprintf(pci_id, sizeof(pci_id), PCI_PRI_FMT, 678 dev->addr.domain, dev->addr.bus, 679 dev->addr.devid, dev->addr.function); 680 681 fp = fopen("/proc/ioports", "r"); 682 if (fp == NULL) { 683 RTE_LOG(ERR, EAL, "%s(): can't open ioports\n", __func__); 684 return -1; 685 } 686 687 while (getdelim(&line, &linesz, '\n', fp) > 0) { 688 char *ptr = line; 689 char *left; 690 int n; 691 692 n = strcspn(ptr, ":"); 693 ptr[n] = 0; 694 left = &ptr[n + 1]; 695 696 while (*left && isspace(*left)) 697 left++; 698 699 if (!strncmp(left, pci_id, strlen(pci_id))) { 700 found = 1; 701 702 while (*ptr && isspace(*ptr)) 703 ptr++; 704 705 sscanf(ptr, "%04hx-%04hx", &start, &end); 706 707 break; 708 } 709 } 710 711 free(line); 712 fclose(fp); 713 714 if (!found) 715 return -1; 716 717 dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; 718 p->base = start; 719 RTE_LOG(DEBUG, EAL, "PCI Port IO found start=0x%x\n", start); 720 721 return 0; 722 } 723 #endif 724 725 int 726 rte_pci_ioport_map(struct rte_pci_device *dev, int bar, 727 struct rte_pci_ioport *p) 728 { 729 int ret = -1; 730 731 switch (dev->kdrv) { 732 #ifdef VFIO_PRESENT 733 case RTE_KDRV_VFIO: 734 if (pci_vfio_is_enabled()) 735 ret = pci_vfio_ioport_map(dev, bar, p); 736 break; 737 #endif 738 case RTE_KDRV_IGB_UIO: 739 ret = pci_uio_ioport_map(dev, bar, p); 740 break; 741 case RTE_KDRV_UIO_GENERIC: 742 #if defined(RTE_ARCH_X86) 743 ret = pci_ioport_map(dev, bar, p); 744 #else 745 ret = pci_uio_ioport_map(dev, bar, p); 746 #endif 747 break; 748 case RTE_KDRV_NONE: 749 #if defined(RTE_ARCH_X86) 750 ret = pci_ioport_map(dev, bar, p); 751 #endif 752 break; 753 default: 754 break; 755 } 756 757 if (!ret) 758 p->dev = dev; 759 760 return ret; 761 } 762 763 void 764 rte_pci_ioport_read(struct rte_pci_ioport *p, 765 void *data, size_t len, off_t offset) 766 { 767 switch (p->dev->kdrv) { 768 #ifdef VFIO_PRESENT 769 case RTE_KDRV_VFIO: 770 pci_vfio_ioport_read(p, data, len, offset); 771 break; 772 #endif 773 case RTE_KDRV_IGB_UIO: 774 pci_uio_ioport_read(p, data, len, offset); 775 break; 776 case RTE_KDRV_UIO_GENERIC: 777 pci_uio_ioport_read(p, data, len, offset); 778 break; 779 case RTE_KDRV_NONE: 780 #if defined(RTE_ARCH_X86) 781 pci_uio_ioport_read(p, data, len, offset); 782 #endif 783 break; 784 default: 785 break; 786 } 787 } 788 789 void 790 rte_pci_ioport_write(struct rte_pci_ioport *p, 791 const void *data, size_t len, off_t offset) 792 { 793 switch (p->dev->kdrv) { 794 #ifdef VFIO_PRESENT 795 case RTE_KDRV_VFIO: 796 pci_vfio_ioport_write(p, data, len, offset); 797 break; 798 #endif 799 case RTE_KDRV_IGB_UIO: 800 pci_uio_ioport_write(p, data, len, offset); 801 break; 802 case RTE_KDRV_UIO_GENERIC: 803 pci_uio_ioport_write(p, data, len, offset); 804 break; 805 case RTE_KDRV_NONE: 806 #if defined(RTE_ARCH_X86) 807 pci_uio_ioport_write(p, data, len, offset); 808 #endif 809 break; 810 default: 811 break; 812 } 813 } 814 815 int 816 rte_pci_ioport_unmap(struct rte_pci_ioport *p) 817 { 818 int ret = -1; 819 820 switch (p->dev->kdrv) { 821 #ifdef VFIO_PRESENT 822 case RTE_KDRV_VFIO: 823 if (pci_vfio_is_enabled()) 824 ret = pci_vfio_ioport_unmap(p); 825 break; 826 #endif 827 case RTE_KDRV_IGB_UIO: 828 ret = pci_uio_ioport_unmap(p); 829 break; 830 case RTE_KDRV_UIO_GENERIC: 831 #if defined(RTE_ARCH_X86) 832 ret = 0; 833 #else 834 ret = pci_uio_ioport_unmap(p); 835 #endif 836 break; 837 case RTE_KDRV_NONE: 838 #if defined(RTE_ARCH_X86) 839 ret = 0; 840 #endif 841 break; 842 default: 843 break; 844 } 845 846 return ret; 847 } 848