After migration, the VF unquiesce path calls igb_start_recv() to kick
RX processing. This does not trigger an interrupt, so NAPI stays idle
and the RX ring is never replenished.

Replace igb_start_recv() with igb_core_vf_rearm_irqs(): re-apply the
VF's PVT shadow register into the PF aggregates, then raise interrupt
causes via igb_set_eics(). This follows the normal EICR -> EIMS ->
MSI-X routing. NAPI wakes, replenishes the ring via
igbvf_alloc_rx_buffers(), and writes RDT - breaking the deadlock.

The PVT re-application is needed because the L1 PF driver's normal
interrupt handling may have cleared EIMS between state load and
unquiesce.

Assisted-by: Claude
Signed-off-by: Cédric Le Goater <[email protected]>
---
 hw/net/igb_core.h      |  1 +
 hw/net/igb_core.c      | 12 ++++++++++++
 hw/net/igb_migration.c |  2 +-
 3 files changed, 14 insertions(+), 1 deletion(-)

diff --git a/hw/net/igb_core.h b/hw/net/igb_core.h
index 50cee2c7683c..3db520048732 100644
--- a/hw/net/igb_core.h
+++ b/hw/net/igb_core.h
@@ -147,5 +147,6 @@ 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 03c349575c0a..1621ee6602d5 100644
--- a/hw/net/igb_core.c
+++ b/hw/net/igb_core.c
@@ -4589,6 +4589,18 @@ void igb_core_vf_propagate_irqs(IGBCore *core, uint16_t 
vfn)
     core->mac[EICR] &= ~(0x7 << shift);
 }
 
+/*
+ * Re-apply VF interrupt enables to PF aggregates and raise interrupt
+ * causes to wake NAPI so it replenishes the ring after migration.
+ */
+void igb_core_vf_rearm_irqs(IGBCore *core, uint16_t vfn)
+{
+    uint32_t shift = 22 - vfn * IGBVF_MSIX_VEC_NUM;
+
+    igb_core_vf_propagate_irqs(core, vfn);
+    igb_set_eics(core, EICS, 0x7 << shift);
+}
+
 /*
  * Re-apply VTIVAR -> IVAR0 interrupt routing. The L1 PF driver
  * may have overwritten the shared IVAR0 entries with its own
diff --git a/hw/net/igb_migration.c b/hw/net/igb_migration.c
index 187077c14c48..a0b4a52c865f 100644
--- a/hw/net/igb_migration.c
+++ b/hw/net/igb_migration.c
@@ -630,7 +630,7 @@ 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);
+        igb_core_vf_rearm_irqs(core, s->vfn);
     }
 }
 
-- 
2.55.0


Reply via email to