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