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