@@ -387,6 +387,13 @@ nbl_userdev_mem_event_callback(enum rte_mem_event type, const void *addr, size_t
}
}
+static int nbl_open_group_fd(int iommu_group_num)
+{
+ char path[PATH_MAX];
+ snprintf(path, sizeof(path), RTE_VFIO_GROUP_FMT, iommu_group_num);
+ return open(path, O_RDWR);
+}
+
static int nbl_mdev_map_device(struct nbl_adapter *adapter)
{
const struct rte_pci_device *pci_dev = adapter->pci_dev;
@@ -424,11 +431,12 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
}
NBL_LOG(DEBUG, "nbl vfio container %d", container);
- vfio_group_fd = rte_vfio_container_group_bind(container, common->iommu_group_num);
+ vfio_group_fd = nbl_open_group_fd(common->iommu_group_num);
if (vfio_group_fd < 0) {
NBL_LOG(ERR, "nbl vfio group bind failed, %d", vfio_group_fd);
goto free_container;
}
+ common->groupfd = vfio_group_fd;
/* check if the group is viable */
ret = ioctl(vfio_group_fd, VFIO_GROUP_GET_STATUS, &group_status);
@@ -535,7 +543,6 @@ static int nbl_mdev_map_device(struct nbl_adapter *adapter)
}
free_group:
close(vfio_group_fd);
- rte_vfio_clear_group(vfio_group_fd);
free_container:
if (container_create)
rte_vfio_container_destroy(container);
@@ -549,17 +556,14 @@ static int nbl_mdev_unmap_device(struct nbl_adapter *adapter)
close(common->devfd);
rte_mcfg_mem_read_lock();
- vfio_group_fd = rte_vfio_container_group_bind(nbl_default_container,
- common->iommu_group_num);
+ vfio_group_fd = common->groupfd;
NBL_LOG(DEBUG, "close vfio_group_fd %d", vfio_group_fd);
ret = ioctl(vfio_group_fd, VFIO_GROUP_UNSET_CONTAINER, &nbl_default_container);
if (ret)
NBL_LOG(ERR, "unset container, error %i (%s) %d",
errno, strerror(errno), ret);
nbl_group_count--;
- ret = rte_vfio_container_group_unbind(nbl_default_container, common->iommu_group_num);
- if (ret)
- NBL_LOG(ERR, "vfio container group unbind failed %d", ret);
+ close(vfio_group_fd);
if (!nbl_group_count) {
rte_mem_event_callback_unregister(NBL_USERDEV_EVENT_CLB_NAME, NULL);
nbl_userdev_dma_free();
@@ -130,6 +130,7 @@ struct nbl_common_info {
u16 vsi_id;
u16 instance_id;
int devfd;
+ int groupfd;
int eventfd;
int ifindex;
int iommu_group_num;
@@ -29,7 +29,6 @@ nt_vfio_vf_num(const struct rte_pci_device *pdev)
/* Internal API */
struct vfio_dev {
int container_fd;
- int group_fd;
int dev_fd;
uint64_t iova_addr;
};
@@ -51,7 +50,6 @@ nthw_vfio_setup(struct rte_pci_device *dev)
{
int ret;
char devname[RTE_DEV_NAME_MAX_LEN] = { 0 };
- int iommu_group_num;
int vf_num;
struct vfio_dev *vfio;
@@ -67,14 +65,9 @@ nthw_vfio_setup(struct rte_pci_device *dev)
}
vfio->dev_fd = -1;
- vfio->group_fd = -1;
vfio->iova_addr = START_VF_IOVA;
rte_pci_device_name(&dev->addr, devname, RTE_DEV_NAME_MAX_LEN);
- ret = rte_vfio_get_group_num(rte_pci_get_sysfs_path(), devname, &iommu_group_num);
- if (ret <= 0)
- return -1;
-
if (vf_num == 0) {
/* use default container for pf0 */
vfio->container_fd = RTE_VFIO_DEFAULT_CONTAINER_FD;
@@ -87,17 +80,14 @@ nthw_vfio_setup(struct rte_pci_device *dev)
"VFIO device setup failed. VFIO container creation failed.");
return -1;
}
- }
+ ret = rte_vfio_container_assign_device(vfio->container_fd,
+ rte_pci_get_sysfs_path(), devname);
+ if (ret < 0) {
+ NT_LOG(ERR, NTNIC,
+ "VFIO device setup failed. Assign device to container failed.");
+ goto err;
+ }
- vfio->group_fd = rte_vfio_container_group_bind(vfio->container_fd, iommu_group_num);
-
- if (vfio->group_fd < 0) {
- NT_LOG(ERR, NTNIC,
- "VFIO device setup failed. VFIO container group bind failed.");
- goto err;
- }
-
- if (vf_num > 0) {
if (rte_pci_map_device(dev)) {
NT_LOG(ERR, NTNIC,
"Map VFIO device failed. is the vfio-pci driver loaded?");
@@ -107,10 +97,8 @@ nthw_vfio_setup(struct rte_pci_device *dev)
vfio->dev_fd = rte_intr_dev_fd_get(dev->intr_handle);
- NT_LOG(DBG, NTNIC,
- "%s: VFIO id=%d, dev_fd=%d, container_fd=%d, group_fd=%d, iommu_group_num=%d",
- dev->name, vf_num, vfio->dev_fd, vfio->container_fd, vfio->group_fd,
- iommu_group_num);
+ NT_LOG(DBG, NTNIC, "%s: VFIO id=%d, dev_fd=%d, container_fd=%d",
+ dev->name, vf_num, vfio->dev_fd, vfio->container_fd);
return vf_num;
@@ -174,28 +174,19 @@ ifcvf_vfio_setup(struct ifcvf_internal *internal)
{
struct rte_pci_device *dev = internal->pdev;
char devname[RTE_DEV_NAME_MAX_LEN] = {0};
- int iommu_group_num;
- int i, ret;
+ int i;
internal->vfio_dev_fd = -1;
- internal->vfio_group_fd = -1;
internal->vfio_container_fd = -1;
rte_pci_device_name(&dev->addr, devname, RTE_DEV_NAME_MAX_LEN);
- ret = rte_vfio_get_group_num(rte_pci_get_sysfs_path(), devname,
- &iommu_group_num);
- if (ret <= 0) {
- DRV_LOG(ERR, "%s failed to get IOMMU group", devname);
- return -1;
- }
internal->vfio_container_fd = rte_vfio_container_create();
if (internal->vfio_container_fd < 0)
return -1;
- internal->vfio_group_fd = rte_vfio_container_group_bind(
- internal->vfio_container_fd, iommu_group_num);
- if (internal->vfio_group_fd < 0)
+ if (rte_vfio_container_assign_device(internal->vfio_container_fd,
+ rte_pci_get_sysfs_path(), devname) < 0)
goto err;
if (rte_pci_map_device(dev))
@@ -122,33 +122,26 @@ nfp_vdpa_vfio_setup(struct nfp_vdpa_dev *device)
rte_pci_unmap_device(pci_dev);
rte_pci_device_name(&pci_dev->addr, dev_name, RTE_DEV_NAME_MAX_LEN);
- ret = rte_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
- &device->iommu_group);
- if (ret <= 0)
- return -1;
device->vfio_container_fd = rte_vfio_container_create();
if (device->vfio_container_fd < 0)
return -1;
- device->vfio_group_fd = rte_vfio_container_group_bind(
- device->vfio_container_fd, device->iommu_group);
- if (device->vfio_group_fd < 0)
+ ret = rte_vfio_container_assign_device(device->vfio_container_fd,
+ rte_pci_get_sysfs_path(), dev_name);
+ if (ret < 0)
goto container_destroy;
- DRV_VDPA_LOG(DEBUG, "The container_fd=%d, group_fd=%d.",
- device->vfio_container_fd, device->vfio_group_fd);
+ DRV_VDPA_LOG(DEBUG, "container_fd=%d", device->vfio_container_fd);
ret = rte_pci_map_device(pci_dev);
if (ret != 0)
- goto group_unbind;
+ goto container_destroy;
device->vfio_dev_fd = rte_intr_dev_fd_get(pci_dev->intr_handle);
return 0;
-group_unbind:
- rte_vfio_container_group_unbind(device->vfio_container_fd, device->iommu_group);
container_destroy:
rte_vfio_container_destroy(device->vfio_container_fd);
@@ -80,22 +80,12 @@ sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
goto fail_container_create;
}
- rc = rte_vfio_get_group_num(rte_pci_get_sysfs_path(), dev_name,
- &sva->iommu_group_num);
- if (rc <= 0) {
- sfc_vdpa_err(sva, "failed to get IOMMU group for %s : %s",
- dev_name, rte_strerror(-rc));
- goto fail_get_group_num;
- }
-
- sva->vfio_group_fd =
- rte_vfio_container_group_bind(sva->vfio_container_fd,
- sva->iommu_group_num);
- if (sva->vfio_group_fd < 0) {
- sfc_vdpa_err(sva,
- "failed to bind IOMMU group %d to container %d",
- sva->iommu_group_num, sva->vfio_container_fd);
- goto fail_group_bind;
+ rc = rte_vfio_container_assign_device(sva->vfio_container_fd,
+ rte_pci_get_sysfs_path(), dev_name);
+ if (rc < 0) {
+ sfc_vdpa_err(sva, "failed to assign device %s to container %d",
+ dev_name, sva->vfio_container_fd);
+ goto fail_device_assign;
}
if (rte_pci_map_device(dev) != 0) {
@@ -109,15 +99,7 @@ sfc_vdpa_vfio_setup(struct sfc_vdpa_adapter *sva)
return 0;
fail_pci_map_device:
- if (rte_vfio_container_group_unbind(sva->vfio_container_fd,
- sva->iommu_group_num) != 0) {
- sfc_vdpa_err(sva,
- "failed to unbind IOMMU group %d from container %d",
- sva->iommu_group_num, sva->vfio_container_fd);
- }
-
-fail_group_bind:
-fail_get_group_num:
+fail_device_assign:
if (rte_vfio_container_destroy(sva->vfio_container_fd) != 0) {
sfc_vdpa_err(sva, "failed to destroy container %d",
sva->vfio_container_fd);
@@ -132,13 +114,6 @@ sfc_vdpa_vfio_teardown(struct sfc_vdpa_adapter *sva)
{
rte_pci_unmap_device(sva->pdev);
- if (rte_vfio_container_group_unbind(sva->vfio_container_fd,
- sva->iommu_group_num) != 0) {
- sfc_vdpa_err(sva,
- "failed to unbind IOMMU group %d from container %d",
- sva->iommu_group_num, sva->vfio_container_fd);
- }
-
if (rte_vfio_container_destroy(sva->vfio_container_fd) != 0) {
sfc_vdpa_err(sva,
"failed to destroy container %d",
@@ -70,10 +70,8 @@ struct sfc_vdpa_adapter {
sfc_vdpa_filter_t filters;
- int vfio_group_fd;
int vfio_dev_fd;
int vfio_container_fd;
- int iommu_group_num;
struct sfc_vdpa_ops_data *ops_data;
};
@@ -937,3 +937,13 @@ rte_vfio_container_dma_unmap(__rte_unused int container_fd,
rte_errno = ENOTSUP;
return -1;
}
+
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_vfio_container_assign_device, 26.02)
+int
+rte_vfio_container_assign_device(__rte_unused int vfio_container_fd,
+ __rte_unused const char *sysfs_base,
+ __rte_unused const char *dev_addr)
+{
+ rte_errno = ENOTSUP;
+ return -1;
+}
@@ -251,6 +251,33 @@ rte_vfio_container_create(void);
int
rte_vfio_container_destroy(int container_fd);
+/**
+ * @warning
+ * @b EXPERIMENTAL: this API may change without prior notice.
+ *
+ * Assign a device to a VFIO container.
+ *
+ * Doing so will cause `rte_vfio_setup_device()` to set up the device with the VFIO container
+ * specified in this assign operation.
+ *
+ * This function is only relevant on Linux.
+ *
+ * @param vfio_container_fd
+ * VFIO container file descriptor.
+ * @param sysfs_base
+ * Sysfs path prefix.
+ * @param dev_addr
+ * Device identifier.
+ *
+ * @return
+ * 0 on success.
+ * <0 on failure, rte_errno is set.
+ */
+__rte_experimental
+int
+rte_vfio_container_assign_device(int vfio_container_fd, const char *sysfs_base,
+ const char *dev_addr);
+
/**
* Bind a IOMMU group to a container.
*
@@ -2128,6 +2128,38 @@ rte_vfio_container_destroy(int container_fd)
return 0;
}
+RTE_EXPORT_EXPERIMENTAL_SYMBOL(rte_vfio_container_assign_device, 26.02)
+int
+rte_vfio_container_assign_device(int vfio_container_fd, const char *sysfs_base,
+ const char *dev_addr)
+{
+ int iommu_group_num;
+ int ret;
+
+ ret = rte_vfio_get_group_num(sysfs_base, dev_addr, &iommu_group_num);
+ if (ret < 0) {
+ EAL_LOG(ERR, "Cannot get IOMMU group number for device %s",
+ dev_addr);
+ return -1;
+ } else if (ret == 0) {
+ EAL_LOG(ERR,
+ "Device %s is not assigned to any IOMMU group",
+ dev_addr);
+ return -1;
+ }
+
+ ret = rte_vfio_container_group_bind(vfio_container_fd,
+ iommu_group_num);
+ if (ret < 0) {
+ EAL_LOG(ERR,
+ "Cannot bind IOMMU group %d for device %s",
+ iommu_group_num, dev_addr);
+ return -1;
+ }
+
+ return 0;
+}
+
RTE_EXPORT_SYMBOL(rte_vfio_container_group_bind)
int
rte_vfio_container_group_bind(int container_fd, int iommu_group_num)