/**
* @file
- * PCI probing under linux (VFIO version)
+ * PCI probing using Linux VFIO.
*
* This code tries to determine if the PCI device is bound to VFIO driver,
* and initialize it (map BARs, set up interrupts) if that's the case.
#ifdef VFIO_PRESENT
-#ifndef PAGE_SIZE
-#define PAGE_SIZE (sysconf(_SC_PAGESIZE))
-#endif
-#define PAGE_MASK (~(PAGE_SIZE - 1))
-
static struct rte_tailq_elem rte_vfio_tailq = {
.name = "VFIO_RESOURCE_LIST",
};
VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +
PCI_CAPABILITY_LIST);
if (ret != sizeof(reg)) {
- RTE_LOG(ERR, EAL, "Cannot read capability pointer from PCI "
- "config space!\n");
+ RTE_LOG(ERR, EAL,
+ "Cannot read capability pointer from PCI config space!\n");
return -1;
}
VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +
cap_offset);
if (ret != sizeof(reg)) {
- RTE_LOG(ERR, EAL, "Cannot read capability ID from PCI "
- "config space!\n");
+ RTE_LOG(ERR, EAL,
+ "Cannot read capability ID from PCI config space!\n");
return -1;
}
VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +
cap_offset);
if (ret != sizeof(reg)) {
- RTE_LOG(ERR, EAL, "Cannot read capability pointer from PCI "
- "config space!\n");
+ RTE_LOG(ERR, EAL,
+ "Cannot read capability pointer from PCI config space!\n");
return -1;
}
VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +
cap_offset + 4);
if (ret != sizeof(reg)) {
- RTE_LOG(ERR, EAL, "Cannot read table offset from PCI config "
- "space!\n");
+ RTE_LOG(ERR, EAL,
+ "Cannot read table offset from PCI config space!\n");
return -1;
}
VFIO_GET_REGION_ADDR(VFIO_PCI_CONFIG_REGION_INDEX) +
cap_offset + 2);
if (ret != sizeof(flags)) {
- RTE_LOG(ERR, EAL, "Cannot read table flags from PCI config "
- "space!\n");
+ RTE_LOG(ERR, EAL,
+ "Cannot read table flags from PCI config space!\n");
return -1;
}
case RTE_INTR_MODE_NONE:
break;
default:
- RTE_LOG(ERR, EAL, " unknown default interrupt type!\n");
+ RTE_LOG(ERR, EAL, "Unknown default interrupt type!\n");
return -1;
}
ret = ioctl(vfio_dev_fd, VFIO_DEVICE_GET_IRQ_INFO, &irq);
if (ret < 0) {
- RTE_LOG(ERR, EAL, " cannot get IRQ info, "
- "error %i (%s)\n", errno, strerror(errno));
+ RTE_LOG(ERR, EAL, "Cannot get VFIO IRQ info, error "
+ "%i (%s)\n", errno, strerror(errno));
return -1;
}
if ((irq.flags & VFIO_IRQ_INFO_EVENTFD) == 0) {
if (intr_mode != RTE_INTR_MODE_NONE) {
RTE_LOG(ERR, EAL,
- " interrupt vector does not support eventfd!\n");
+ "Interrupt vector does not support eventfd!\n");
return -1;
} else
continue;
/* set up an eventfd for interrupts */
fd = eventfd(0, EFD_NONBLOCK | EFD_CLOEXEC);
if (fd < 0) {
- RTE_LOG(ERR, EAL, " cannot set up eventfd, "
- "error %i (%s)\n", errno, strerror(errno));
+ RTE_LOG(ERR, EAL, "Cannot set up eventfd, error "
+ "%i (%s)\n", errno, strerror(errno));
return -1;
}
dev->intr_handle.type = RTE_INTR_HANDLE_VFIO_LEGACY;
break;
default:
- RTE_LOG(ERR, EAL, " unknown interrupt type!\n");
+ RTE_LOG(ERR, EAL, "Unknown interrupt type!\n");
return -1;
}
return -1;
}
- ret = rte_intr_callback_unregister(&dev->vfio_req_intr_handle,
+ ret = rte_intr_callback_unregister_sync(&dev->vfio_req_intr_handle,
pci_vfio_req_handler,
(void *)&dev->device);
if (ret < 0) {
*/
uint32_t table_start = msix_table->offset;
uint32_t table_end = table_start + msix_table->size;
- table_end = RTE_ALIGN(table_end, PAGE_SIZE);
- table_start = RTE_ALIGN_FLOOR(table_start, PAGE_SIZE);
+ table_end = RTE_ALIGN(table_end, rte_mem_page_size());
+ table_start = RTE_ALIGN_FLOOR(table_start, rte_mem_page_size());
/* If page-aligned start of MSI-X table is less than the
* actual MSI-X table start address, reassign to the actual
RTE_MAP_FORCE_ADDRESS);
}
+ /*
+ * Regarding "memreg[0].size == 0":
+ * If this BAR has MSI-X table, memreg[0].size (the
+ * first part or the part before the table) can
+ * legitimately be 0 for hardware using vector table
+ * offset 0 (i.e. first part does not exist).
+ *
+ * When memreg[0].size is 0, "mapping the first part"
+ * never happens, and map_addr is NULL at this
+ * point. So check that mapping has been actually
+ * attempted.
+ */
/* if there's a second part, try to map it */
- if (map_addr != MAP_FAILED
+ if ((map_addr != NULL || memreg[0].size == 0)
&& memreg[1].offset && memreg[1].size) {
void *second_addr = RTE_PTR_ADD(bar_addr,
(uintptr_t)(memreg[1].offset -
RTE_MAP_FORCE_ADDRESS);
}
- if (map_addr == NULL || map_addr == MAP_FAILED) {
+ if (map_addr == NULL) {
munmap(bar_addr, bar->size);
bar_addr = MAP_FAILED;
RTE_LOG(ERR, EAL, "Failed to map pci BAR%d\n",
ri = malloc(sizeof(*ri));
if (ri == NULL) {
- RTE_LOG(ERR, EAL, "Cannot allocate memory for region info\n");
+ RTE_LOG(ERR, EAL,
+ "Cannot allocate memory for VFIO region info\n");
return -1;
}
again:
if (tmp == NULL) {
/* realloc failed but the ri is still there */
free(ri);
- RTE_LOG(ERR, EAL, "Cannot reallocate memory for region info\n");
+ RTE_LOG(ERR, EAL,
+ "Cannot reallocate memory for VFIO region info\n");
return -1;
}
ri = tmp;
vfio_res = rte_zmalloc("VFIO_RES", sizeof(*vfio_res), 0);
if (vfio_res == NULL) {
RTE_LOG(ERR, EAL,
- "%s(): cannot store vfio mmap details\n", __func__);
+ "Cannot store VFIO mmap details\n");
goto err_vfio_dev_fd;
}
memcpy(&vfio_res->pci_addr, &dev->addr, sizeof(vfio_res->pci_addr));
*/
ret = pci_vfio_get_msix_bar(vfio_dev_fd, &vfio_res->msix_table);
if (ret < 0) {
- RTE_LOG(ERR, EAL, " %s cannot get MSI-X BAR number!\n",
+ RTE_LOG(ERR, EAL, "%s cannot get MSI-X BAR number!\n",
pci_addr);
goto err_vfio_res;
}
}
}
- for (i = 0; i < (int) vfio_res->nb_maps; i++) {
+ for (i = 0; i < vfio_res->nb_maps; i++) {
struct vfio_region_info *reg = NULL;
void *bar_addr;
ret = pci_vfio_get_region_info(vfio_dev_fd, ®, i);
if (ret < 0) {
- RTE_LOG(ERR, EAL, " %s cannot get device region info "
- "error %i (%s)\n", pci_addr, errno,
- strerror(errno));
+ RTE_LOG(ERR, EAL,
+ "%s cannot get device region info error "
+ "%i (%s)\n", pci_addr, errno, strerror(errno));
goto err_vfio_res;
}
ret = pci_vfio_mmap_bar(vfio_dev_fd, vfio_res, i, 0);
if (ret < 0) {
- RTE_LOG(ERR, EAL, " %s mapping BAR%i failed: %s\n",
+ RTE_LOG(ERR, EAL, "%s mapping BAR%i failed: %s\n",
pci_addr, i, strerror(errno));
free(reg);
goto err_vfio_res;
}
if (pci_rte_vfio_setup_device(dev, vfio_dev_fd) < 0) {
- RTE_LOG(ERR, EAL, " %s setup device failed\n", pci_addr);
+ RTE_LOG(ERR, EAL, "%s setup device failed\n", pci_addr);
goto err_vfio_res;
}
err_vfio_res:
rte_free(vfio_res);
err_vfio_dev_fd:
- close(vfio_dev_fd);
+ rte_vfio_release_device(rte_pci_get_sysfs_path(),
+ pci_addr, vfio_dev_fd);
return -1;
}
}
/* if we haven't found our tailq entry, something's wrong */
if (vfio_res == NULL) {
- RTE_LOG(ERR, EAL, " %s cannot find TAILQ entry for PCI device!\n",
+ RTE_LOG(ERR, EAL, "%s cannot find TAILQ entry for PCI device!\n",
pci_addr);
return -1;
}
/* map BARs */
maps = vfio_res->maps;
- for (i = 0; i < (int) vfio_res->nb_maps; i++) {
+ for (i = 0; i < vfio_res->nb_maps; i++) {
ret = pci_vfio_mmap_bar(vfio_dev_fd, vfio_res, i, MAP_FIXED);
if (ret < 0) {
- RTE_LOG(ERR, EAL, " %s mapping BAR%i failed: %s\n",
+ RTE_LOG(ERR, EAL, "%s mapping BAR%i failed: %s\n",
pci_addr, i, strerror(errno));
goto err_vfio_dev_fd;
}
return 0;
err_vfio_dev_fd:
- close(vfio_dev_fd);
+ rte_vfio_release_device(rte_pci_get_sysfs_path(),
+ pci_addr, vfio_dev_fd);
return -1;
}
if (vfio_res == NULL)
return vfio_res;
- RTE_LOG(INFO, EAL, "Releasing pci mapped resource for %s\n",
+ RTE_LOG(INFO, EAL, "Releasing PCI mapped resource for %s\n",
pci_addr);
maps = vfio_res->maps;
- for (i = 0; i < (int) vfio_res->nb_maps; i++) {
+ for (i = 0; i < vfio_res->nb_maps; i++) {
/*
* We do not need to be aware of MSI-X table BAR mappings as
}
if (pci_vfio_set_bus_master(dev->intr_handle.vfio_dev_fd, false)) {
- RTE_LOG(ERR, EAL, " %s cannot unset bus mastering for PCI device!\n",
+ RTE_LOG(ERR, EAL, "%s cannot unset bus mastering for PCI device!\n",
pci_addr);
return -1;
}
ret = rte_vfio_release_device(rte_pci_get_sysfs_path(), pci_addr,
dev->intr_handle.vfio_dev_fd);
if (ret < 0) {
- RTE_LOG(ERR, EAL,
- "%s(): cannot release device\n", __func__);
+ RTE_LOG(ERR, EAL, "Cannot release VFIO device\n");
return ret;
}
/* if we haven't found our tailq entry, something's wrong */
if (vfio_res == NULL) {
- RTE_LOG(ERR, EAL, " %s cannot find TAILQ entry for PCI device!\n",
+ RTE_LOG(ERR, EAL, "%s cannot find TAILQ entry for PCI device!\n",
pci_addr);
return -1;
}
TAILQ_REMOVE(vfio_res_list, vfio_res, next);
-
+ rte_free(vfio_res);
return 0;
}
ret = rte_vfio_release_device(rte_pci_get_sysfs_path(), pci_addr,
dev->intr_handle.vfio_dev_fd);
if (ret < 0) {
- RTE_LOG(ERR, EAL,
- "%s(): cannot release device\n", __func__);
+ RTE_LOG(ERR, EAL, "Cannot release VFIO device\n");
return ret;
}
/* if we haven't found our tailq entry, something's wrong */
if (vfio_res == NULL) {
- RTE_LOG(ERR, EAL, " %s cannot find TAILQ entry for PCI device!\n",
+ RTE_LOG(ERR, EAL, "%s cannot find TAILQ entry for PCI device!\n",
pci_addr);
return -1;
}