After restoring VFRE/VFTE on the destination, the VF's RX rings may
be stalled because the guest driver is waiting for an interrupt that
was pending at the time of migration. Re-raise any pending EICR
causes for the VF (both RX and TX) via igb_set_eics() to break the
deadlock.

AI-used-for: analysis, code (prototype)
Signed-off-by: Cédric Le Goater <[email protected]>
---
 hw/net/igb_core.h      |  1 +
 hw/net/igb_core.c      | 16 ++++++++++++++++
 hw/net/igb_migration.c |  4 ++--
 3 files changed, 19 insertions(+), 2 deletions(-)

diff --git a/hw/net/igb_core.h b/hw/net/igb_core.h
index 7fdc41690b36..7d6f44b7ffe9 100644
--- a/hw/net/igb_core.h
+++ b/hw/net/igb_core.h
@@ -150,6 +150,7 @@ igb_start_recv(IGBCore *core);
 IGBCore *igb_pf_get_core(void *pf);
 
 void igb_core_vf_propagate_irqs(IGBCore *core, uint16_t vfn);
+void igb_core_vf_rearm_irqs(IGBCore *core, uint16_t vfn);
 void igb_core_vf_propagate_ivar(IGBCore *core, uint16_t vfn);
 
 #endif
diff --git a/hw/net/igb_core.c b/hw/net/igb_core.c
index 12329a1aff58..1de8d95102e4 100644
--- a/hw/net/igb_core.c
+++ b/hw/net/igb_core.c
@@ -4632,3 +4632,19 @@ void igb_core_vf_propagate_ivar(IGBCore *core, uint16_t 
vfn)
         core->mac[IVAR0 + n / 4] &= ~mask;
     }
 }
+
+/*
+ * Re-apply VF interrupt enables to PF aggregates and raise the
+ * pending causes so the guest driver resumes polling after migration.
+ */
+void igb_core_vf_rearm_irqs(IGBCore *core, uint16_t vfn)
+{
+    uint32_t shift = 22 - vfn * IGBVF_MSIX_VEC_NUM;
+    uint32_t pvt_idx = PVTEICR0 + vfn * 0x40;
+    uint32_t causes = (core->mac[pvt_idx] & 0x7) << shift;
+
+    igb_core_vf_propagate_irqs(core, vfn);
+    if (causes) {
+        igb_set_eics(core, EICS, causes);
+    }
+}
diff --git a/hw/net/igb_migration.c b/hw/net/igb_migration.c
index 435bd0d1623b..46299ff77ab9 100644
--- a/hw/net/igb_migration.c
+++ b/hw/net/igb_migration.c
@@ -813,8 +813,8 @@ static void igb_core_vf_unquiesce(IgbVfState *s)
 
     trace_igbvf_mig_unquiesce(s->vfn, core->mac[VFRE], core->mac[VFTE]);
 
-    if (re) {
-        igb_start_recv(core);
+    if (re || te) {
+        igb_core_vf_rearm_irqs(core, s->vfn);
     }
 }
 
-- 
2.55.0


Reply via email to