From nobody Sun Aug 2 23:10:36 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 4hCwWx1B2Xz6mZ5S for ; Sun, 02 Aug 2026 23:10:37 +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 4hCwWw5sPcz48vB for ; Sun, 02 Aug 2026 23:10:36 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1785712236; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Kr14P34lWTFD4qd2XAFKPXzrQinC3I6lZ1OlIbv43ag=; b=gZtV6HiSaAj5seuQAhF6tV/TRAhXftWVhrkc8MeP9hA7y3Q4O+EDEwQNy5T0K5ojOGTjEM 84X7p4g4wi6V3ahOooUltowAspfFlQgCzfcWTgUoqBQrUDtUvB1Pk9ilAZHZYUCQKPLIsp maAkug/wh1dEDyEj+vW93ukeKpjrSq54fN691h6inqYJE20zy8M7WomzNE6c+zcDzo+68X S4lKSOPbccO+Xeyw/hQgvlBex1OgrXwi54/3us8v+b4yw8a25PoPmkwDpGpwK6fkhTxwwp I48uG3GTOwP2NTY34wuudns2GDZ+IiQRjQGvGj3vfPUmmps+oTSF8LA8xgMTcg== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1785712236; a=rsa-sha256; cv=none; b=HS8h9T7IAC8lB9nzdEdn+0c/QF/XX7ppbFokPoaAHc0KGiu45S032piNV0khcM1SR33njX fO+ubpLiGKjAuhwlEtET+Aame5mBs1tOHGGg7nmzbnjy2koczGrRS5W+BlTg2bCgaGVR+Y POtOpShpd+x/vYY+M6JAuY53hoWxFuF9fl/Lk9WkEyjgrG6uHPEJnlZoyBUyvTUakH/qF9 0GwOOmB0b9LOgEByjfLSQiat1h2Px1LUnjsaZNvSq8Rfp2RfWlgMdpz66PPviEFxy2auc2 rkt+awcqhnRcPZ2G2TfsFxrogHjIw1SaYLs4LOmQkzczk1MnHTd55Ly+avSgEQ== 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=1785712236; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=Kr14P34lWTFD4qd2XAFKPXzrQinC3I6lZ1OlIbv43ag=; b=phuqTabME+rIheoKthglltPwiQ/1az+v/sQFGw2f9tg1Sw4Qr0bjU/kA5XL26lGOXF5b+q I8ZA3182J7LqnnYjcHbV1GuAFUHGl4XrbkF1z+oHP6ex2SKO2WiHTxLP8MK38aSSvkWNqN uPGxDBoTyTXpkxLJlZ+7y5TxPxOCtuKyMS1o9PWlYfwzi8Aplt9qM4YJEQxyNEVVzLG4Ou qbO0EbvRgI3/r5sxAupowudyl5eknnbrTa7hgl2eT0XNvGq5VseN+beOgdwno4Wl7RpMYU WHyn0JgA09lyq6Zl+/0R1HI8WuSBQNC3NZaiJ7Ctr+2K9GgLLpCAs39CWhleiA== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hCwWw4Z4WzbqM for ; Sun, 02 Aug 2026 23:10:36 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 43579 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sun, 02 Aug 2026 23:10:36 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org Cc: Nick Price From: Adrian Chadd Subject: git: c956cc0f033a - main - aq(4): interface lifecycle and link-state fixes 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: adrian X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: c956cc0f033a4050fbca4e39fdace7276a588e15 Auto-Submitted: auto-generated Date: Sun, 02 Aug 2026 23:10:36 +0000 Message-Id: <6a6fce6c.43579.744d2b5c@gitrepo.freebsd.org> The branch main has been updated by adrian: URL: https://cgit.FreeBSD.org/src/commit/?id=c956cc0f033a4050fbca4e39fdace7276a588e15 commit c956cc0f033a4050fbca4e39fdace7276a588e15 Author: Nick Price AuthorDate: 2026-08-02 22:45:03 +0000 Commit: Adrian Chadd CommitDate: 2026-08-02 22:45:03 +0000 aq(4): interface lifecycle and link-state fixes aq_if_init() programmed the address captured at attach, so an address set with "ifconfig ether" or by lagg(4) enslavement was never written to unicast filter slot 0: the interface transmitted with the new address but the MAC still filtered on the old one, so it received nothing. Copy the current if_getlladdr() the way the other iflib drivers do. The link state could latch UP forever. aq_if_stop() cleared linkup before calling aq_if_update_admin_status(), which suppressed the LINK_STATE_DOWN transition the "link was UP" branch would have made. Announce the down transition directly from aq_if_stop() instead, and do not poll the admin status there at all: the MAC has just been reset, so a stale link reading would re-announce the link as up. The admin task itself had to stop reporting a link on a stopped interface. iflib runs it while either IFF_DRV_RUNNING or IFF_DRV_OACTIVE is set, and iflib_stop() sets OACTIVE, so the task kept polling after the stop and re-announced LINK_STATE_UP behind the driver's back. Treat a non-running interface as having no link. A lagg(4) parent otherwise keeps hashing flows onto a port whose carrier is gone, because LAGG_PORTACTIVE tests if_link_state together with IFF_UP. Stop the rest of the task there as well: the PHY thermal poll and the initialization retry both end in iflib_request_reset(), and _task_fn_admin() acts on that with no test of its own, so either could re-initialize an interface the operator had just taken down. aq_if_update_admin_status() also only reacted to transitions in and out of zero speed, so an autoneg downshift that kept the link up left if_baudrate, ifmedia, RX pause and interrupt moderation programmed for the old speed. Track the announced speed and re-run that work when it changes. aq_if_suspend() resets the MAC and stops the rings, but iflib_device_suspend() only calls IFDI_SUSPEND and never stops the interface, leaving IFF_DRV_RUNNING set over a suspended device. Clear it. Signed-off-by: Nick Price Reviewed by: adrian Differential Revision: https://reviews.freebsd.org/D58473 --- sys/dev/aq/aq_device.h | 1 + sys/dev/aq/aq_irq.c | 29 +++++++++++++++++++++++------ sys/dev/aq/aq_main.c | 12 ++++++++++-- 3 files changed, 34 insertions(+), 8 deletions(-) diff --git a/sys/dev/aq/aq_device.h b/sys/dev/aq/aq_device.h index c8942e19cf13..31c225bf2ddf 100644 --- a/sys/dev/aq/aq_device.h +++ b/sys/dev/aq/aq_device.h @@ -121,6 +121,7 @@ struct aq_dev { uint32_t tx_rings_count; uint32_t rx_rings_count; bool linkup; + uint32_t link_speed; /* Mbit/s last announced to the stack */ uint16_t phy_fault_last; /* last fault code reported */ enum aq_thermal_state { AQ_THERMAL_NORMAL = 0, /* no thermal shutdown pending */ diff --git a/sys/dev/aq/aq_irq.c b/sys/dev/aq/aq_irq.c index a15424cbeeba..054492bfe3df 100644 --- a/sys/dev/aq/aq_irq.c +++ b/sys/dev/aq/aq_irq.c @@ -217,20 +217,31 @@ aq_if_update_admin_status(if_ctx_t ctx) struct aq_dev *aq_dev = iflib_get_softc(ctx); struct aq_hw *hw = &aq_dev->hw; uint32_t link_speed; + bool running; struct aq_hw_fc_info fc_neg; aq_hw_get_link_state(hw, &link_speed, &fc_neg); - /* An interface whose initialization did not complete has no link. */ - if (aq_dev->init_failed) + /* A stopped or half-initialized interface has no link. */ + running = (if_getdrvflags(iflib_get_ifp(ctx)) & IFF_DRV_RUNNING) != 0; + if (!running || aq_dev->init_failed) link_speed = 0; - if (link_speed && !aq_dev->linkup) { /* link was DOWN */ - device_printf(aq_dev->dev, "link UP: speed=%d\n", link_speed); + /* A retrain can change the speed without ever dropping the link. */ + if (link_speed != 0U && + (!aq_dev->linkup || link_speed != aq_dev->link_speed)) { + if (!aq_dev->linkup) { + if (bootverbose) + device_printf(aq_dev->dev, + "link UP: speed=%d\n", link_speed); + aq_dev->phy_fault_last = 0; + } else + device_printf(aq_dev->dev, "link speed=%d\n", + link_speed); aq_dev->linkup = 1; - aq_dev->phy_fault_last = 0; + aq_dev->link_speed = link_speed; /* turn on/off RX Pause in RPB */ rpb_rx_xoff_en_per_tc_set(hw, fc_neg.fc_rx, 0); @@ -242,9 +253,11 @@ aq_if_update_admin_status(if_ctx_t ctx) /* update ITR settings according new link speed */ aq_hw_interrupt_moderation_set(hw); } else if (link_speed == 0U && aq_dev->linkup) { /* link was UP */ - device_printf(aq_dev->dev, "link DOWN\n"); + if (bootverbose) + device_printf(aq_dev->dev, "link DOWN\n"); aq_dev->linkup = 0; + aq_dev->link_speed = 0; /* turn off RX Pause in RPB */ rpb_rx_xoff_en_per_tc_set(hw, 0, 0); @@ -253,6 +266,10 @@ aq_if_update_admin_status(if_ctx_t ctx) aq_mediastatus_update(aq_dev, link_speed, &fc_neg); } + /* A stopped interface must not be re-initialized behind the operator. */ + if (!running) + return; + /* Re-arming while a reset is queued would re-init once too often. */ if (aq_dev->init_failed) { if (aq_dev->reset_pending) diff --git a/sys/dev/aq/aq_main.c b/sys/dev/aq/aq_main.c index cb04ccf5d158..d958a2aa62c5 100644 --- a/sys/dev/aq/aq_main.c +++ b/sys/dev/aq/aq_main.c @@ -559,6 +559,8 @@ aq_if_suspend(if_ctx_t ctx) aq_if_stop(ctx); aq_hw_deinit(&softc->hw); + /* iflib_device_suspend() does not stop the interface for us. */ + if_setdrvflagbits(iflib_get_ifp(ctx), IFF_DRV_OACTIVE, IFF_DRV_RUNNING); AQ_DBG_EXIT(0); return (0); @@ -755,6 +757,9 @@ aq_if_init(if_ctx_t ctx) softc->reset_pending = false; hw->tx_rings_count = softc->tx_rings_count; + /* Pick up a locally administered address set since the last init. */ + bcopy(if_getlladdr(iflib_get_ifp(ctx)), hw->mac_addr, ETHER_ADDR_LEN); + err = aq_hw_init(&softc->hw, softc->hw.mac_addr, softc->msix, softc->scctx->isc_intr == IFLIB_INTR_MSIX); if (err != 0) { @@ -855,8 +860,11 @@ aq_if_stop(if_ctx_t ctx) memset(&softc->last_stats, 0, sizeof(softc->last_stats)); /* Each bring-up gets its own budget of re-init attempts. */ softc->init_retries = 0; - softc->linkup = false; - aq_if_update_admin_status(ctx); + if (softc->linkup) { + softc->linkup = false; + softc->link_speed = 0; + iflib_link_state_change(ctx, LINK_STATE_DOWN, 0); + } AQ_DBG_EXIT(0); }