[v5] bus/pci: fix legacy device IO port map in secondary process
Checks
Commit Message
When doing IO port mapping for legacy device in secondary process, the
region information is missing, so, we need to refill it.
Fixes: 4b741542ecde ("bus/pci: avoid depending on private kernel value")
Cc: stable@dpdk.org
Signed-off-by: Wenwu Ma <wenwux.ma@intel.com>
---
v5:
- adding checks to vfio setup
v4:
- adjusting commit log
v3:
- adjusting variable settings
v2:
- add release of device in pci_vfio_ioport_unmap
---
drivers/bus/pci/linux/pci_vfio.c | 52 ++++++++++++++++++++++++++++++--
1 file changed, 50 insertions(+), 2 deletions(-)
Comments
On 10/24/2023 7:30 AM, Wenwu Ma wrote:
> When doing IO port mapping for legacy device in secondary process, the
> region information is missing, so, we need to refill it.
>
> Fixes: 4b741542ecde ("bus/pci: avoid depending on private kernel value")
> Cc: stable@dpdk.org
>
> Signed-off-by: Wenwu Ma <wenwux.ma@intel.com>
> ---
> v5:
> - adding checks to vfio setup
> v4:
> - adjusting commit log
> v3:
> - adjusting variable settings
> v2:
> - add release of device in pci_vfio_ioport_unmap
>
> ---
> drivers/bus/pci/linux/pci_vfio.c | 52 ++++++++++++++++++++++++++++++--
> 1 file changed, 50 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/bus/pci/linux/pci_vfio.c b/drivers/bus/pci/linux/pci_vfio.c
> index 3f3201daf2..a1f7cc2421 100644
> --- a/drivers/bus/pci/linux/pci_vfio.c
> +++ b/drivers/bus/pci/linux/pci_vfio.c
> @@ -1230,6 +1230,36 @@ pci_vfio_ioport_map(struct rte_pci_device *dev, int bar,
> return -1;
> }
>
> + if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
> + struct vfio_device_info device_info = { .argsz = sizeof(device_info) };
> + char pci_addr[PATH_MAX];
> + int vfio_dev_fd;
> + struct rte_pci_addr *loc = &dev->addr;
> + /* store PCI address string */
> + snprintf(pci_addr, sizeof(pci_addr), PCI_PRI_FMT,
> + loc->domain, loc->bus, loc->devid, loc->function);
> +
> + vfio_dev_fd = rte_intr_dev_fd_get(dev->intr_handle);
> + if (vfio_dev_fd < 0)
> + return -1;
> +
> + if (vfio_dev_fd == 0) {
> + if (rte_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
> + &vfio_dev_fd, &device_info))
> + return -1;
> +
> + /* we need save vfio_dev_fd, so it can be used during release */
> + if (rte_intr_dev_fd_set(dev->intr_handle, vfio_dev_fd))
> + return -1;
> + } else {
> + if (ioctl(vfio_dev_fd, VFIO_DEVICE_GET_INFO, &device_info))
> + return -1;
> + }
Code upto here is to get device info, IMO we should have a separate API
for this in VFIO layer which can be used from any driver, rather than
being limited here.
This can go into a new API like rte_vfio_get_device_info() in eal_vfio.c.
Thanks,
Nipun
@@ -1230,6 +1230,36 @@ pci_vfio_ioport_map(struct rte_pci_device *dev, int bar,
return -1;
}
+ if (rte_eal_process_type() == RTE_PROC_SECONDARY) {
+ struct vfio_device_info device_info = { .argsz = sizeof(device_info) };
+ char pci_addr[PATH_MAX];
+ int vfio_dev_fd;
+ struct rte_pci_addr *loc = &dev->addr;
+ /* store PCI address string */
+ snprintf(pci_addr, sizeof(pci_addr), PCI_PRI_FMT,
+ loc->domain, loc->bus, loc->devid, loc->function);
+
+ vfio_dev_fd = rte_intr_dev_fd_get(dev->intr_handle);
+ if (vfio_dev_fd < 0)
+ return -1;
+
+ if (vfio_dev_fd == 0) {
+ if (rte_vfio_setup_device(rte_pci_get_sysfs_path(), pci_addr,
+ &vfio_dev_fd, &device_info))
+ return -1;
+
+ /* we need save vfio_dev_fd, so it can be used during release */
+ if (rte_intr_dev_fd_set(dev->intr_handle, vfio_dev_fd))
+ return -1;
+ } else {
+ if (ioctl(vfio_dev_fd, VFIO_DEVICE_GET_INFO, &device_info))
+ return -1;
+ }
+
+ if (pci_vfio_fill_regions(dev, vfio_dev_fd, &device_info))
+ return -1;
+ }
+
if (pci_vfio_get_region(dev, bar, &size, &offset) != 0) {
RTE_LOG(ERR, EAL, "Cannot get offset of region %d.\n", bar);
return -1;
@@ -1277,8 +1307,26 @@ pci_vfio_ioport_write(struct rte_pci_ioport *p,
int
pci_vfio_ioport_unmap(struct rte_pci_ioport *p)
{
- RTE_SET_USED(p);
- return -1;
+ char pci_addr[PATH_MAX] = {0};
+ struct rte_pci_addr *loc = &p->dev->addr;
+ int ret, vfio_dev_fd;
+
+ /* store PCI address string */
+ snprintf(pci_addr, sizeof(pci_addr), PCI_PRI_FMT,
+ loc->domain, loc->bus, loc->devid, loc->function);
+
+ vfio_dev_fd = rte_intr_dev_fd_get(p->dev->intr_handle);
+ if (vfio_dev_fd < 0)
+ return -1;
+
+ ret = rte_vfio_release_device(rte_pci_get_sysfs_path(), pci_addr,
+ vfio_dev_fd);
+ if (ret < 0) {
+ RTE_LOG(ERR, EAL, "Cannot release VFIO device\n");
+ return ret;
+ }
+
+ return 0;
}
int