diff options
| author | Kevin Bowling <kbowling@FreeBSD.org> | 2026-07-28 11:26:28 +0000 |
|---|---|---|
| committer | Kevin Bowling <kbowling@FreeBSD.org> | 2026-07-31 12:14:36 +0000 |
| commit | 6f940ca879cbf691ddf5605d852770cef27847b2 (patch) | |
| tree | 5758ebef75904c72ed7d24f1688161cc516ddf8e | |
| parent | 9cf1aa6e68e4b9dd4a77c67b7b902b9221198e7a (diff) | |
ixgbe: clear VF head write-back state on reset
VF reset and FLR do not clear the transmit head write-back address
registers. A previous VF driver can therefore leave DMA write-back
enabled with a stale address for the next driver instance.
After consuming the reset request and disabling the VF queues, clear the
address registers for each queue belonging to that VF. Derive the queue
count from the active IOV mode so peer queue state is not touched.
Linux commit dbf231af81a7 documents the hardware behavior. The FreeBSD
implementation follows the local queue mapping and register interfaces.
MFC after: 1 week
| -rw-r--r-- | sys/dev/ixgbe/if_sriov.c | 13 |
1 files changed, 13 insertions, 0 deletions
diff --git a/sys/dev/ixgbe/if_sriov.c b/sys/dev/ixgbe/if_sriov.c index 8d4e20fcf8bf..b9e5205cf1b9 100644 --- a/sys/dev/ixgbe/if_sriov.c +++ b/sys/dev/ixgbe/if_sriov.c @@ -353,6 +353,7 @@ ixgbe_vf_reset_msg(struct ixgbe_softc *sc, struct ixgbe_vf *vf, uint32_t *msg) struct ixgbe_hw *hw; uint32_t ack; uint32_t resp[IXGBE_VF_PERMADDR_MSG_LEN]; + int i, queue_count; hw = &sc->hw; @@ -363,6 +364,18 @@ ixgbe_vf_reset_msg(struct ixgbe_softc *sc, struct ixgbe_vf *vf, uint32_t *msg) */ ixgbe_clear_mbx(hw, vf->pool); + /* + * VF reset does not clear the transmit head write-back addresses. + * The queues were disabled by ixgbe_process_vf_reset(). + */ + queue_count = ixgbe_vf_queues(sc->iov_mode); + for (i = 0; i < queue_count; i++) { + IXGBE_WRITE_REG(hw, + IXGBE_PVFTDWBAHn(queue_count, vf->pool, i), 0); + IXGBE_WRITE_REG(hw, + IXGBE_PVFTDWBALn(queue_count, vf->pool, i), 0); + } + if (ixgbe_validate_mac_addr(vf->ether_addr) == 0) { ixgbe_set_rar(&sc->hw, vf->rar_index, vf->ether_addr, vf->pool, true); |
