On 11/9/22 00:13, John Johnson wrote:
Server holds device current device pending state
Use irq masking commands in socket case
Signed-off-by: John G Johnson
Signed-off-by: Elena Ufimtseva
Signed-off-by: Jagannathan Raman
May be use 'can_mask_irq' instead of 'irq_mask_works'
Reviewed-by: Cédric Le Goater
Thanks,
C.
One typo below,
---
hw/vfio/ccw.c | 1 +
hw/vfio/common.c | 26 +
hw/vfio/pci.c | 87 ++-
hw/vfio/pci.h | 1 +
hw/vfio/platform.c| 1 +
include/hw/vfio/vfio-common.h | 3 ++
6 files changed, 118 insertions(+), 1 deletion(-)
diff --git a/hw/vfio/ccw.c b/hw/vfio/ccw.c
index cbd1c25..830ca53 100644
--- a/hw/vfio/ccw.c
+++ b/hw/vfio/ccw.c
@@ -615,6 +615,7 @@ static void vfio_ccw_get_device(VFIOGroup *group,
VFIOCCWDevice *vcdev,
vcdev->vdev.name = name;
vcdev->vdev.dev = >cdev.parent_obj.parent_obj;
vcdev->vdev.io_ops = _dev_io_ioctl;
+vcdev->vdev.irq_mask_works = false;
return;
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index 87cd1d1..b540195 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -101,6 +101,32 @@ void vfio_mask_single_irqindex(VFIODevice *vbasedev, int
index)
VDEV_SET_IRQS(vbasedev, _set);
}
+void vfio_mask_single_irq(VFIODevice *vbasedev, int index, int irq)
+{
+struct vfio_irq_set irq_set = {
+.argsz = sizeof(irq_set),
+.flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_MASK,
+.index = index,
+.start = irq,
+.count = 1,
+};
+
+VDEV_SET_IRQS(vbasedev, _set);
+}
+
+void vfio_unmask_single_irq(VFIODevice *vbasedev, int index, int irq)
+{
+struct vfio_irq_set irq_set = {
+.argsz = sizeof(irq_set),
+.flags = VFIO_IRQ_SET_DATA_NONE | VFIO_IRQ_SET_ACTION_UNMASK,
+.index = index,
+.start = irq,
+.count = 1,
+};
+
+VDEV_SET_IRQS(vbasedev, _set);
+}
+
static inline const char *action_to_str(int action)
{
switch (action) {
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index be39a4e..a1ae3fb 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -479,6 +479,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev,
unsigned int nr,
{
VFIOPCIDevice *vdev = VFIO_PCI_BASE(pdev);
VFIOMSIVector *vector;
+bool new_vec = false;
int ret;
trace_vfio_msix_vector_do_use(vdev->vbasedev.name, nr);
@@ -492,6 +493,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev,
unsigned int nr,
error_report("vfio: Error: event_notifier_init failed");
}
vector->use = true;
+new_vec = true;
msix_vector_use(pdev, nr);
}
@@ -518,6 +520,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
kvm_irqchip_commit_route_changes(_route_change);
vfio_connect_kvm_msi_virq(vector);
}
+new_vec = true;
}
}
@@ -525,6 +528,8 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
* We don't want to have the host allocate all possible MSI vectors
* for a device if they're not in use, so we shutdown and incrementally
* increase them as needed.
+ * Otherwise, unmask the vector if the vector is already setup (and we can
+ * do so) or send the fd if not.
*/
if (vdev->nr_vectors < nr + 1) {
vdev->nr_vectors = nr + 1;
@@ -535,6 +540,8 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev,
unsigned int nr,
error_report("vfio: failed to enable vectors, %d", ret);
}
}
+} else if (vdev->vbasedev.irq_mask_works && !new_vec) {
+vfio_unmask_single_irq(>vbasedev, VFIO_PCI_MSIX_IRQ_INDEX, nr);
} else {
Error *err = NULL;
int32_t fd;
@@ -576,6 +583,12 @@ static void vfio_msix_vector_release(PCIDevice *pdev,
unsigned int nr)
trace_vfio_msix_vector_release(vdev->vbasedev.name, nr);
+/* just mask vector if peer supports it */
+if (vdev->vbasedev.irq_mask_works) {
+vfio_mask_single_irq(>vbasedev, VFIO_PCI_MSIX_IRQ_INDEX, nr);
+return;
+}
+
/*
* There are still old guests that mask and unmask vectors on every
* interrupt. If we're using QEMU bypass with a KVM irqfd, leave all of
@@ -646,7 +659,7 @@ static void vfio_msix_enable(VFIOPCIDevice *vdev)
if (ret) {
error_report("vfio: failed to enable vectors, %d", ret);
}
-} else {
+} else if (!vdev->vbasedev.irq_mask_works) {
/*
* Some communication channels between VF & PF or PF & fw rely on the
* physical state of the device and expect that enabling MSI-X from
the
@@ -662,6 +675,13 @@ static void vfio_msix_enable(VFIOPCIDevice *vdev)
*/
vfio_msix_vector_do_use(>pdev, 0, NULL, NULL);