From nobody Sat Sep 12 22:19:51 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 4hj5SR5swnz6r4yy for ; Sat, 12 Sep 2026 22:19:51 +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 4hj5SR59wnz4RVT for ; Sat, 12 Sep 2026 22:19:51 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789251591; 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=8BJBXDZBUgYnB+SPFEHL9KhOMlQkoy0fS5EmfBSZ74s=; b=OYWo/EaxipWoR2B38fMVYDlcTEeWLLpvrsi7AkusAfTWwl/FXBXzI93QYayNvkbi+Hxvu5 2IF1lxQAlYL9PEsQnJ0EAvmoLzBtqMIV6rbje3wI9tCP0LN6g/SBrrYXKxnpxlCWz8oWZa tdEt2qn19hnZieh6fUUvs7zUohgeipUAWWsN56wvOcOHpgODLzf2HbqEZW3yCFa7Ce2DRv CJ4UFGPjZu0lZTU/M/desOk9A3O5PkndTtEecMJH1FBfZ8l/5IMt6fkwT7fe+1oJ/5MBFt sQ43lHuYlFWwCwVNKdwctzkIOwfTQDR+cUTKj/6jJN0uo2a4vlMfruL3SA3G7Q== ARC-Seal: i=1; a=rsa-sha256; d=freebsd.org; s=dkim; cv=none; t=1789251591; b=ntTbGFoRaF4gYR9sDQX/y8VdcKlmdh5AUXmGdt2dqDgZ+DSXQ9EW3rN8El8ZGJTvCbRPEW pSIVEQs4mTSrMQuCX1EEDJP2QsY/6fUAba9dezf44CmosQp3USSpBVx1t33pAr4DLVuUDQ kazum4/U74T4kO358x782OUeaWKEcXtmvbkliiTO/zOOSEaWM829x30EFhd5RLheb+km+m tc4hXDdNPH5G41MCh9m0xiqaBdvjmtZ9W9AW91mRp6SCQ+Hu7dXSjbOSANw6KqyvprZ1q5 GlZJ+7pzJEy9DF2+KE0FcrRYboYcEe7a/Xg+TLX6KJ52t1Ds1sw8C0s8JUE0Fw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1789251591; 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=8BJBXDZBUgYnB+SPFEHL9KhOMlQkoy0fS5EmfBSZ74s=; b=t2KynqC0zYb3VTMlHw4CdqkKVm1epHnkKK8Fex8Yft2/8TUl7g5E4TRX8Hvn0UJKSkPtSs FK0MTHt508hZzUyJafiyknjX6bcDDczLsLsApyrMLUUiqCMkJZQSM6v+BiaIBFFZ2IfN26 VkAWsoE1yIUwxnmLZWHSdS2+JX35g+Wb4xP2FISyqFcZ/w+2A8/aKyAS6ENTnbxftjAil4 WLOsaqk2ZBK/nQukflvmOk3DvbSfHt+xqdndrAkPIcgGimJLMQu96YU0pb8OMiKXgf3QEG QllGXreg2mtsAMJehViUfveJuTqo11ABUHf9FBY+RUY4uFYKZwhD+HcwM3Kejg== ARC-Authentication-Results: i=1; mx1.freebsd.org; none Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) by mxrelay.nyi.freebsd.org (Postfix) with ESMTP id 4hj5SR4DmYzFq3 for ; Sat, 12 Sep 2026 22:19:51 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from git (uid 1279) (envelope-from git@FreeBSD.org) id 33fa5 by gitrepo.freebsd.org (DragonFly Mail Agent v0.13+ on gitrepo.freebsd.org); Sat, 12 Sep 2026 22:19:51 +0000 To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-main@FreeBSD.org From: Nick Price Subject: git: 75a1939f6360 - main - aq(4): arm PHY thermal shutdown from the admin poll 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: nprice X-Git-Repository: src X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: 75a1939f6360d4a329891e2075d18eef069db9bb Auto-Submitted: auto-generated Date: Sat, 12 Sep 2026 22:19:51 +0000 Message-Id: <6aa5d007.33fa5.15a4f406@gitrepo.freebsd.org> The branch main has been updated by nprice: URL: https://cgit.FreeBSD.org/src/commit/?id=75a1939f6360d4a329891e2075d18eef069db9bb commit 75a1939f6360d4a329891e2075d18eef069db9bb Author: Nick Price AuthorDate: 2026-09-11 03:35:07 +0000 Commit: Nick Price CommitDate: 2026-09-12 22:19:14 +0000 aq(4): arm PHY thermal shutdown from the admin poll move thermal shutdown arming to the admin poll this gives a more reasonable delay prior to the first attempt, and also allows us to retry and make the option runtime-tuneable via a new disable_thermal_arm sysctl Approved by: adrian (mentor) Reviewed by: adrian Differential Revision: https://reviews.freebsd.org/D59593 Signed-off-by: Nick Price --- share/man/man4/aq.4 | 21 ++++++++++++++++++++- sys/dev/aq/aq2_fw.c | 35 ++++++++++++++++++++++++++++++++++- sys/dev/aq/aq_device.h | 2 ++ sys/dev/aq/aq_fw.h | 4 ++-- sys/dev/aq/aq_fw2x.c | 22 ++++++++++++++++------ sys/dev/aq/aq_irq.c | 30 ++++++++++++++++++++++++++++++ sys/dev/aq/aq_main.c | 24 ++++++++++++++---------- 7 files changed, 118 insertions(+), 20 deletions(-) diff --git a/share/man/man4/aq.4 b/share/man/man4/aq.4 index 50b3fd853e8c..c511070248cd 100644 --- a/share/man/man4/aq.4 +++ b/share/man/man4/aq.4 @@ -3,7 +3,7 @@ .\" .\" SPDX-License-Identifier: BSD-2-Clause .\" -.Dd August 6, 2026 +.Dd September 11, 2026 .Dt AQ 4 .Os .Sh NAME @@ -97,6 +97,24 @@ Comparing this against the transitions logged by the driver distinguishes a single link event from a flapping link. .El .Pp +The following variable controls the PHY thermal shutdown. +It is present only on adapters whose firmware reports a PHY temperature +and lets the driver arm the shutdown, and it may also be set as a +.Xr loader.conf 5 +tunable: +.Bl -tag -width indent +.It Va thermal_shutdown.enabled +Arm the PHY's autonomous thermal shutdown. +Armed, the PHY drops the link when its die passes the threshold the +board provisions; the driver reports the trip, waits for the PHY to +cool, and brings the link back. +The default, 1, arms the shutdown on every adapter that supports it, +whether or not its firmware ships it armed; 0 disarms it on those same +adapters. +The driver applies the setting from its periodic status poll, normally +within a second, and again after any reset of the adapter. +.El +.Pp The following variables tune the driver's own tracing: .Bl -tag -width indent .It Va debug @@ -111,4 +129,5 @@ All categories are enabled by default. .Sh SEE ALSO .Xr arp 4 , .Xr miibus 4 , +.Xr loader.conf 5 , .Xr ifconfig 8 diff --git a/sys/dev/aq/aq2_fw.c b/sys/dev/aq/aq2_fw.c index 3c2ba7ad944c..c373e98ebfe1 100644 --- a/sys/dev/aq/aq2_fw.c +++ b/sys/dev/aq/aq2_fw.c @@ -46,6 +46,7 @@ static int aq2_fw_get_link_counters(struct aq_hw *hw, uint32_t *up, uint32_t *down); static int aq2_fw_get_temp(struct aq_hw *hw, int *temp_mc); static int aq2_fw_get_thermal_limit(struct aq_hw *hw, int *limit_mc); +static int aq2_fw_thermal_arm(struct aq_hw *hw, bool enable); static int aq2_fw_get_phy_hot_warning(struct aq_hw *hw, bool *hot); /* Coherent OUT-window read, bracketed by the transaction id. */ @@ -542,6 +543,38 @@ aq2_fw_get_temp(struct aq_hw *hw, int *temp_mc) return (0); } +/* interface-in thermal_shutdown.enable; the F/W boots with it set. */ +static int +aq2_fw_thermal_arm(struct aq_hw *hw, bool enable) +{ + uint32_t v, want; + int err, limit_mc; + + /* No threshold means an unpopulated word or a departed adapter. */ + err = aq2_fw_get_thermal_limit(hw, &limit_mc); + if (err != 0) + return (err); + + mtx_lock(&hw->fw_mtx); + v = AQ_READ_REG(hw, AQ2_FW_INTERFACE_IN_THERMAL_SHUTDOWN_REG); + if (enable) + want = v | AQ2_FW_INTERFACE_IN_THERMAL_SHUTDOWN_ENABLE; + else + want = v & ~AQ2_FW_INTERFACE_IN_THERMAL_SHUTDOWN_ENABLE; + if (want != v) { + AQ_WRITE_REG(hw, AQ2_FW_INTERFACE_IN_THERMAL_SHUTDOWN_REG, + want); + err = aq2_fw_wait_shared_ack(hw); + /* Unacked: put the word back so the next poll retries. */ + if (err != 0) + AQ_WRITE_REG(hw, + AQ2_FW_INTERFACE_IN_THERMAL_SHUTDOWN_REG, v); + } + mtx_unlock(&hw->fw_mtx); + + return (err); +} + /* interface-in thermal_shutdown.shutdown_temperature, whole degC. */ static int aq2_fw_get_thermal_limit(struct aq_hw *hw, int *limit_mc) @@ -618,7 +651,7 @@ const struct aq_firmware_ops aq2_fw_ops = { .get_phy_fault = aq2_fw_get_phy_fault, .get_phy_hot_warning = aq2_fw_get_phy_hot_warning, .phy_reset = NULL, /* A2 clears thermal shutdown on its own reset */ - .thermal_arm = NULL, /* A2 firmware ships thermal shutdown armed */ + .thermal_arm = aq2_fw_thermal_arm, .get_thermal_limit = aq2_fw_get_thermal_limit, .led_control = NULL, }; diff --git a/sys/dev/aq/aq_device.h b/sys/dev/aq/aq_device.h index 4f4c3335e4c8..1f71a410b9f0 100644 --- a/sys/dev/aq/aq_device.h +++ b/sys/dev/aq/aq_device.h @@ -134,6 +134,8 @@ struct aq_dev { int thermal_retry_ticks; /* earliest tick to retry at */ int thermal_temp_mc; /* temp at the last shutdown/cool */ int thermal_recover_mc; /* recover once cooled to here */ + bool thermal_shutdown_enabled; /* arm the shutdown */ + int thermal_arm_err; /* last result returned */ bool init_failed; /* aq_hw_init() left the hw down */ int init_retries; bool reset_pending; /* a re-init is already queued */ diff --git a/sys/dev/aq/aq_fw.h b/sys/dev/aq/aq_fw.h index bdac9f87cb08..334c8c874edf 100644 --- a/sys/dev/aq/aq_fw.h +++ b/sys/dev/aq/aq_fw.h @@ -86,8 +86,8 @@ struct aq_firmware_ops /* Resets the PHY (clears a latched thermal shutdown). */ int (*phy_reset)(struct aq_hw* hw); - /* Arms the firmware autonomous thermal shutdown (A2 ships armed). */ - int (*thermal_arm)(struct aq_hw* hw); + /* Arms or disarms the firmware autonomous thermal shutdown. */ + int (*thermal_arm)(struct aq_hw* hw, bool enable); /* Reports the PHY high-temperature shutdown threshold (millidegrees C). */ int (*get_thermal_limit)(struct aq_hw* hw, int* limit_mc); diff --git a/sys/dev/aq/aq_fw2x.c b/sys/dev/aq/aq_fw2x.c index a4e584da2d65..cfb8048ac81a 100644 --- a/sys/dev/aq/aq_fw2x.c +++ b/sys/dev/aq/aq_fw2x.c @@ -650,11 +650,11 @@ aq_fw2x_phy_reset(struct aq_hw* hw) return (err); } -/* Arm autonomous thermal shutdown (1E.C478.A), cleared by any PHY reset. */ +/* Arm/disarm thermal shutdown, cleared by any PHY reset. */ static int -aq_fw2x_thermal_arm(struct aq_hw* hw) +aq_fw2x_thermal_arm(struct aq_hw* hw, bool enable) { - uint16_t ctrl; + uint16_t ctrl, want; int err; if ((hw->fw_caps & FW2X_CAP_TEMPERATURE) == 0) @@ -664,11 +664,21 @@ aq_fw2x_thermal_arm(struct aq_hw* hw) aq_fw2x_phy_id_probe(hw); err = aq_fw2x_phy_read(hw, AQ_PHY_MMD_GLOBAL, AQ_PHY_THERMAL_CTRL_REG, &ctrl); - if (err == 0 && ctrl == 0xffff) + if (err != 0) + goto out; + /* All ones is no PHY answering, not a control word. */ + if (ctrl == 0xffff) { err = ENXIO; - if (err == 0 && (ctrl & AQ_PHY_THERMAL_SD_EN) == 0) + goto out; + } + if (enable) + want = ctrl | AQ_PHY_THERMAL_SD_EN; + else + want = ctrl & ~AQ_PHY_THERMAL_SD_EN; + if (want != ctrl) err = aq_fw2x_phy_write(hw, AQ_PHY_MMD_GLOBAL, - AQ_PHY_THERMAL_CTRL_REG, ctrl | AQ_PHY_THERMAL_SD_EN); + AQ_PHY_THERMAL_CTRL_REG, want); +out: mtx_unlock(&hw->fw_mtx); return (err); diff --git a/sys/dev/aq/aq_irq.c b/sys/dev/aq/aq_irq.c index e52820ad77dc..48cbb6c3f2de 100644 --- a/sys/dev/aq/aq_irq.c +++ b/sys/dev/aq/aq_irq.c @@ -178,6 +178,35 @@ aq_thermal_report_hot(struct aq_dev *aq_dev) device_printf(aq_dev->dev, "PHY over-temperature warning\n"); } +/* reconcile thermal arm with knob value */ +static void +aq_thermal_apply(struct aq_dev *aq_dev) +{ + struct aq_hw *hw = &aq_dev->hw; + bool enable; + int err; + + /* A queued re-init would undo the write; the poll after it applies. */ + if (hw->fw_ops->thermal_arm == NULL || aq_dev->reset_pending) + return; + + enable = aq_dev->thermal_shutdown_enabled; + err = hw->fw_ops->thermal_arm(hw, enable); + /* No sensor to arm against; the knob is absent on such an adapter. */ + if (err == ENOTSUP) + return; + /* Print only on a change, so a lasting failure is reported once. */ + if (err == aq_dev->thermal_arm_err) + return; + aq_dev->thermal_arm_err = err; + if (err != 0) + device_printf(aq_dev->dev, "could not %s PHY thermal shutdown, " + "error %d\n", enable ? "arm" : "disarm", err); + else + device_printf(aq_dev->dev, "PHY thermal shutdown %s\n", + enable ? "armed" : "disarmed"); +} + /* Recover after cooldown: A1 needs a PHY reset then re-init, A2 re-inits alone. */ static void aq_thermal_poll(struct aq_dev *aq_dev) @@ -188,6 +217,7 @@ aq_thermal_poll(struct aq_dev *aq_dev) switch (aq_dev->thermal_state) { case AQ_THERMAL_NORMAL: + aq_thermal_apply(aq_dev); aq_thermal_report_hot(aq_dev); if (aq_dev->linkup) return; diff --git a/sys/dev/aq/aq_main.c b/sys/dev/aq/aq_main.c index 819ab5fb7e5c..f55f958233ce 100644 --- a/sys/dev/aq/aq_main.c +++ b/sys/dev/aq/aq_main.c @@ -378,6 +378,7 @@ aq_if_attach_pre(if_ctx_t ctx) hw->fc.fc_rx = 1; hw->fc.fc_tx = 1; softc->linkup = 0U; + softc->thermal_shutdown_enabled = true; /* Set here, not in aq_if_init(): a recovery re-init must not reset it. */ softc->thermal_retry_ticks = ticks; @@ -778,14 +779,6 @@ aq_if_init(if_ctx_t ctx) softc->init_failed = false; softc->init_retries = 0; - /* aq_hw_init reloads the PHY, resetting the thermal-shutdown arming. */ - if (hw->fw_ops->thermal_arm != NULL) { - err = hw->fw_ops->thermal_arm(hw); - if (err != 0 && err != ENOTSUP) - device_printf(softc->dev, - "could not arm PHY thermal shutdown\n"); - } - aq_if_media_status(ctx, &ifmr); aq_update_vlan_filters(softc); @@ -1459,7 +1452,7 @@ aq_add_stats_sysctls(struct aq_dev *softc) struct sysctl_oid *tree = device_get_sysctl_tree(dev); struct sysctl_oid_list *child = SYSCTL_CHILDREN(tree); struct aq_stats *stats = &softc->curr_stats; - struct sysctl_oid *stat_node, *queue_node; + struct sysctl_oid *stat_node, *queue_node, *thermal_node; struct sysctl_oid_list *stat_list, *queue_list; uint32_t link_up, link_down; int temp_mc; @@ -1481,10 +1474,21 @@ aq_add_stats_sysctls(struct aq_dev *softc) /* ENOTSUP means no sensor; other errors may just be a cold PHY. */ if (softc->hw.fw_ops != NULL && softc->hw.fw_ops->get_temp != NULL && - softc->hw.fw_ops->get_temp(&softc->hw, &temp_mc) != ENOTSUP) + softc->hw.fw_ops->get_temp(&softc->hw, &temp_mc) != ENOTSUP) { SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD | CTLFLAG_MPSAFE, softc, 0, aq_sysctl_temperature, "IK", "PHY temperature"); + /* Without the sensor there is no shutdown to arm. */ + if (softc->hw.fw_ops->thermal_arm != NULL) { + thermal_node = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, + "thermal_shutdown", CTLFLAG_RD | CTLFLAG_MPSAFE, + NULL, "PHY thermal shutdown"); + SYSCTL_ADD_BOOL(ctx, SYSCTL_CHILDREN(thermal_node), + OID_AUTO, "enabled", CTLFLAG_RWTUN, + &softc->thermal_shutdown_enabled, 0, + "Arm the PHY's autonomous thermal shutdown"); + } + } /* Only some firmware interface versions count link transitions. */ if (softc->hw.fw_ops != NULL &&