/* map the PCI resource of a PCI device in virtual memory */ int pci_uio_map_resource(struct rte_pci_device *dev) { int i, map_idx = 0, ret; uint64_t phaddr; struct mapped_pci_resource *uio_res = NULL; struct mapped_pci_res_list *uio_res_list = RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); dev->intr_handle.fd = -1; dev->intr_handle.uio_cfg_fd = -1; dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; /* secondary processes - use already recorded details */ if (rte_eal_process_type() != RTE_PROC_PRIMARY) return pci_uio_map_secondary(dev); /* allocate uio resource */ ret = pci_uio_alloc_resource(dev, &uio_res); if (ret) return ret; /* Map all BARs */ for (i = 0; i != PCI_MAX_RESOURCE; i++) { /* skip empty BAR */ phaddr = dev->mem_resource[i].phys_addr; if (phaddr == 0) continue; ret = pci_uio_map_resource_by_index(dev, i, uio_res, map_idx); if (ret) goto error; map_idx++; } uio_res->nb_maps = map_idx; TAILQ_INSERT_TAIL(uio_res_list, uio_res, next); return 0; error: for (i = 0; i < map_idx; i++) { pci_unmap_resource(uio_res->maps[i].addr, (size_t)uio_res->maps[i].size); rte_free(uio_res->maps[i].path); } pci_uio_free_resource(dev, uio_res); return -1; }
/* map the PCI resource of a PCI device in virtual memory */ int pci_uio_map_resource(struct rte_pci_device *dev) { int i, map_idx; char dirname[PATH_MAX]; char cfgname[PATH_MAX]; char devname[PATH_MAX]; /* contains the /dev/uioX */ void *mapaddr; int uio_num; uint64_t phaddr; struct rte_pci_addr *loc = &dev->addr; struct mapped_pci_resource *uio_res; struct mapped_pci_res_list *uio_res_list = RTE_TAILQ_CAST(rte_uio_tailq.head, mapped_pci_res_list); struct pci_map *maps; dev->intr_handle.fd = -1; dev->intr_handle.uio_cfg_fd = -1; dev->intr_handle.type = RTE_INTR_HANDLE_UNKNOWN; /* secondary processes - use already recorded details */ if (rte_eal_process_type() != RTE_PROC_PRIMARY) return pci_uio_map_secondary(dev); /* find uio resource */ uio_num = pci_get_uio_dev(dev, dirname, sizeof(dirname)); if (uio_num < 0) { RTE_LOG(WARNING, EAL, " "PCI_PRI_FMT" not managed by UIO driver, " "skipping\n", loc->domain, loc->bus, loc->devid, loc->function); return 1; } snprintf(devname, sizeof(devname), "/dev/uio%u", uio_num); /* save fd if in primary process */ dev->intr_handle.fd = open(devname, O_RDWR); if (dev->intr_handle.fd < 0) { RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", devname, strerror(errno)); return -1; } dev->intr_handle.type = RTE_INTR_HANDLE_UIO; snprintf(cfgname, sizeof(cfgname), "/sys/class/uio/uio%u/device/config", uio_num); dev->intr_handle.uio_cfg_fd = open(cfgname, O_RDWR); if (dev->intr_handle.uio_cfg_fd < 0) { RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", cfgname, strerror(errno)); return -1; } /* set bus master that is not done by uio_pci_generic */ if (pci_uio_set_bus_master(dev->intr_handle.uio_cfg_fd)) { RTE_LOG(ERR, EAL, "Cannot set up bus mastering!\n"); return -1; } /* allocate the mapping details for secondary processes*/ uio_res = rte_zmalloc("UIO_RES", sizeof(*uio_res), 0); if (uio_res == NULL) { RTE_LOG(ERR, EAL, "%s(): cannot store uio mmap details\n", __func__); return -1; } snprintf(uio_res->path, sizeof(uio_res->path), "%s", devname); memcpy(&uio_res->pci_addr, &dev->addr, sizeof(uio_res->pci_addr)); /* Map all BARs */ maps = uio_res->maps; for (i = 0, map_idx = 0; i != PCI_MAX_RESOURCE; i++) { int fd; int fail = 0; /* skip empty BAR */ phaddr = dev->mem_resource[i].phys_addr; if (phaddr == 0) continue; /* update devname for mmap */ snprintf(devname, sizeof(devname), SYSFS_PCI_DEVICES "/" PCI_PRI_FMT "/resource%d", loc->domain, loc->bus, loc->devid, loc->function, i); /* * open resource file, to mmap it */ fd = open(devname, O_RDWR); if (fd < 0) { RTE_LOG(ERR, EAL, "Cannot open %s: %s\n", devname, strerror(errno)); return -1; } /* try mapping somewhere close to the end of hugepages */ if (pci_map_addr == NULL) pci_map_addr = pci_find_max_end_va(); mapaddr = pci_map_resource(pci_map_addr, fd, 0, (size_t)dev->mem_resource[i].len, 0); if (mapaddr == MAP_FAILED) fail = 1; pci_map_addr = RTE_PTR_ADD(mapaddr, (size_t)dev->mem_resource[i].len); maps[map_idx].path = rte_malloc(NULL, strlen(devname) + 1, 0); if (maps[map_idx].path == NULL) fail = 1; if (fail) { rte_free(uio_res); close(fd); return -1; } close(fd); maps[map_idx].phaddr = dev->mem_resource[i].phys_addr; maps[map_idx].size = dev->mem_resource[i].len; maps[map_idx].addr = mapaddr; maps[map_idx].offset = 0; strcpy(maps[map_idx].path, devname); map_idx++; dev->mem_resource[i].addr = mapaddr; } uio_res->nb_maps = map_idx; TAILQ_INSERT_TAIL(uio_res_list, uio_res, next); return 0; }