git: 877f0ee40c2a - main - ixgbe: Preserve VF jumbo frame size across PF resets

From: Kevin Bowling <kbowling_at_FreeBSD.org>
Date: Mon, 10 Aug 2026 16:33:20 UTC
The branch main has been updated by kbowling:

URL: https://cgit.FreeBSD.org/src/commit/?id=877f0ee40c2af801c5ca758a37b3ebddc560dad2

commit 877f0ee40c2af801c5ca758a37b3ebddc560dad2
Author:     Kevin Bowling <kbowling@FreeBSD.org>
AuthorDate: 2026-08-10 15:08:49 +0000
Commit:     Kevin Bowling <kbowling@FreeBSD.org>
CommitDate: 2026-08-10 16:33:12 +0000

    ixgbe: Preserve VF jumbo frame size across PF resets
    
    sc->max_frame_size represents the largest frame requested by the PF or
    an active VF.  The MTU callback replaces it with the PF frame size, so
    a subsequent reinitialization can program MHADD below an active VF's
    jumbo-frame request.
    
    Recompute the aggregate before hardware initialization and use it when
    programming MHADD.  Recompute after each VF LPE request as well, so a
    reduced request can lower the hardware limit when no other function
    needs the previous value.
    
    MFC after:      2 weeks
---
 sys/dev/ixgbe/if_ix.c    | 6 +++++-
 sys/dev/ixgbe/if_sriov.c | 7 ++++---
 2 files changed, 9 insertions(+), 4 deletions(-)

diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c
index cd8acf6685a8..252ae352829e 100644
--- a/sys/dev/ixgbe/if_ix.c
+++ b/sys/dev/ixgbe/if_ix.c
@@ -3973,6 +3973,10 @@ ixgbe_if_init(if_ctx_t ctx)
 
 	INIT_DEBUGOUT("ixgbe_if_init: begin");
 
+	/* Preserve the largest frame requested by the PF or an active VF. */
+	sc->max_frame_size = if_getmtu(ifp) + IXGBE_MTU_HDR;
+	ixgbe_recalculate_max_frame(sc);
+
 	/* Queue indices may change with IOV mode */
 	ixgbe_align_all_queue_indices(sc);
 
@@ -4010,7 +4014,7 @@ ixgbe_if_init(if_ctx_t ctx)
 	ixgbe_config_gpie(sc);
 
 	/* Set MTU size */
-	if (if_getmtu(ifp) > ETHERMTU) {
+	if (sc->max_frame_size > ETHER_MAX_LEN) {
 		/* aka IXGBE_MAXFRS on 82599 and newer */
 		mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
 		mhadd &= ~IXGBE_MHADD_MFS_MASK;
diff --git a/sys/dev/ixgbe/if_sriov.c b/sys/dev/ixgbe/if_sriov.c
index 93555d11e72e..4ca61d078c8e 100644
--- a/sys/dev/ixgbe/if_sriov.c
+++ b/sys/dev/ixgbe/if_sriov.c
@@ -1150,7 +1150,7 @@ ixgbe_vf_set_lpe(struct ixgbe_softc *sc, struct ixgbe_vf *vf, uint32_t *msg)
 	}
 
 	vf->maximum_frame_size = vf_max_size;
-	ixgbe_update_max_frame(sc, vf->maximum_frame_size);
+	ixgbe_recalculate_max_frame(sc);
 
 	/*
 	 * We might have to disable reception to this VF if the frame size is
@@ -1161,7 +1161,7 @@ ixgbe_vf_set_lpe(struct ixgbe_softc *sc, struct ixgbe_vf *vf, uint32_t *msg)
 	mhadd = IXGBE_READ_REG(hw, IXGBE_MHADD);
 	pf_max_size = (mhadd & IXGBE_MHADD_MFS_MASK) >> IXGBE_MHADD_MFS_SHIFT;
 
-	if (pf_max_size < sc->max_frame_size) {
+	if (pf_max_size != sc->max_frame_size) {
 		mhadd &= ~IXGBE_MHADD_MFS_MASK;
 		mhadd |= sc->max_frame_size << IXGBE_MHADD_MFS_SHIFT;
 		IXGBE_WRITE_REG(hw, IXGBE_MHADD, mhadd);
@@ -2107,12 +2107,13 @@ ixgbe_activate_vfs(struct ixgbe_softc *sc)
 } /* ixgbe_activate_vfs */
 
 
-/* Check the max frame setting of all active VF's */
+/* Recompute the maximum frame setting of the PF and all active VFs. */
 void
 ixgbe_recalculate_max_frame(struct ixgbe_softc *sc)
 {
 	struct ixgbe_vf *vf;
 
+	sc->max_frame_size = if_getmtu(iflib_get_ifp(sc->ctx)) + IXGBE_MTU_HDR;
 	for (int i = 0; i < sc->num_vfs; i++) {
 		vf = &sc->vfs[i];
 		if (vf->flags & IXGBE_VF_ACTIVE)