To support INTx enabling for multiple times, we need firstly to extract one-time initialisation and move the related code into a new function vfio_pci_init_intx(); if later disable and re-enable the INTx, we can skip these one-time operations. This patch move below three main operations for INTx one-time initialisation from function vfio_pci_enable_intx() into function vfio_pci_init_intx(): - Reserve 2 FDs for INTx; - Sanity check with ioctl VFIO_DEVICE_GET_IRQ_INFO; - Setup pdev->intx_gsi. Suggested-by: Jean-Philippe Brucker <jean-philippe.brucker@xxxxxxx> Signed-off-by: Leo Yan <leo.yan@xxxxxxxxxx> Reviewed-by: Jean-Philippe Brucker <jean-philippe.brucker@xxxxxxx> --- vfio/pci.c | 67 ++++++++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/vfio/pci.c b/vfio/pci.c index 5224fee..3c39844 100644 --- a/vfio/pci.c +++ b/vfio/pci.c @@ -1018,30 +1018,7 @@ static int vfio_pci_enable_intx(struct kvm *kvm, struct vfio_device *vdev) struct vfio_irq_eventfd trigger; struct vfio_irq_eventfd unmask; struct vfio_pci_device *pdev = &vdev->pci; - int gsi = pdev->hdr.irq_line - KVM_IRQ_OFFSET; - - struct vfio_irq_info irq_info = { - .argsz = sizeof(irq_info), - .index = VFIO_PCI_INTX_IRQ_INDEX, - }; - - vfio_pci_reserve_irq_fds(2); - - ret = ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info); - if (ret || irq_info.count == 0) { - vfio_dev_err(vdev, "no INTx reported by VFIO"); - return -ENODEV; - } - - if (!(irq_info.flags & VFIO_IRQ_INFO_EVENTFD)) { - vfio_dev_err(vdev, "interrupt not eventfd capable"); - return -EINVAL; - } - - if (!(irq_info.flags & VFIO_IRQ_INFO_AUTOMASKED)) { - vfio_dev_err(vdev, "INTx interrupt not AUTOMASKED"); - return -EINVAL; - } + int gsi = pdev->intx_gsi; /* * PCI IRQ is level-triggered, so we use two eventfds. trigger_fd @@ -1097,8 +1074,6 @@ static int vfio_pci_enable_intx(struct kvm *kvm, struct vfio_device *vdev) pdev->intx_fd = trigger_fd; pdev->unmask_fd = unmask_fd; - /* Guest is going to ovewrite our irq_line... */ - pdev->intx_gsi = gsi; return 0; @@ -1117,6 +1092,39 @@ err_close: return ret; } +static int vfio_pci_init_intx(struct kvm *kvm, struct vfio_device *vdev) +{ + int ret; + struct vfio_pci_device *pdev = &vdev->pci; + struct vfio_irq_info irq_info = { + .argsz = sizeof(irq_info), + .index = VFIO_PCI_INTX_IRQ_INDEX, + }; + + vfio_pci_reserve_irq_fds(2); + + ret = ioctl(vdev->fd, VFIO_DEVICE_GET_IRQ_INFO, &irq_info); + if (ret || irq_info.count == 0) { + vfio_dev_err(vdev, "no INTx reported by VFIO"); + return -ENODEV; + } + + if (!(irq_info.flags & VFIO_IRQ_INFO_EVENTFD)) { + vfio_dev_err(vdev, "interrupt not eventfd capable"); + return -EINVAL; + } + + if (!(irq_info.flags & VFIO_IRQ_INFO_AUTOMASKED)) { + vfio_dev_err(vdev, "INTx interrupt not AUTOMASKED"); + return -EINVAL; + } + + /* Guest is going to ovewrite our irq_line... */ + pdev->intx_gsi = pdev->hdr.irq_line - KVM_IRQ_OFFSET; + + return 0; +} + static int vfio_pci_configure_dev_irqs(struct kvm *kvm, struct vfio_device *vdev) { int ret = 0; @@ -1142,8 +1150,13 @@ static int vfio_pci_configure_dev_irqs(struct kvm *kvm, struct vfio_device *vdev return ret; } - if (pdev->irq_modes & VFIO_PCI_IRQ_MODE_INTX) + if (pdev->irq_modes & VFIO_PCI_IRQ_MODE_INTX) { + ret = vfio_pci_init_intx(kvm, vdev); + if (ret) + return ret; + ret = vfio_pci_enable_intx(kvm, vdev); + } return ret; } -- 2.19.1