From nobody Sat Aug 22 00:26:18 2026 X-Original-To: dev-commits-src-branches@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 4hRdJV69kwz6ppwP for ; Sat, 22 Aug 2026 00:26:18 +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 "YR2" (not verified)) by mx1.freebsd.org (Postfix) with ESMTPS id 4hRdJV3V0Cz3CmB for ; Sat, 22 Aug 2026 00:26:18 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1787358378; 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=ok9RK+K1IOcplYgKkgQmKWshL+4EtA0ZjtOwl2ztyYM=; b=q1xOX+JZcDwEhApj+xQxcTXhN0tpZIG0o3WTQVOo51Y95I7gI5saScCsuTfiXNqkYuPnCl aNLAO4XB9CuEyF9c0LVRC/JlOiJVIZ2NFQlVEej2ICbBM7qr1DhBM5ovzx0/LB/Lu4Wa1N RxEVqclEo/cDYx1Rv519p83Ri7K2fF7WkQ0MOGaS5O/sHJ+EaRNk9Drp6sU0zoDmXkokxd oL0GXUQNNuB9Sz/jyZ5LutdpdtezXW+KLuK24uAI8GMD8sylePXxuCgM12Kvec0OyrWVjx rX7EYYiiU+CuShUSBDzyPyagUjxjq1aVGc2CwoaY25WkUnEciH3KEOLOayWMdQ== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1787358378; a=rsa-sha256; cv=none; b=qJsaJxFXNiv3Q9zmgt1b5uyX8gF6cveA4/4ECW4Ry2fhTn9YDwjX2cj+/InwZNK3lCNuEE 6CiZczChmMlNkzRYJk3CzQG0htZODzTA4ghpqAQRwkeIzSZjwErQo2o9C1Z7jazigBKHIm Wj7mXgMnx26ONX2W8rvqm0ESYMy8Mo4+f9LNielafkLUcVpYNY8jSoXw+Il24274WmSqxv mNX6oaDpfOrIJuaADHv5sJdV+H7I63GG3jNvOiRCXXsoqqHH+6kTx9EjpjojFW/Y8A4ECf 5e8uDsBI43lnu4D/p0u04Gzqtac5Hw+zPAUgZ72SgjMrfvuWpxJCIFnC3Yt3IA== 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=1787358378; 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=ok9RK+K1IOcplYgKkgQmKWshL+4EtA0ZjtOwl2ztyYM=; b=gFR89bCfpo91oSZu17614DS75pNADTaru1mvLJaXWRLFvdjWIl3KKpRSpuLC3XcOSjrurv wvJ9lyHuOTxBU+lZ0GSzaeU+yXNBjIwcAJXRep0U9UsBFXgwChJae3+uEY6QSRsXwSF2cI C1qZFplRuWvGlXWl9lmSTgGiMDMY130qzd/zDjJnGHaKk0U1TfkrdOx556kE5OL8suCa9I ng/5kWDftPluEFNRBXovMbeD+pQt7kej2nbn4EgQshuZnnQDtgoCQec2ucfiOrw6kIQclD NnvrI0DWGX8aC79Ny+Qd2rhDVefOarZQFrFfEMaF/1fyA5QoBsUmFFLxCZC4kg== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hRdJV2K9Fz9hG for ; Sat, 22 Aug 2026 00:26:18 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 24d04 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sat, 22 Aug 2026 00:26:18 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org From: Kevin Bowling Subject: git: 7df3a9c641f5 - stable/15 - ixgbe: Handle deferred link-status requests List-Id: Commits to the stable branches of the FreeBSD src repository List-Archive: https://lists.freebsd.org/archives/dev-commits-src-branches List-Help: List-Post: List-Subscribe: List-Unsubscribe: X-BeenThere: dev-commits-src-branches@freebsd.org Sender: owner-dev-commits-src-branches@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/stable/15 X-Git-Reftype: branch X-Git-Commit: 7df3a9c641f5bbb49fdd157e2afce12376dd3f0f Auto-Submitted: auto-generated Date: Sat, 22 Aug 2026 00:26:18 +0000 Message-Id: <6a88ecaa.24d04.48fa44fc@gitrepo.freebsd.org> The branch stable/15 has been updated by kbowling: URL: https://cgit.FreeBSD.org/src/commit/?id=7df3a9c641f5bbb49fdd157e2afce12376dd3f0f commit 7df3a9c641f5bbb49fdd157e2afce12376dd3f0f Author: Kevin Bowling AuthorDate: 2026-08-06 08:22:21 +0000 Commit: Kevin Bowling CommitDate: 2026-08-22 00:25:56 +0000 ixgbe: Handle deferred link-status requests The iflib conversion records link-status interrupts in the administrative request mask, but the administrative task did not consume them. Timer polling usually hid the omission; frequent mailbox interrupts could continually rearm that timer and leave cached link state down after hardware recovered. Claim request batches atomically, process link-setup dependencies, and sample hardware before publishing link state. Bound each invocation to eight batches and requeue residual work so a continuous producer cannot monopolize the admin taskqueue. Queue every link-related request from the legacy interrupt path. Unlike MSI-X, its threaded continuation services RX and does not enqueue the admin task. This restores the event-driven behavior of ix-3.4.39. Fixes: b2c1e8e62049 ("ix(4): Run {mod,msf,mbx,fdir,phy}_task in if_update_admin_status") (cherry picked from commit 2b763a82f9f21b722b50830bc22af2b2acf36746) --- sys/dev/ixgbe/if_ix.c | 133 +++++++++++++++++++++++++++++++------------------- 1 file changed, 83 insertions(+), 50 deletions(-) diff --git a/sys/dev/ixgbe/if_ix.c b/sys/dev/ixgbe/if_ix.c index 1909a936c3c1..4baaa040cbce 100644 --- a/sys/dev/ixgbe/if_ix.c +++ b/sys/dev/ixgbe/if_ix.c @@ -47,6 +47,9 @@ ************************************************************************/ static const char ixgbe_driver_version[] = "5.0.1-k"; +/* Bound one admin-task invocation while still coalescing new requests. */ +#define IXGBE_ADMIN_TASK_BUDGET 8 + /************************************************************************ * PCI Device ID Table * @@ -276,9 +279,9 @@ static int ixgbe_sysctl_dump_debug_dump(SYSCTL_HANDLER_ARGS); /* Deferred interrupt tasklets */ static void ixgbe_handle_msf(void *); -static void ixgbe_handle_mod(void *); +static bool ixgbe_handle_mod(void *); static void ixgbe_handle_phy(void *); -static void ixgbe_handle_fw_event(void *); +static u32 ixgbe_handle_fw_event(void *); static int ixgbe_enable_lse(struct ixgbe_softc *sc); static int ixgbe_disable_lse(struct ixgbe_softc *sc); @@ -1827,7 +1830,7 @@ ixgbe_config_link(if_ctx_t ctx) if (sfp) { /* ixgbe_if_stop() disables it on every 82599 SFP port. */ ixgbe_enable_tx_laser(hw); - sc->task_requests |= IXGBE_REQUEST_TASK_MOD; + atomic_set_32(&sc->task_requests, IXGBE_REQUEST_TASK_MOD); iflib_admin_intr_deferred(ctx); } else { if (hw->mac.ops.check_link) @@ -3112,12 +3115,12 @@ ixgbe_msix_link(void *arg) /* Link status change */ if (eicr & IXGBE_EICR_LSC) { IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); - sc->task_requests |= IXGBE_REQUEST_TASK_LSC; + atomic_set_32(&sc->task_requests, IXGBE_REQUEST_TASK_LSC); } if (eicr & IXGBE_EICR_FW_EVENT) { IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FW_EVENT); - sc->task_requests |= IXGBE_REQUEST_TASK_FWEVENT; + atomic_set_32(&sc->task_requests, IXGBE_REQUEST_TASK_FWEVENT); } if (sc->hw.mac.type != ixgbe_mac_82598EB) { @@ -3128,7 +3131,7 @@ ixgbe_msix_link(void *arg) return (FILTER_HANDLED); /* Disable the interrupt */ IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EICR_FLOW_DIR); - sc->task_requests |= IXGBE_REQUEST_TASK_FDIR; + atomic_set_32(&sc->task_requests, IXGBE_REQUEST_TASK_FDIR); } else if (eicr & IXGBE_EICR_ECC) { device_printf(iflib_get_dev(sc->ctx), @@ -3179,7 +3182,7 @@ ixgbe_msix_link(void *arg) /* Check for VF message */ if ((sc->feat_en & IXGBE_FEATURE_SRIOV) && (eicr & IXGBE_EICR_MAILBOX)) { - sc->task_requests |= IXGBE_REQUEST_TASK_MBX; + atomic_set_32(&sc->task_requests, IXGBE_REQUEST_TASK_MBX); } } @@ -3196,14 +3199,14 @@ ixgbe_msix_link(void *arg) if (eicr & eicr_mask) { IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); - sc->task_requests |= IXGBE_REQUEST_TASK_MOD; + atomic_set_32(&sc->task_requests, IXGBE_REQUEST_TASK_MOD); } if ((hw->mac.type == ixgbe_mac_82599EB) && (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); - sc->task_requests |= IXGBE_REQUEST_TASK_MSF; + atomic_set_32(&sc->task_requests, IXGBE_REQUEST_TASK_MSF); } } @@ -3218,10 +3221,10 @@ ixgbe_msix_link(void *arg) if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && (eicr & IXGBE_EICR_GPI_SDP0_X540)) { IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP0_X540); - sc->task_requests |= IXGBE_REQUEST_TASK_PHY; + atomic_set_32(&sc->task_requests, IXGBE_REQUEST_TASK_PHY); } - return (sc->task_requests != 0) ? + return (atomic_load_acq_32(&sc->task_requests) != 0) ? FILTER_SCHEDULE_THREAD : FILTER_HANDLED; } /* ixgbe_msix_link */ @@ -3975,10 +3978,9 @@ ixgbe_if_init(if_ctx_t ctx) ixgbe_initialize_receive_units(ctx); /* - * Initialize variable holding task enqueue requests - * from MSI-X interrupts + * Initialize the deferred administrative request mask. */ - sc->task_requests = 0; + atomic_store_rel_32(&sc->task_requests, 0); /* Enable SDP & MSI-X interrupts based on adapter */ ixgbe_config_gpie(sc); @@ -4537,7 +4539,7 @@ out: /************************************************************************ * ixgbe_handle_mod - Tasklet for SFP module interrupts ************************************************************************/ -static void +static bool ixgbe_handle_mod(void *context) { if_ctx_t ctx = context; @@ -4582,11 +4584,10 @@ ixgbe_handle_mod(void *context) "Setup failure - unsupported SFP+ module type.\n"); goto handle_mod_out; } - sc->task_requests |= IXGBE_REQUEST_TASK_MSF; - return; + return (true); handle_mod_out: - sc->task_requests &= ~(IXGBE_REQUEST_TASK_MSF); + return (false); } /* ixgbe_handle_mod */ @@ -4678,7 +4679,7 @@ s32 ixgbe_disable_lse(struct ixgbe_softc *sc) /************************************************************************ * ixgbe_handle_fw_event - Tasklet for MSI-X Link Status Event interrupts ************************************************************************/ -static void +static u32 ixgbe_handle_fw_event(void *context) { if_ctx_t ctx = context; @@ -4687,13 +4688,14 @@ ixgbe_handle_fw_event(void *context) struct ixgbe_aci_event event; bool pending = false; s32 error; + u32 requests = 0; event.buf_len = IXGBE_ACI_MAX_BUFFER_SIZE; event.msg_buf = malloc(event.buf_len, M_IXGBE, M_ZERO | M_NOWAIT); if (!event.msg_buf) { device_printf(sc->dev, "Can not allocate buffer for " "event message\n"); - return; + return (0); } do { @@ -4706,7 +4708,7 @@ ixgbe_handle_fw_event(void *context) switch (le16toh(event.desc.opcode)) { case ixgbe_aci_opc_get_link_status: - sc->task_requests |= IXGBE_REQUEST_TASK_LSC; + requests |= IXGBE_REQUEST_TASK_LSC; break; case ixgbe_aci_opc_fw_logs_event: @@ -4730,6 +4732,7 @@ ixgbe_handle_fw_event(void *context) } while (pending); free(event.msg_buf, M_IXGBE); + return (requests); } /* ixgbe_handle_fw_event */ /************************************************************************ @@ -4801,15 +4804,61 @@ ixgbe_link_speed_to_str(u32 link_speed) /************************************************************************ * ixgbe_update_link_status - Update OS on link state * - * Note: Only updates the OS on the cached link state. - * The real check of the hardware only happens with - * a link interrupt. + * Process deferred administrative requests and update the OS link state. ************************************************************************/ static void ixgbe_if_update_admin_status(if_ctx_t ctx) { struct ixgbe_softc *sc = iflib_get_softc(ctx); device_t dev = iflib_get_dev(ctx); + u32 requests; + u_int pass; + bool check_link = false; + + /* + * The interrupt filter and other producers can run concurrently with + * this task. Claim each batch atomically so a request posted while the + * task is running remains pending for this or the next invocation. + * + * MOD and firmware events can produce dependent requests. Fold those + * into the claimed batch so link state is sampled after any link setup. + */ + if ((if_getdrvflags(iflib_get_ifp(ctx)) & IFF_DRV_RUNNING) != 0 && + (sc->iov_mbx_cleanup_pending || ixgbe_mbx_pending(sc))) + atomic_set_32(&sc->task_requests, IXGBE_REQUEST_TASK_MBX); + for (pass = 0; pass < IXGBE_ADMIN_TASK_BUDGET; pass++) { + requests = atomic_readandclear_32(&sc->task_requests); + if (requests == 0) + break; + if (requests & IXGBE_REQUEST_TASK_FWEVENT) + requests |= ixgbe_handle_fw_event(ctx); + if (requests & IXGBE_REQUEST_TASK_MOD) { + if (ixgbe_handle_mod(ctx)) + requests |= IXGBE_REQUEST_TASK_MSF; + else + requests &= ~IXGBE_REQUEST_TASK_MSF; + } + if (requests & IXGBE_REQUEST_TASK_MSF) + ixgbe_handle_msf(ctx); + /* A reset request can re-enable VF traffic; skip it while stopped. */ + if ((requests & IXGBE_REQUEST_TASK_MBX) != 0 && + (if_getdrvflags(iflib_get_ifp(ctx)) & IFF_DRV_RUNNING) != 0) + ixgbe_handle_mbx(ctx); + if (requests & IXGBE_REQUEST_TASK_FDIR) + ixgbe_reinit_fdir(ctx); + if (requests & IXGBE_REQUEST_TASK_PHY) + ixgbe_handle_phy(ctx); + if (requests & IXGBE_REQUEST_TASK_LSC) + check_link = true; + } + + /* Do not let a continuous producer monopolize the admin taskqueue. */ + if (atomic_load_acq_32(&sc->task_requests) != 0) + iflib_admin_intr_deferred(ctx); + + if (check_link) + ixgbe_check_link(&sc->hw, &sc->link_speed, &sc->link_up, + false); if (sc->link_up) { if (sc->link_active == false) { @@ -4853,27 +4902,6 @@ ixgbe_if_update_admin_status(if_ctx_t ctx) } } - /* Handle task requests from msix_link() */ - if (sc->task_requests & IXGBE_REQUEST_TASK_FWEVENT) - ixgbe_handle_fw_event(ctx); - if (sc->task_requests & IXGBE_REQUEST_TASK_MOD) - ixgbe_handle_mod(ctx); - if (sc->task_requests & IXGBE_REQUEST_TASK_MSF) - ixgbe_handle_msf(ctx); - /* - * A reset request re-enables VF traffic, so do not service mailboxes - * while the PF is stopped. VFREQ, VFACK, and VFLR are hardware-latched - * and ixgbe_mbx_pending() resamples them after the PF is running again. - */ - if ((if_getdrvflags(iflib_get_ifp(ctx)) & IFF_DRV_RUNNING) != 0 && - ((sc->task_requests & IXGBE_REQUEST_TASK_MBX) != 0 || - sc->iov_mbx_cleanup_pending || ixgbe_mbx_pending(sc))) - ixgbe_handle_mbx(ctx); - if (sc->task_requests & IXGBE_REQUEST_TASK_FDIR) - ixgbe_reinit_fdir(ctx); - if (sc->task_requests & IXGBE_REQUEST_TASK_PHY) - ixgbe_handle_phy(ctx); - sc->task_requests = 0; ixgbe_schedule_iov_recovery(sc); ixgbe_update_stats_counters(sc); @@ -5098,9 +5126,10 @@ ixgbe_intr(void *arg) struct ix_rx_queue *que = sc->rx_queues; struct ixgbe_hw *hw = &sc->hw; if_ctx_t ctx = sc->ctx; - u32 eicr, eicr_mask; + u32 eicr, eicr_mask, requests; eicr = IXGBE_READ_REG(hw, IXGBE_EICR); + requests = 0; ++que->irqs; if (eicr == 0) { @@ -5120,7 +5149,7 @@ ixgbe_intr(void *arg) /* Link status change */ if (eicr & IXGBE_EICR_LSC) { IXGBE_WRITE_REG(hw, IXGBE_EIMC, IXGBE_EIMC_LSC); - iflib_admin_intr_deferred(ctx); + requests |= IXGBE_REQUEST_TASK_LSC; } if (ixgbe_is_sfp(hw)) { @@ -5132,21 +5161,25 @@ ixgbe_intr(void *arg) if (eicr & eicr_mask) { IXGBE_WRITE_REG(hw, IXGBE_EICR, eicr_mask); - sc->task_requests |= IXGBE_REQUEST_TASK_MOD; + requests |= IXGBE_REQUEST_TASK_MOD; } if ((hw->mac.type == ixgbe_mac_82599EB) && (eicr & IXGBE_EICR_GPI_SDP1_BY_MAC(hw))) { IXGBE_WRITE_REG(hw, IXGBE_EICR, IXGBE_EICR_GPI_SDP1_BY_MAC(hw)); - sc->task_requests |= IXGBE_REQUEST_TASK_MSF; + requests |= IXGBE_REQUEST_TASK_MSF; } } /* External PHY interrupt */ if ((hw->phy.type == ixgbe_phy_x550em_ext_t) && (eicr & IXGBE_EICR_GPI_SDP0_X540)) { - sc->task_requests |= IXGBE_REQUEST_TASK_PHY; + requests |= IXGBE_REQUEST_TASK_PHY; + } + if (requests != 0) { + atomic_set_32(&sc->task_requests, requests); + iflib_admin_intr_deferred(ctx); } return (FILTER_SCHEDULE_THREAD);