Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/patches/2216526/?format=api
{ "id": 2216526, "url": "http://patchwork.ozlabs.org/api/patches/2216526/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20260326162832.3135857-9-grzegorz.nitka@intel.com/", "project": { "id": 46, "url": "http://patchwork.ozlabs.org/api/projects/46/?format=api", "name": "Intel Wired Ethernet development", "link_name": "intel-wired-lan", "list_id": "intel-wired-lan.osuosl.org", "list_email": "intel-wired-lan@osuosl.org", "web_url": "", "scm_url": "", "webscm_url": "", "list_archive_url": "", "list_archive_url_format": "", "commit_url_format": "" }, "msgid": "<20260326162832.3135857-9-grzegorz.nitka@intel.com>", "list_archive_url": null, "date": "2026-03-26T16:28:32", "name": "[v4,net-next,8/8] ice: add TX reference clock (tx_clk) control for E825 devices", "commit_ref": null, "pull_url": null, "state": "handled-elsewhere", "archived": false, "hash": "29bf8baf06a7a474d6e74f6caacd5374a759ea78", "submitter": { "id": 82711, "url": "http://patchwork.ozlabs.org/api/people/82711/?format=api", "name": "Nitka, Grzegorz", "email": "grzegorz.nitka@intel.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/intel-wired-lan/patch/20260326162832.3135857-9-grzegorz.nitka@intel.com/mbox/", "series": [ { "id": 497620, "url": "http://patchwork.ozlabs.org/api/series/497620/?format=api", "web_url": "http://patchwork.ozlabs.org/project/intel-wired-lan/list/?series=497620", "date": "2026-03-26T16:28:24", "name": "dpll/ice: Add TXC DPLL type and full TX reference clock control for E825", "version": 4, "mbox": "http://patchwork.ozlabs.org/series/497620/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2216526/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2216526/checks/", "tags": {}, "related": [], "headers": { "Return-Path": "<intel-wired-lan-bounces@osuosl.org>", "X-Original-To": [ "incoming@patchwork.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Delivered-To": [ "patchwork-incoming@legolas.ozlabs.org", "intel-wired-lan@lists.osuosl.org" ], "Authentication-Results": [ "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=osuosl.org header.i=@osuosl.org header.a=rsa-sha256\n header.s=default header.b=V5TR5uUe;\n\tdkim-atps=neutral", "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=osuosl.org\n (client-ip=2605:bc80:3010::136; helo=smtp3.osuosl.org;\n envelope-from=intel-wired-lan-bounces@osuosl.org;\n receiver=patchwork.ozlabs.org)" ], "Received": [ "from smtp3.osuosl.org (smtp3.osuosl.org [IPv6:2605:bc80:3010::136])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4fhTqJ4My2z1yGD\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 27 Mar 2026 03:33:32 +1100 (AEDT)", "from localhost (localhost [127.0.0.1])\n\tby smtp3.osuosl.org (Postfix) with ESMTP id 44F356084C;\n\tThu, 26 Mar 2026 16:33:31 +0000 (UTC)", "from smtp3.osuosl.org ([127.0.0.1])\n by localhost (smtp3.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id BmOPO2Kw_ICb; Thu, 26 Mar 2026 16:33:29 +0000 (UTC)", "from lists1.osuosl.org (lists1.osuosl.org [140.211.166.142])\n\tby smtp3.osuosl.org (Postfix) with ESMTP id D064460853;\n\tThu, 26 Mar 2026 16:33:29 +0000 (UTC)", "from smtp1.osuosl.org (smtp1.osuosl.org [140.211.166.138])\n by lists1.osuosl.org (Postfix) with ESMTP id F3E34F5\n for <intel-wired-lan@lists.osuosl.org>; Thu, 26 Mar 2026 16:33:28 +0000 (UTC)", "from localhost (localhost [127.0.0.1])\n by smtp1.osuosl.org (Postfix) with ESMTP id D93EB8126D\n for <intel-wired-lan@lists.osuosl.org>; Thu, 26 Mar 2026 16:33:28 +0000 (UTC)", "from smtp1.osuosl.org ([127.0.0.1])\n by localhost (smtp1.osuosl.org [127.0.0.1]) (amavis, port 10024) with ESMTP\n id 84loxeMKaTAC for <intel-wired-lan@lists.osuosl.org>;\n Thu, 26 Mar 2026 16:33:27 +0000 (UTC)", "from mgamail.intel.com (mgamail.intel.com [192.198.163.19])\n by smtp1.osuosl.org (Postfix) with ESMTPS id 7712681206\n for <intel-wired-lan@lists.osuosl.org>; Thu, 26 Mar 2026 16:33:27 +0000 (UTC)", "from orviesa007.jf.intel.com ([10.64.159.147])\n by fmvoesa113.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384;\n 26 Mar 2026 09:33:26 -0700", "from gklab-003-001.igk.intel.com ([10.91.173.48])\n by orviesa007.jf.intel.com with ESMTP; 26 Mar 2026 09:33:21 -0700" ], "X-Virus-Scanned": [ "amavis at osuosl.org", "amavis at osuosl.org" ], "X-Comment": "SPF check N/A for local connections - client-ip=140.211.166.142;\n helo=lists1.osuosl.org; envelope-from=intel-wired-lan-bounces@osuosl.org;\n receiver=<UNKNOWN> ", "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 smtp3.osuosl.org D064460853", "OpenDKIM Filter v2.11.0 smtp1.osuosl.org 7712681206" ], "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed; d=osuosl.org;\n\ts=default; t=1774542809;\n\tbh=4m+5GwSNTyQugn8+1NY79ohYVnrPI6E2r6ZMcglTKY0=;\n\th=From:To:Date:In-Reply-To:References:Subject:List-Id:\n\t List-Unsubscribe:List-Archive:List-Post:List-Help:List-Subscribe:\n\t Cc:From;\n\tb=V5TR5uUe0p+MpN+QoZ99dkWyC+Zn57JZO9NHFHDbx0Ii55i74kENDfZ213SWE6NOk\n\t i0p5YawUZ0IKO1pNPYkKKAgVYwyv8dBgP0DMHmmfcbL2K3rWXwMGqM47LdrSg6KBsF\n\t q3X/RPtB+1dW6pQ+e+kw393Ul8KYYDJ/xvG5Ih1if2LZ27NHl2WKwaZlQZj/teDLLZ\n\t s+h+IhRVTH1jsdPct4XSehmtkOhHF5+0fYVcZPhx2zxHgWRPHgOzNykM/mzD30cL1j\n\t BLs+YB+h7Y0MgW4xtIOo1CtDbNnch0FY+JPTCf5CdS8VYs/rJyn8WTuOZqwLSxCwv9\n\t gXTX6KNJlppiQ==", "Received-SPF": "Pass (mailfrom) identity=mailfrom; client-ip=192.198.163.19;\n helo=mgamail.intel.com; envelope-from=grzegorz.nitka@intel.com;\n receiver=<UNKNOWN>", "DMARC-Filter": "OpenDMARC Filter v1.4.2 smtp1.osuosl.org 7712681206", "X-CSE-ConnectionGUID": [ "1Km3PhRhR3W2WBX3Qo54iA==", "CtUyLLrVTx61STSSPn75cA==" ], "X-CSE-MsgGUID": [ "ls1DvkDvRDCf5Eo6jL+9Ew==", "koG7bDrXSyWxLH3L+XrkuA==" ], "X-IronPort-AV": [ "E=McAfee;i=\"6800,10657,11741\"; a=\"74636793\"", "E=Sophos;i=\"6.23,142,1770624000\"; d=\"scan'208\";a=\"74636793\"", "E=Sophos;i=\"6.23,142,1770624000\"; d=\"scan'208\";a=\"225311414\"" ], "X-ExtLoop1": "1", "From": "Grzegorz Nitka <grzegorz.nitka@intel.com>", "To": "netdev@vger.kernel.org", "Date": "Thu, 26 Mar 2026 17:28:32 +0100", "Message-Id": "<20260326162832.3135857-9-grzegorz.nitka@intel.com>", "X-Mailer": "git-send-email 2.39.3", "In-Reply-To": "<20260326162832.3135857-1-grzegorz.nitka@intel.com>", "References": "<20260326162832.3135857-1-grzegorz.nitka@intel.com>", "MIME-Version": "1.0", "Content-Type": "text/plain; charset=UTF-8", "Content-Transfer-Encoding": "8bit", "X-Mailman-Original-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/simple;\n d=intel.com; i=@intel.com; q=dns/txt; s=Intel;\n t=1774542807; x=1806078807;\n h=from:to:cc:subject:date:message-id:in-reply-to:\n references:mime-version:content-transfer-encoding;\n bh=YvFe7Mrp0/nooPRVRV/8VS/UW7rTm2ND8U7tebxBNaU=;\n b=LtaI87ufk8q9PFN7SkZtSlp+uJff7lfJK5z3lYh9j/K8POeeuI5Y/klE\n kdSg0s7lBZGE5M3A0qPWHu5fY4eJONGCIHossFm/G0eH3cppV31Rf3LWq\n of0QtiX9N9OzUlT7BUaBn90o6d3AvRPYgk8W57O0TasHEZxzsuN49RxQU\n 84ISVl2ofYwH/i5TWYxcBDbG4tYy35Y01gVTeGfd5xay3uRXvQVb0dDfP\n EpxvVjH6j7/VlQ1f9xrMQfBkQkaYm1Evkz8g6WGRV036oYG1XT+Kn/7RD\n L3X15MjI4dD7PDDQvtBhCS2B+CheHFzVbx2awKocZstOhJLKOvRt33ylr\n w==;", "X-Mailman-Original-Authentication-Results": [ "smtp1.osuosl.org;\n dmarc=pass (p=none dis=none)\n header.from=intel.com", "smtp1.osuosl.org;\n dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com\n header.a=rsa-sha256 header.s=Intel header.b=LtaI87uf" ], "Subject": "[Intel-wired-lan] [PATCH v4 net-next 8/8] ice: add TX reference\n clock (tx_clk) control for E825 devices", "X-BeenThere": "intel-wired-lan@osuosl.org", "X-Mailman-Version": "2.1.30", "Precedence": "list", "List-Id": "Intel Wired Ethernet Linux Kernel Driver Development\n <intel-wired-lan.osuosl.org>", "List-Unsubscribe": "<https://lists.osuosl.org/mailman/options/intel-wired-lan>,\n <mailto:intel-wired-lan-request@osuosl.org?subject=unsubscribe>", "List-Archive": "<http://lists.osuosl.org/pipermail/intel-wired-lan/>", "List-Post": "<mailto:intel-wired-lan@osuosl.org>", "List-Help": "<mailto:intel-wired-lan-request@osuosl.org?subject=help>", "List-Subscribe": "<https://lists.osuosl.org/mailman/listinfo/intel-wired-lan>,\n <mailto:intel-wired-lan-request@osuosl.org?subject=subscribe>", "Cc": "ivecera@redhat.com, vadim.fedorenko@linux.dev, kuba@kernel.org,\n jiri@resnulli.us, edumazet@google.com, przemyslaw.kitszel@intel.com,\n richardcochran@gmail.com, donald.hunter@gmail.com,\n linux-kernel@vger.kernel.org, arkadiusz.kubalewski@intel.com,\n andrew+netdev@lunn.ch, intel-wired-lan@lists.osuosl.org, horms@kernel.org,\n Prathosh.Satish@microchip.com, anthony.l.nguyen@intel.com, pabeni@redhat.com,\n davem@davemloft.net", "Errors-To": "intel-wired-lan-bounces@osuosl.org", "Sender": "\"Intel-wired-lan\" <intel-wired-lan-bounces@osuosl.org>" }, "content": "Add full support for selecting and controlling the TX SERDES reference\nclock on E825C hardware. E825C devicede supports selecting among\nmultiple SERDES transmit reference clock sources (ENET, SyncE, EREF0),\nbut imposes several routing constraints: on some paths a reference\nmust be enabled on both PHY complexes, and ports sharing a PHY must\ncoordinate usage so that a reference is not disabled while still in\nactive use. Until now the driver did not expose this domain through\nthe DPLL API, nor did it provide a coherent control layer for enabling,\nswitching, or tracking TX reference clocks.\n\nThis patch implements full TX reference clock management for E825\ndevices. Compared to previous iterations, the logic is now separated\ninto a dedicated module (ice_txclk.c) which encapsulates all\nclock-selection rules, cross‑PHY dependencies, and the bookkeeping\nneeded to ensure safe transitions. This allows the DPLL layer and\nthe PTP code to remain focused on their respective roles.\n\nKey additions:\n\n * A new txclk control module (`ice_txclk.c`) implementing:\n - software usage tracking for each reference clock per PHY,\n - peer‑PHY enable rules (SyncE required on both PHYs when used on\n PHY0, EREF0 required on both when used on PHY1),\n - safe disabling of unused reference clocks after switching,\n - a single, driver‑internal entry point for clock changes.\n\n * Integration with the DPLL pin ops:\n - pin‑set now calls into `ice_txclk_set_clk()` to request a\n hardware switch,\n - pin‑get reports the current SERDES reference by reading back the\n active selector (`ice_get_serdes_ref_sel_e825c()`).\n\n * Wiring the requested reference clock into Auto‑Negotiation restart\n through the already‑extended `ice_aq_set_link_restart_an()`.\n\n * After each link-up the driver verifies the effective hardware state\n (`ice_txclk_verify()`) and updates its per‑PHY usage bitmaps,\n correcting the requested/active state if the FW or AN flow applied a\n different reference.\n\n * PTP PF initialization now seeds the ENET reference clock as enabled\n by default for its port.\n\nAll reference clock transitions are serialized through the DPLL lock,\nand usage information is shared across all PFs belonging to the\nsame E825C controller PF. This ensures that concurrent changes are\ncoordinated and that shared PHYs never see an unexpected disable.\n\nWith this patch, E825 devices gain full userspace‑driven TXC reference\nclock selection via the DPLL subsystem, enabling complete SyncE support,\nprecise multi‑clock setups, and predictable clock routing behavior.\n\nReviewed-by: Arkadiusz Kubalewski <arkadiusz.kubalewski@intel.com>\nSigned-off-by: Grzegorz Nitka <grzegorz.nitka@intel.com>\n---\n drivers/net/ethernet/intel/ice/Makefile | 2 +-\n drivers/net/ethernet/intel/ice/ice.h | 12 +\n drivers/net/ethernet/intel/ice/ice_dpll.c | 53 +++-\n drivers/net/ethernet/intel/ice/ice_ptp.c | 27 ++-\n drivers/net/ethernet/intel/ice/ice_ptp.h | 7 +\n drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 37 +++\n drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 27 +++\n drivers/net/ethernet/intel/ice/ice_txclk.c | 256 ++++++++++++++++++++\n drivers/net/ethernet/intel/ice/ice_txclk.h | 41 ++++\n 9 files changed, 445 insertions(+), 17 deletions(-)\n create mode 100644 drivers/net/ethernet/intel/ice/ice_txclk.c\n create mode 100644 drivers/net/ethernet/intel/ice/ice_txclk.h", "diff": "diff --git a/drivers/net/ethernet/intel/ice/Makefile b/drivers/net/ethernet/intel/ice/Makefile\nindex 38db476ab2ec..95fd0c49800f 100644\n--- a/drivers/net/ethernet/intel/ice/Makefile\n+++ b/drivers/net/ethernet/intel/ice/Makefile\n@@ -54,7 +54,7 @@ ice-$(CONFIG_PCI_IOV) +=\t\\\n \tice_vf_mbx.o\t\t\\\n \tice_vf_vsi_vlan_ops.o\t\\\n \tice_vf_lib.o\n-ice-$(CONFIG_PTP_1588_CLOCK) += ice_ptp.o ice_ptp_hw.o ice_dpll.o ice_tspll.o ice_cpi.o\n+ice-$(CONFIG_PTP_1588_CLOCK) += ice_ptp.o ice_ptp_hw.o ice_dpll.o ice_tspll.o ice_cpi.o ice_txclk.o\n ice-$(CONFIG_DCB) += ice_dcb.o ice_dcb_nl.o ice_dcb_lib.o\n ice-$(CONFIG_RFS_ACCEL) += ice_arfs.o\n ice-$(CONFIG_XDP_SOCKETS) += ice_xsk.o\ndiff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h\nindex 2b2b22af42be..b42df789295f 100644\n--- a/drivers/net/ethernet/intel/ice/ice.h\n+++ b/drivers/net/ethernet/intel/ice/ice.h\n@@ -1133,4 +1133,16 @@ static inline struct ice_hw *ice_get_primary_hw(struct ice_pf *pf)\n \telse\n \t\treturn &pf->adapter->ctrl_pf->hw;\n }\n+\n+/**\n+ * ice_get_ctrl_pf - Get pointer to Control PF of the adapter\n+ * @pf: pointer to the current PF structure\n+ *\n+ * Return: A pointer to ice_pf structure which is Control PF,\n+ * NULL if it's not initialized yet.\n+ */\n+static inline struct ice_pf *ice_get_ctrl_pf(struct ice_pf *pf)\n+{\n+\treturn !pf->adapter ? NULL : pf->adapter->ctrl_pf;\n+}\n #endif /* _ICE_H_ */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_dpll.c b/drivers/net/ethernet/intel/ice/ice_dpll.c\nindex 72518fd1398d..ac0bfc2f0f0e 100644\n--- a/drivers/net/ethernet/intel/ice/ice_dpll.c\n+++ b/drivers/net/ethernet/intel/ice/ice_dpll.c\n@@ -4,6 +4,7 @@\n #include \"ice.h\"\n #include \"ice_lib.h\"\n #include \"ice_trace.h\"\n+#include \"ice_txclk.h\"\n #include <linux/dpll.h>\n #include <linux/property.h>\n \n@@ -2538,7 +2539,9 @@ ice_dpll_rclk_state_on_pin_get(const struct dpll_pin *pin, void *pin_priv,\n *\n * Dpll subsystem callback, set a state of a Tx reference clock pin\n *\n+ * Context: Acquires and releases pf->dplls.lock\n * Return:\n+ * * 0 - success\n * * negative - failure\n */\n static int\n@@ -2547,11 +2550,24 @@ ice_dpll_txclk_state_on_dpll_set(const struct dpll_pin *pin, void *pin_priv,\n \t\t\t\t void *dpll_priv, enum dpll_pin_state state,\n \t\t\t\t struct netlink_ext_ack *extack)\n {\n-\t/*\n-\t * TODO: set HW accordingly to selected TX reference clock.\n-\t * To be added in the follow up patches.\n-\t */\n-\treturn -EOPNOTSUPP;\n+\tstruct ice_dpll_pin *p = pin_priv;\n+\tstruct ice_pf *pf = p->pf;\n+\tenum ice_e825c_ref_clk new_clk;\n+\tint ret = 0;\n+\n+\tif (ice_dpll_is_reset(pf, extack))\n+\t\treturn -EBUSY;\n+\n+\tmutex_lock(&pf->dplls.lock);\n+\tnew_clk = (state == DPLL_PIN_STATE_DISCONNECTED) ? ICE_REF_CLK_ENET :\n+\t\t\tp->tx_ref_src;\n+\tif (new_clk == pf->ptp.port.tx_clk)\n+\t\tgoto unlock;\n+\n+\tret = ice_txclk_set_clk(pf, new_clk);\n+unlock:\n+\tmutex_unlock(&pf->dplls.lock);\n+\treturn ret;\n }\n \n /**\n@@ -2565,8 +2581,10 @@ ice_dpll_txclk_state_on_dpll_set(const struct dpll_pin *pin, void *pin_priv,\n *\n * dpll subsystem callback, get a state of a TX clock reference pin.\n *\n+ * Context: Acquires and releases pf->dplls.lock\n * Return:\n * * 0 - success\n+ * * negative - failure\n */\n static int\n ice_dpll_txclk_state_on_dpll_get(const struct dpll_pin *pin, void *pin_priv,\n@@ -2575,13 +2593,26 @@ ice_dpll_txclk_state_on_dpll_get(const struct dpll_pin *pin, void *pin_priv,\n \t\t\t\t enum dpll_pin_state *state,\n \t\t\t\t struct netlink_ext_ack *extack)\n {\n-\t/*\n-\t * TODO: query HW status to determine if the TX reference is selected.\n-\t * To be added in the follow up patches.\n-\t */\n-\t*state = DPLL_PIN_STATE_DISCONNECTED;\n+\tstruct ice_dpll_pin *p = pin_priv;\n+\tenum ice_e825c_ref_clk clk;\n+\tstruct ice_pf *pf = p->pf;\n+\tint ret;\n \n-\treturn 0;\n+\tif (ice_dpll_is_reset(pf, extack))\n+\t\treturn -EBUSY;\n+\n+\tmutex_lock(&pf->dplls.lock);\n+\tret = ice_get_serdes_ref_sel_e825c(&pf->hw, pf->ptp.port.port_num,\n+\t\t\t\t\t &clk);\n+\tif (ret)\n+\t\tgoto unlock;\n+\n+\t*state = (clk == p->tx_ref_src) ? DPLL_PIN_STATE_CONNECTED :\n+\t\t\tDPLL_PIN_STATE_DISCONNECTED;\n+unlock:\n+\tmutex_unlock(&pf->dplls.lock);\n+\n+\treturn ret;\n }\n \n static const struct dpll_pin_ops ice_dpll_rclk_ops = {\ndiff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c\nindex 094e96219f45..a75a1380097b 100644\n--- a/drivers/net/ethernet/intel/ice/ice_ptp.c\n+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c\n@@ -4,6 +4,7 @@\n #include \"ice.h\"\n #include \"ice_lib.h\"\n #include \"ice_trace.h\"\n+#include \"ice_txclk.h\"\n \n static const char ice_pin_names[][64] = {\n \t\"SDP0\",\n@@ -54,11 +55,6 @@ static const struct ice_ptp_pin_desc ice_pin_desc_dpll[] = {\n \t{ SDP3, { 3, -1 }, { 0, 0 }},\n };\n \n-static struct ice_pf *ice_get_ctrl_pf(struct ice_pf *pf)\n-{\n-\treturn !pf->adapter ? NULL : pf->adapter->ctrl_pf;\n-}\n-\n static struct ice_ptp *ice_get_ctrl_ptp(struct ice_pf *pf)\n {\n \tstruct ice_pf *ctrl_pf = ice_get_ctrl_pf(pf);\n@@ -1325,6 +1321,10 @@ void ice_ptp_link_change(struct ice_pf *pf, bool linkup)\n \t\t\t\treturn;\n \t\t\t}\n \t\t}\n+\n+\t\tif (linkup)\n+\t\t\tice_txclk_verify(pf);\n+\n \t\tmutex_unlock(&pf->dplls.lock);\n \t}\n \n@@ -3079,6 +3079,7 @@ static int ice_ptp_setup_pf(struct ice_pf *pf)\n {\n \tstruct ice_ptp *ctrl_ptp = ice_get_ctrl_ptp(pf);\n \tstruct ice_ptp *ptp = &pf->ptp;\n+\tu8 port_num, phy;\n \n \tif (WARN_ON(!ctrl_ptp) || pf->hw.mac_type == ICE_MAC_UNKNOWN)\n \t\treturn -ENODEV;\n@@ -3090,6 +3091,10 @@ static int ice_ptp_setup_pf(struct ice_pf *pf)\n \t\t &pf->adapter->ports.ports);\n \tmutex_unlock(&pf->adapter->ports.lock);\n \n+\tport_num = ptp->port.port_num;\n+\tphy = port_num / pf->hw.ptp.ports_per_phy;\n+\tset_bit(port_num, &ctrl_ptp->tx_refclks[phy][pf->ptp.port.tx_clk]);\n+\n \treturn 0;\n }\n \n@@ -3290,6 +3295,7 @@ static void ice_ptp_init_tx_interrupt_mode(struct ice_pf *pf)\n */\n void ice_ptp_init(struct ice_pf *pf)\n {\n+\tenum ice_e825c_ref_clk tx_ref_clk;\n \tstruct ice_ptp *ptp = &pf->ptp;\n \tstruct ice_hw *hw = &pf->hw;\n \tint err;\n@@ -3318,6 +3324,17 @@ void ice_ptp_init(struct ice_pf *pf)\n \t\t\tgoto err_exit;\n \t}\n \n+\tptp->port.tx_clk = ICE_REF_CLK_ENET;\n+\tptp->port.tx_clk_req = ICE_REF_CLK_ENET;\n+\tif (hw->mac_type == ICE_MAC_GENERIC_3K_E825) {\n+\t\terr = ice_get_serdes_ref_sel_e825c(hw, ptp->port.port_num,\n+\t\t\t\t\t\t &tx_ref_clk);\n+\t\tif (!err) {\n+\t\t\tptp->port.tx_clk = tx_ref_clk;\n+\t\t\tptp->port.tx_clk_req = tx_ref_clk;\n+\t\t}\n+\t}\n+\n \terr = ice_ptp_setup_pf(pf);\n \tif (err)\n \t\tgoto err_exit;\ndiff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h\nindex 8c44bd758a4f..8b385271ab36 100644\n--- a/drivers/net/ethernet/intel/ice/ice_ptp.h\n+++ b/drivers/net/ethernet/intel/ice/ice_ptp.h\n@@ -144,6 +144,8 @@ struct ice_ptp_tx {\n * @link_up: indicates whether the link is up\n * @tx_fifo_busy_cnt: number of times the Tx FIFO was busy\n * @port_num: the port number this structure represents\n+ * @tx_clk: currently active Tx reference clock source\n+ * @tx_clk_req: requested Tx reference clock source (new target)\n */\n struct ice_ptp_port {\n \tstruct list_head list_node;\n@@ -153,6 +155,8 @@ struct ice_ptp_port {\n \tbool link_up;\n \tu8 tx_fifo_busy_cnt;\n \tu8 port_num;\n+\tenum ice_e825c_ref_clk tx_clk;\n+\tenum ice_e825c_ref_clk tx_clk_req;\n };\n \n enum ice_ptp_tx_interrupt {\n@@ -236,6 +240,7 @@ struct ice_ptp_pin_desc {\n * @info: structure defining PTP hardware capabilities\n * @clock: pointer to registered PTP clock device\n * @tstamp_config: hardware timestamping configuration\n+ * @tx_refclks: bitmaps table to store the information about TX reference clocks\n * @reset_time: kernel time after clock stop on reset\n * @tx_hwtstamp_good: number of completed Tx timestamp requests\n * @tx_hwtstamp_skipped: number of Tx time stamp requests skipped\n@@ -261,6 +266,8 @@ struct ice_ptp {\n \tstruct ptp_clock_info info;\n \tstruct ptp_clock *clock;\n \tstruct kernel_hwtstamp_config tstamp_config;\n+#define ICE_E825_MAX_PHYS 2\n+\tunsigned long tx_refclks[ICE_E825_MAX_PHYS][ICE_REF_CLK_MAX];\n \tu64 reset_time;\n \tu64 tx_hwtstamp_good;\n \tu32 tx_hwtstamp_skipped;\ndiff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c\nindex 61c0a0d93ea8..c0720525ac49 100644\n--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c\n+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c\n@@ -461,6 +461,43 @@ static int ice_read_phy_eth56g(struct ice_hw *hw, u8 port, u32 addr, u32 *val)\n \treturn err;\n }\n \n+/**\n+ * ice_get_serdes_ref_sel_e825c - Read current Tx ref clock source\n+ * @hw: pointer to the HW struct\n+ * @port: port number for which Tx reference clock is read\n+ * @clk: Tx reference clock value (output)\n+ *\n+ * Return: 0 on success, other error codes when failed to read from PHY\n+ */\n+int ice_get_serdes_ref_sel_e825c(struct ice_hw *hw, u8 port,\n+\t\t\t\t enum ice_e825c_ref_clk *clk)\n+{\n+\tu8 lane = port % hw->ptp.ports_per_phy;\n+\tu32 serdes_rx_nt, serdes_tx_nt;\n+\tu32 val;\n+\tint ret;\n+\n+\tret = ice_read_phy_eth56g(hw, port,\n+\t\t\t\t SERDES_IP_IF_LN_FLXM_GENERAL(lane, 0),\n+\t\t\t\t &val);\n+\tif (ret)\n+\t\treturn ret;\n+\n+\tserdes_rx_nt = FIELD_GET(CFG_ICTL_PCS_REF_SEL_RX_NT, val);\n+\tserdes_tx_nt = FIELD_GET(CFG_ICTL_PCS_REF_SEL_TX_NT, val);\n+\n+\tif (serdes_tx_nt == REF_SEL_NT_SYNCE &&\n+\t serdes_rx_nt == REF_SEL_NT_SYNCE)\n+\t\t*clk = ICE_REF_CLK_SYNCE;\n+\telse if (serdes_tx_nt == REF_SEL_NT_EREF0 &&\n+\t\t serdes_rx_nt == REF_SEL_NT_EREF0)\n+\t\t*clk = ICE_REF_CLK_EREF0;\n+\telse\n+\t\t*clk = ICE_REF_CLK_ENET;\n+\n+\treturn 0;\n+}\n+\n /**\n * ice_phy_res_address_eth56g - Calculate a PHY port register address\n * @hw: pointer to the HW struct\ndiff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h\nindex cbc9693179a1..820ba953ea01 100644\n--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h\n+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h\n@@ -381,6 +381,8 @@ int ice_stop_phy_timer_eth56g(struct ice_hw *hw, u8 port, bool soft_reset);\n int ice_start_phy_timer_eth56g(struct ice_hw *hw, u8 port);\n int ice_phy_cfg_intr_eth56g(struct ice_hw *hw, u8 port, bool ena, u8 threshold);\n int ice_phy_cfg_ptp_1step_eth56g(struct ice_hw *hw, u8 port);\n+int ice_get_serdes_ref_sel_e825c(struct ice_hw *hw, u8 port,\n+\t\t\t\t enum ice_e825c_ref_clk *clk);\n \n #define ICE_ETH56G_NOMINAL_INCVAL\t0x140000000ULL\n #define ICE_ETH56G_NOMINAL_PCS_REF_TUS\t0x100000000ULL\n@@ -790,4 +792,29 @@ static inline u64 ice_get_base_incval(struct ice_hw *hw)\n #define PHY_PTP_1STEP_PD_DELAY_M\tGENMASK(30, 1)\n #define PHY_PTP_1STEP_PD_DLY_V_M\tBIT(31)\n \n+#define SERDES_IP_IF_LN_FLXM_GENERAL(n, m) \\\n+\t(0x32B800 + (m) * 0x100000 + (n) * 0x8000)\n+#define CFG_RESERVED0_1 GENMASK(1, 0)\n+#define CFG_ICTL_PCS_MODE_NT BIT(2)\n+#define CFG_ICTL_PCS_RCOMP_SLAVE_EN_NT BIT(3)\n+#define CFG_ICTL_PCS_CMN_FORCE_PUP_A BIT(4)\n+#define CFG_ICTL_PCS_RCOMP_SLAVE_VALID_A BIT(5)\n+#define CFG_ICTL_PCS_REF_SEL_RX_NT GENMASK(9, 6)\n+#define REF_SEL_NT_ENET 0\n+#define REF_SEL_NT_EREF0 1\n+#define REF_SEL_NT_SYNCE 2\n+#define CFG_IDAT_DFX_OBS_DIG_ GENMASK(11, 10)\n+#define CFG_IRST_APB_MEM_B BIT(12)\n+#define CFG_ICTL_PCS_DISCONNECT_NT BIT(13)\n+#define CFG_ICTL_PCS_ISOLATE_NT BIT(14)\n+#define CFG_RESERVED15_15 BIT(15)\n+#define CFG_IRST_PCS_TSTBUS_B_A BIT(16)\n+#define CFG_ICTL_PCS_REF_TERM_HIZ_EN_NT BIT(17)\n+#define CFG_RESERVED18_19 GENMASK(19, 18)\n+#define CFG_ICTL_PCS_SYNTHLCSLOW_FORCE_PUP_A BIT(20)\n+#define CFG_ICTL_PCS_SYNTHLCFAST_FORCE_PUP_A BIT(21)\n+#define CFG_RESERVED22_24 GENMASK(24, 22)\n+#define CFG_ICTL_PCS_REF_SEL_TX_NT GENMASK(28, 25)\n+#define CFG_RESERVED29_31 GENMASK(31, 29)\n+\n #endif /* _ICE_PTP_HW_H_ */\ndiff --git a/drivers/net/ethernet/intel/ice/ice_txclk.c b/drivers/net/ethernet/intel/ice/ice_txclk.c\nnew file mode 100644\nindex 000000000000..ccb8411dca94\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/ice/ice_txclk.c\n@@ -0,0 +1,256 @@\n+// SPDX-License-Identifier: GPL-2.0\n+/* Copyright (C) 2026 Intel Corporation */\n+\n+#include \"ice.h\"\n+#include \"ice_cpi.h\"\n+#include \"ice_txclk.h\"\n+\n+#define ICE_PHY0\t0\n+#define ICE_PHY1\t1\n+\n+/**\n+ * ice_txclk_enable_peer - Enable required TX reference clock on peer PHY\n+ * @pf: pointer to the PF structure\n+ * @clk: TX reference clock that must be enabled\n+ *\n+ * Some TX reference clocks on E825-class devices (SyncE and EREF0) must\n+ * be enabled on both PHY complexes to allow proper routing:\n+ *\n+ * - SyncE must be enabled on both PHYs when used by PHY0\n+ * - EREF0 must be enabled on both PHYs when used by PHY1\n+ *\n+ * If the requested clock is not yet enabled on the peer PHY, enable it.\n+ * ENET does not require duplication and is ignored.\n+ *\n+ * Return: 0 on success or negative error code on failure.\n+ */\n+static int ice_txclk_enable_peer(struct ice_pf *pf, enum ice_e825c_ref_clk clk)\n+{\n+\tstruct ice_pf *ctrl_pf = ice_get_ctrl_pf(pf);\n+\tu8 port_num, phy;\n+\tint err;\n+\n+\tif (clk == ICE_REF_CLK_ENET)\n+\t\treturn 0;\n+\n+\tif (IS_ERR_OR_NULL(ctrl_pf)) {\n+\t\tdev_err(ice_pf_to_dev(pf),\n+\t\t\t\"Can't enable tx-clk on peer: no controlling PF\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tport_num = pf->ptp.port.port_num;\n+\tphy = port_num / pf->hw.ptp.ports_per_phy;\n+\n+\tif ((clk == ICE_REF_CLK_SYNCE && phy == ICE_PHY0 &&\n+\t !ice_txclk_any_port_uses(ctrl_pf, ICE_PHY1, clk)) ||\n+\t (clk == ICE_REF_CLK_EREF0 && phy == ICE_PHY1 &&\n+\t !ice_txclk_any_port_uses(ctrl_pf, ICE_PHY0, clk))) {\n+\t\tu8 peer_phy = phy ? ICE_PHY0 : ICE_PHY1;\n+\n+\t\terr = ice_cpi_ena_dis_clk_ref(&pf->hw, peer_phy, clk, true);\n+\t\tif (err) {\n+\t\t\tdev_err(ice_hw_to_dev(&pf->hw),\n+\t\t\t\t\"Failed to enable the %u TX clock for the %u PHY\\n\",\n+\t\t\t\tclk, peer_phy);\n+\t\t\treturn err;\n+\t\t}\n+\t}\n+\n+\treturn 0;\n+}\n+\n+/**\n+ * ice_txclk_disable_unused - Disable TX reference clock no longer in use\n+ * @pf: pointer to the PF structure\n+ * @ref_clk: TX reference clock source to evaluate for disabling\n+ *\n+ * Disable (from power-saving reasons) a TX reference clock after a clock\n+ * switch, provided that:\n+ * - no port on the local PHY uses this clock, and\n+ * - for SyncE: no port on PHY0 or PHY1 requires the clock, depending on\n+ * where it must remain enabled for routing.\n+ * - for EREF0: same logic as above but inverted PHY roles.\n+ *\n+ * Some reference clocks must be enabled on both PHY complexes when used\n+ * (SyncE for PHY0, EREF0 for PHY1). The function therefore also attempts\n+ * to implicitly disable the peer PHY copy when no port requires it.\n+ *\n+ * Return: 0 on success or negative error code if disabling fails.\n+ */\n+static int\n+ice_txclk_disable_unused(struct ice_pf *pf, enum ice_e825c_ref_clk ref_clk)\n+{\n+\tstruct ice_pf *ctrl_pf = ice_get_ctrl_pf(pf);\n+\tstruct ice_hw *hw = &pf->hw;\n+\tint err = 0;\n+\tu8 cur_phy;\n+\n+\tif (IS_ERR_OR_NULL(ctrl_pf)) {\n+\t\tdev_err(ice_pf_to_dev(pf),\n+\t\t\t\"Can't disable unused tx-clk: no controlling PF\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tcur_phy = pf->ptp.port.port_num / hw->ptp.ports_per_phy;\n+\n+\tif (ref_clk == ICE_REF_CLK_SYNCE) {\n+\t\t/* Don't disable SyncE clock if it's still in use on PHY 0 */\n+\t\tif (ice_txclk_any_port_uses(ctrl_pf, ICE_PHY0, ref_clk))\n+\t\t\treturn 0;\n+\t\tif (cur_phy == ICE_PHY0 &&\n+\t\t !ice_txclk_any_port_uses(ctrl_pf, ICE_PHY1, ref_clk)) {\n+\t\t\terr = ice_cpi_ena_dis_clk_ref(hw, ICE_PHY1, ref_clk,\n+\t\t\t\t\t\t false);\n+\t\t\tif (err) {\n+\t\t\t\tcur_phy = ICE_PHY1;\n+\t\t\t\tgoto err;\n+\t\t\t}\n+\t\t}\n+\t} else if (ref_clk == ICE_REF_CLK_EREF0) {\n+\t\t/* Don't disable EREF0 clock if it's still in use on PHY 1 */\n+\t\tif (ice_txclk_any_port_uses(ctrl_pf, ICE_PHY1, ref_clk))\n+\t\t\treturn 0;\n+\t\tif (cur_phy == ICE_PHY1 &&\n+\t\t !ice_txclk_any_port_uses(ctrl_pf, ICE_PHY0, ref_clk)) {\n+\t\t\terr = ice_cpi_ena_dis_clk_ref(hw, ICE_PHY0, ref_clk,\n+\t\t\t\t\t\t false);\n+\t\t\tif (err) {\n+\t\t\t\tcur_phy = ICE_PHY0;\n+\t\t\t\tgoto err;\n+\t\t\t}\n+\t\t}\n+\t}\n+\n+\tif (!ice_txclk_any_port_uses(ctrl_pf, cur_phy, ref_clk))\n+\t\terr = ice_cpi_ena_dis_clk_ref(hw, cur_phy, ref_clk, false);\n+err:\n+\tif (err)\n+\t\tdev_warn(ice_pf_to_dev(pf), \"Failed to disable the %u TX clock for the %u PHY\\n\",\n+\t\t\t ref_clk, cur_phy);\n+\n+\treturn err;\n+}\n+\n+#define ICE_REFCLK_USER_TO_AQ_IDX(x) ((x) + 1)\n+\n+/**\n+ * ice_txclk_set_clk - Set Tx reference clock\n+ * @pf: pointer to pf structure\n+ * @clk: new Tx clock\n+ *\n+ * Return: 0 on success, negative value otherwise.\n+ */\n+int ice_txclk_set_clk(struct ice_pf *pf, enum ice_e825c_ref_clk clk)\n+{\n+\tstruct ice_pf *ctrl_pf = ice_get_ctrl_pf(pf);\n+\tstruct ice_port_info *port_info;\n+\tu8 port_num, phy;\n+\tint err;\n+\n+\tif (pf->ptp.port.tx_clk == clk)\n+\t\treturn 0;\n+\n+\tif (IS_ERR_OR_NULL(ctrl_pf)) {\n+\t\tdev_err(ice_pf_to_dev(pf),\n+\t\t\t\"Can't set tx-clk: no controlling PF\\n\");\n+\t\treturn -EINVAL;\n+\t}\n+\n+\tport_num = pf->ptp.port.port_num;\n+\tphy = port_num / pf->hw.ptp.ports_per_phy;\n+\tport_info = pf->hw.port_info;\n+\n+\t/* Check if the TX clk is enabled for this PHY, if not - enable it */\n+\tif (!ice_txclk_any_port_uses(ctrl_pf, phy, clk)) {\n+\t\terr = ice_cpi_ena_dis_clk_ref(&pf->hw, phy, clk, true);\n+\t\tif (err) {\n+\t\t\tdev_err(ice_hw_to_dev(&pf->hw), \"Failed to enable the %u TX clock for the %u PHY\\n\",\n+\t\t\t\tclk, phy);\n+\t\t\treturn err;\n+\t\t}\n+\t\terr = ice_txclk_enable_peer(pf, clk);\n+\t\tif (err)\n+\t\t\treturn err;\n+\t}\n+\n+\tpf->ptp.port.tx_clk_req = clk;\n+\n+\t/* We are ready to switch to the new TX clk. */\n+\terr = ice_aq_set_link_restart_an(port_info, true, NULL,\n+\t\t\t\t\t ICE_REFCLK_USER_TO_AQ_IDX(clk));\n+\tif (err)\n+\t\tdev_err(ice_hw_to_dev(&pf->hw), \"Failed to switch to %u TX clock for the %u PHY\\n\",\n+\t\t\tclk, phy);\n+\n+\treturn err;\n+}\n+\n+/**\n+ * ice_txclk_verify - Validate TX reference clock switch and update usage state\n+ * @pf: pointer to PF structure\n+ *\n+ * After a link-up event, verify whether the previously requested TX reference\n+ * clock transition actually succeeded. The SERDES reference selector reflects\n+ * the effective hardware choice, which may differ from the requested clock\n+ * when Auto-Negotiation or firmware applies additional policy.\n+ *\n+ * If the hardware-selected clock differs from the requested one, update the\n+ * software state accordingly and stop further processing.\n+ *\n+ * When the switch is successful, update the per‑PHY usage bitmaps so that the\n+ * driver knows which reference clock is currently in use by this port. Using\n+ * these bitmaps, disable any reference clocks that are no longer required by\n+ * any port on the local PHY or, when applicable, on the peer PHY (according\n+ * to E825 clock‑routing rules).\n+ *\n+ * This function does not initiate a clock switch; it only validates the result\n+ * of a previously triggered transition and performs cleanup of unused clocks.\n+ */\n+void ice_txclk_verify(struct ice_pf *pf)\n+{\n+\tstruct ice_ptp_port *ptp_port = &pf->ptp.port;\n+\tstruct ice_pf *ctrl_pf = ice_get_ctrl_pf(pf);\n+\tstruct ice_hw *hw = &pf->hw;\n+\tenum ice_e825c_ref_clk clk;\n+\tint err;\n+\tu8 phy;\n+\n+\tphy = ptp_port->port_num / hw->ptp.ports_per_phy;\n+\n+\t/* verify current Tx reference settings */\n+\terr = ice_get_serdes_ref_sel_e825c(hw,\n+\t\t\t\t\t ptp_port->port_num,\n+\t\t\t\t\t &clk);\n+\tif (err)\n+\t\treturn;\n+\n+\tif (clk != pf->ptp.port.tx_clk_req) {\n+\t\tdev_warn(ice_pf_to_dev(pf),\n+\t\t\t \"Failed to switch tx-clk for phy %d and clk %u (current: %u)\\n\",\n+\t\t\t phy, pf->ptp.port.tx_clk_req, clk);\n+\t\tpf->ptp.port.tx_clk = clk;\n+\t\tpf->ptp.port.tx_clk_req = clk;\n+\t\treturn;\n+\t}\n+\n+\tif (IS_ERR_OR_NULL(ctrl_pf)) {\n+\t\tdev_err(ice_pf_to_dev(pf),\n+\t\t\t\"Can't set tx-clk: no controlling PF\\n\");\n+\t\treturn;\n+\t}\n+\n+\t/* update Tx reference clock usage map */\n+\tfor (int i = 0; i < ICE_REF_CLK_MAX; i++)\n+\t\t(clk == i) ?\n+\t\t set_bit(ptp_port->port_num,\n+\t\t\t &ctrl_pf->ptp.tx_refclks[phy][i]) :\n+\t\t clear_bit(ptp_port->port_num,\n+\t\t\t &ctrl_pf->ptp.tx_refclks[phy][i]);\n+\n+\tice_txclk_disable_unused(pf, pf->ptp.port.tx_clk);\n+\n+\tpf->ptp.port.tx_clk = clk;\n+\tpf->ptp.port.tx_clk_req = clk;\n+}\n+\ndiff --git a/drivers/net/ethernet/intel/ice/ice_txclk.h b/drivers/net/ethernet/intel/ice/ice_txclk.h\nnew file mode 100644\nindex 000000000000..6423b448841e\n--- /dev/null\n+++ b/drivers/net/ethernet/intel/ice/ice_txclk.h\n@@ -0,0 +1,41 @@\n+/* SPDX-License-Identifier: GPL-2.0 */\n+/* Copyright (C) 2026 Intel Corporation */\n+\n+#ifndef _ICE_TXCLK_H_\n+#define _ICE_TXCLK_H_\n+\n+/**\n+ * ice_txclk_any_port_uses - check if any port on a PHY uses this TX refclk\n+ * @ctrl_pf: control PF (owner of the shared tx_refclks map)\n+ * @phy: PHY index\n+ * @clk: TX reference clock\n+ *\n+ * Return: true if any bit (port) is set for this clock on this PHY\n+ */\n+static inline bool\n+ice_txclk_any_port_uses(const struct ice_pf *ctrl_pf, u8 phy,\n+\t\t\tenum ice_e825c_ref_clk clk)\n+{\n+\treturn find_first_bit(&ctrl_pf->ptp.tx_refclks[phy][clk],\n+\t\t\tBITS_PER_LONG) < BITS_PER_LONG;\n+}\n+\n+/**\n+ * ice_txclk_port_uses - check if a specific port uses this TX refclk\n+ * @ctrl_pf: control PF\n+ * @phy: PHY index\n+ * @clk: TX reference clock\n+ * @port: port number to test\n+ *\n+ * Return: true if this port uses the given clock\n+ */\n+static inline bool\n+ice_txclk_port_uses(const struct ice_pf *ctrl_pf, u8 phy,\n+\t\t enum ice_e825c_ref_clk clk, u8 port)\n+{\n+\treturn test_bit(port, &ctrl_pf->ptp.tx_refclks[phy][clk]);\n+}\n+\n+int ice_txclk_set_clk(struct ice_pf *pf, enum ice_e825c_ref_clk clk);\n+void ice_txclk_verify(struct ice_pf *pf);\n+#endif /* _ICE_TXCLK_H_ */\n", "prefixes": [ "v4", "net-next", "8/8" ] }