From nobody Sat Jul 25 21:04:26 2026 X-Original-To: dev-commits-src-all@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4h6y686nKmz6m66V for ; Sat, 25 Jul 2026 21:04:32 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "YR1" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4h6y6846YTz3vYc for ; Sat, 25 Jul 2026 21:04:32 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785013472; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nwqyYGVmI1sdLR0kd3+5lJpl0G191Qmg8X83GCj0994=; b=afk/dQhtBFcXvKMZT2IeM2a2EVNX4xfTuvzgD9ztnm5IBIDAhCZpPqD/aW3JFTxJlT6SCI bP4QpEG3ZVN1dM2KF0dSCNXMMYWRNDA+6nuXX9b+/A9cPmg4IDUovspqnjpTURzR7jtCNj hSI36Q33Opx83Utg1KEGn7IpCeRDsvlaSQ+vZHZBrCFDBXrAFeNd3kZZNiHBnAKJlm62EI VOd++yha9KlmVENwh8Ebosn+7nsPyS5WSDOqy5OBT/EF5oFcOS63wp4CFuRNYfO6PzPP6a RMCG4N/nixPFFW/fVp3L4lUQxdrslK1r0FZ4lr2FJefp2yUhzEDUyIGKA+928A== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1785013472; a=rsa-sha256; cv=none; b=dhsRnXJSR+RmdCtHRHJzD1QIQrilf7NqUTv8JWj2rulKncn667mwEMVuUcYjaS1z78FIv+ ji+pzYkB+Fh55jeLPQp8nf/y9u1lEusRpjH4LCO+UxU4SHfw8k1h8aXdfLzfNBKCw9N9SQ zJWsLelBivpzTDw1H5hjEzfHtuHeLtZ+d/W+hdTaBRwZ37ClqzQCP69GTPfH07Lbn2syy8 LBMNncHdnplnhmsJzr9AHe+cP0iJK4M1c0NNsCwV2V4UPCxX1kEI6IC039YbqYO5n1FJk3 Ve+sqvHW8TkE7y7Db0MorxpIfaqq0VN9793LHMNON1j4DL2shJ9YawqzXNLpZQ== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785013472; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=nwqyYGVmI1sdLR0kd3+5lJpl0G191Qmg8X83GCj0994=; b=e7fg7R6G+HIhZ4HntMUsYUnTB38c0jojM6U5d7DRjsPGEyk//HOl6XSehxK7xgoTg6WmU8 VGUkxy/waA452YPufr1KW59HlSLPpfI4OC8cAZ7+aHsAxK5aP7vFAXp9KuRBNMx1AuoPqX lfe6lWFVOHjvXn9uqZnNgyN7Kes3ixxx3TWqh5iV/r4QzXPCf2jLNpqu7EcNzcGDmLG0BT 7i6o8dvrkVdPjyUjbQOR09EXhg7/D93XjiOPDGA46KfB7z/r+YaH8vziQVvF4/ErSSFcby cRVt6aesNm9soIHRCUmUV+sIo9t3sbp9yfIRc1W46ZQSY3THiuepsiHbRXqi5w== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4h6y674w5mzsrH for ; Sat, 25 Jul 2026 21:04:31 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 41983 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sat, 25 Jul 2026 21:04:26 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Kevin Bowling Subject: git: 0bd6a167c156 - main - e1000: Defer link-up notification until after TSO reset List-Id: Commit messages for all branches of the src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-all List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-all@freebsd.org Sender: owner-dev-commits-src-all@FreeBSD.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: kbowling X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 0bd6a167c1561f01c227b1c428a3d8adf0e38833 Auto-Submitted: auto-generated Date: Sat, 25 Jul 2026 21:04:26 +0000 Message-Id: <6a6524da.41983.8c6cef9@gitrepo.freebsd.org> The branch main has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=0bd6a167c1561f01c227b1c428a3d8adf0e38833 commit 0bd6a167c1561f01c227b1c428a3d8adf0e38833 Author: Kevin Bowling AuthorDate: 2026-07-25 21:00:10 +0000 Commit: Kevin Bowling CommitDate: 2026-07-25 21:00:10 +0000 e1000: Defer link-up notification until after TSO reset em_automask_tso() changes the enabled TSO capabilities when the link moves between 10/100 and 1000 Mb/s. A running interface must be reinitialized to apply the new capability set. Do not publish LINK_STATE_UP until the requested iflib reset has completed. Replace link_active with an explicit state machine that distinguishes the physical link, its publication to iflib, and an outstanding reset barrier. Preserve that barrier across a link flap with DOWN_RESET_PENDING, and only publish DOWN if UP was previously published. Only request a reset for a running interface or for an initialization while the interface is administratively up. In other states the next initialization will apply the capability changes, avoiding a reset request that iflib's admin task could discard. Reviewed by: Faraz Vahedi Fixes: 2ddf24f8f525 ("e1000: Automask TSO on lem(4)/em(4) 10/100 Ethernet") MFC after: 1 week --- sys/dev/e1000/if_em.c | 79 +++++++++++++++++++++++++++++++++++++++------------ sys/dev/e1000/if_em.h | 10 ++++++- 2 files changed, 70 insertions(+), 19 deletions(-) diff --git a/sys/dev/e1000/if_em.c b/sys/dev/e1000/if_em.c index 3118b27e8122..5547c4ec8614 100644 --- a/sys/dev/e1000/if_em.c +++ b/sys/dev/e1000/if_em.c @@ -1562,6 +1562,10 @@ em_if_init(if_ctx_t ctx) /* Initialize the hardware */ em_reset(ctx); + /* Re-arm a link-up transition deferred for this reset. */ + if (sc->link_state == EM_LINK_STATE_DOWN_RESET_PENDING || + sc->link_state == EM_LINK_STATE_UP_RESET_PENDING) + sc->link_state = EM_LINK_STATE_DOWN; em_if_update_admin_status(ctx); for (i = 0, tx_que = sc->tx_queues; i < sc->tx_num_queues; @@ -1999,7 +2003,8 @@ em_if_media_status(if_ctx_t ctx, struct ifmediareq *ifmr) ifmr->ifm_status = IFM_AVALID; ifmr->ifm_active = IFM_ETHER; - if (!sc->link_active) { + if (sc->link_state == EM_LINK_STATE_DOWN || + sc->link_state == EM_LINK_STATE_DOWN_RESET_PENDING) { return; } @@ -2219,7 +2224,7 @@ em_if_update_admin_status(if_ctx_t ctx) struct e1000_hw *hw = &sc->hw; device_t dev = iflib_get_dev(ctx); u32 link_check, thstat, ctrl; - bool automasked = false; + bool reset_requested = false; link_check = thstat = ctrl = 0; /* Get the cached link value or read phy for real */ @@ -2262,7 +2267,13 @@ em_if_update_admin_status(if_ctx_t ctx) } /* Now check for a transition */ - if (link_check && (sc->link_active == 0)) { + if (link_check && + (sc->link_state == EM_LINK_STATE_DOWN || + sc->link_state == EM_LINK_STATE_DOWN_RESET_PENDING)) { + bool reset_pending; + + reset_pending = + sc->link_state == EM_LINK_STATE_DOWN_RESET_PENDING; e1000_get_speed_and_duplex(hw, &sc->link_speed, &sc->link_duplex); /* Check if we must disable SPEED_MODE bit on PCI-E */ @@ -2279,7 +2290,7 @@ em_if_update_admin_status(if_ctx_t ctx) sc->link_speed, ((sc->link_duplex == FULL_DUPLEX) ? "Full Duplex" : "Half Duplex")); - sc->link_active = 1; + sc->link_state = EM_LINK_STATE_UP; sc->smartspeed = 0; if ((ctrl & E1000_CTRL_EXT_LINK_MODE_MASK) == E1000_CTRL_EXT_LINK_MODE_GMII && @@ -2299,17 +2310,33 @@ em_if_update_admin_status(if_ctx_t ctx) } /* Only do TSO on gigabit for older chips due to errata */ if (hw->mac.type < igb_mac_min) - automasked = em_automask_tso(ctx); + reset_requested = em_automask_tso(ctx); - /* Automasking resets the interface so don't mark it up yet */ - if (!automasked) + if (reset_pending || reset_requested) { + /* + * The PHY is up, but publish it only after the TSO + * capability-change reset. + */ + sc->link_state = EM_LINK_STATE_UP_RESET_PENDING; + } else { iflib_link_state_change(ctx, LINK_STATE_UP, IF_Mbps(sc->link_speed)); - } else if (!link_check && (sc->link_active == 1)) { + } + } else if (!link_check && + (sc->link_state == EM_LINK_STATE_UP || + sc->link_state == EM_LINK_STATE_UP_RESET_PENDING)) { + bool link_was_published; + bool reset_pending; + + link_was_published = sc->link_state == EM_LINK_STATE_UP; + reset_pending = + sc->link_state == EM_LINK_STATE_UP_RESET_PENDING; sc->link_speed = 0; sc->link_duplex = 0; - sc->link_active = 0; - iflib_link_state_change(ctx, LINK_STATE_DOWN, 0); + sc->link_state = reset_pending ? + EM_LINK_STATE_DOWN_RESET_PENDING : EM_LINK_STATE_DOWN; + if (link_was_published) + iflib_link_state_change(ctx, LINK_STATE_DOWN, 0); } em_update_stats_counters(sc); @@ -2758,7 +2785,9 @@ lem_smartspeed(struct e1000_softc *sc) { u16 phy_tmp; - if (sc->link_active || (sc->hw.phy.type != e1000_phy_igp) || + if (sc->link_state == EM_LINK_STATE_UP || + sc->link_state == EM_LINK_STATE_UP_RESET_PENDING || + (sc->hw.phy.type != e1000_phy_igp) || sc->hw.mac.autoneg == 0 || (sc->hw.phy.autoneg_advertised & ADVERTISE_1000_FULL) == 0) return; @@ -4342,6 +4371,8 @@ em_automask_tso(if_ctx_t ctx) struct e1000_softc *sc = iflib_get_softc(ctx); if_softc_ctx_t scctx = iflib_get_softc_ctx(ctx); if_t ifp = iflib_get_ifp(ctx); + bool reset_needed; + int drvflags; if (!em_unsupported_tso && sc->link_speed && sc->link_speed != SPEED_1000 && @@ -4351,20 +4382,32 @@ em_automask_tso(if_ctx_t ctx) sc->tso_automasked = scctx->isc_capenable & IFCAP_TSO; scctx->isc_capenable &= ~IFCAP_TSO; if_setcapenablebit(ifp, 0, IFCAP_TSO); - /* iflib_init_locked handles ifnet hwassistbits */ - iflib_request_reset(ctx); - return true; } else if (sc->link_speed == SPEED_1000 && sc->tso_automasked) { device_printf(sc->dev, "Re-enabling TSO for GbE.\n"); scctx->isc_capenable |= sc->tso_automasked; if_setcapenablebit(ifp, sc->tso_automasked, 0); sc->tso_automasked = 0; - /* iflib_init_locked handles ifnet hwassistbits */ - iflib_request_reset(ctx); - return true; + } else { + return (false); } - return false; + /* + * Reset a running interface, or one being initialized while + * administratively up. OACTIVE remains set after iflib_stop(), so + * it alone cannot distinguish initialization from an interface that + * is down. In other states, the next initialization will apply the + * updated capabilities. + */ + drvflags = if_getdrvflags(ifp); + reset_needed = (drvflags & IFF_DRV_RUNNING) != 0 || + ((drvflags & IFF_DRV_OACTIVE) != 0 && + (if_getflags(ifp) & IFF_UP) != 0); + if (!reset_needed) + return (false); + + /* iflib_init_locked handles ifnet hwassistbits */ + iflib_request_reset(ctx); + return (true); } /* diff --git a/sys/dev/e1000/if_em.h b/sys/dev/e1000/if_em.h index 4c80c7696952..56c28597fa22 100644 --- a/sys/dev/e1000/if_em.h +++ b/sys/dev/e1000/if_em.h @@ -469,6 +469,14 @@ struct em_rx_queue { struct if_irq que_irq; }; +/* Driver-observed link state and its publication barrier. */ +enum em_link_state { + EM_LINK_STATE_DOWN = 0, + EM_LINK_STATE_DOWN_RESET_PENDING, + EM_LINK_STATE_UP, + EM_LINK_STATE_UP_RESET_PENDING, +}; + /* Our softc structure */ struct e1000_softc { struct e1000_hw hw; @@ -530,7 +538,7 @@ struct e1000_softc { u32 shadow_vfta[EM_VFTA_SIZE]; /* Info about the interface */ - u16 link_active; + enum em_link_state link_state; u16 fc; u16 link_speed; u16 link_duplex;