From 713dd6f44291f078cb249b1a8deb1b5c02c2cd70 Mon Sep 17 00:00:00 2001 From: Carsten Beckmann Date: Wed, 16 Sep 2026 14:54:10 +0200 Subject: [PATCH 2/8] iavf: improve VF reset handling Currently VF resets are detected by checking if a register contains 0xdeadbeef in the admin queue interrupt. The interrupt is triggered because the host driver sends the VF a RESET_IMPENDING event before actually triggering the VF reset. If the interrupt is processed too early or too late the temporary 0xdeadbeef state and therefore the VF reset can be missed. Triggering a reset when a RESET_IMPENDING event arrives fixes this issue. In theory this could now allow the reset task to run before the actual VF reset is triggered by the host. To prevent this the reset task now waits until the arq_len_enable bit goes low which would indicate a VF reset. The same approach is used by the Linux iavf driver. --- sys/dev/pci/if_iavf.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/sys/dev/pci/if_iavf.c b/sys/dev/pci/if_iavf.c index e41396e7873..5a15f80db48 100644 --- a/sys/dev/pci/if_iavf.c +++ b/sys/dev/pci/if_iavf.c @@ -1708,6 +1708,7 @@ iavf_reset(void *xsc) struct iavf_softc *sc = xsc; struct ifnet *ifp = &sc->sc_ac.ac_if; int tries, up, link_state; + uint32_t reg; NET_LOCK(); @@ -1732,7 +1733,20 @@ iavf_reset(void *xsc) sc->sc_got_irq_map = 0; for (tries = 0; tries < 100; tries++) { - uint32_t reg; + reg = iavf_rd(sc, sc->sc_aq_regs->arq_len) & + sc->sc_aq_regs->arq_len_enable; + if (!reg) + break; + + delay(10000); + } + + if (tries == 100) { + printf("%s: did not detect VF reset\n", DEVNAME(sc)); + goto failed; + } + + for (tries = 0; tries < 100; tries++) { reg = iavf_rd(sc, I40E_VFGEN_RSTAT) & I40E_VFGEN_RSTAT_VFR_STATE_MASK; if (reg == IAVF_VFR_VFACTIVE || @@ -2654,7 +2668,11 @@ iavf_process_vc_event(struct iavf_softc *sc, struct iavf_aq_desc *desc, if_link_state_change(ifp); } break; - + case IAVF_VC_EVENT_RESET_IMPENDING: + printf("%s: VF reset impending\n", DEVNAME(sc)); + sc->sc_resetting = 1; + task_add(systq, &sc->sc_reset_task); + break; default: break; } -- 2.53.0