From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 3EC2BC55175 for ; Sat, 1 Aug 2026 14:23:27 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:Cc:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=EnSjpb2yPJh8Gi00ZiQk7FFLPjfOPWRR7GVm5XU+Sug=; b=xoNA3oVYAWDsnI jnNuQMafzH7Um0a5qOHkD4CxsHAy93Sewcm11Q/WiRlqOCW6J6m5/IEU6GG04Nu6q4etiMR6MZr8J MMVHcSeFlTvnYtrQuexez1Tx++Dx5zxMXmz2VR1EMkuGRme2ukiOV5RjCBmbf3UCtfSJC3m76gQ2M bBLWoyCaSRfuiQLHFnyj503ELefnS9PCbSKIfxXcIZlwnkVheTt7eZoK1IdogSuzOjL9cBxLpxYEJ sEDUrRyuae1/jGhTU8Onk3SMCWHXgjSRU2GHoQwKvJAwdsCceHheKdbfgYCi3NJWpP4SjtC2NE123 BUSM3H2jFMN1/kBRaagA==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1wqAcY-0000000EiNg-3uNH; Sat, 01 Aug 2026 14:23:26 +0000 Received: from mail-pj2-x03.google.com ([2607:f8b0:4864:39::3]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1wqAcT-0000000EiJy-1PXF for linux-phy@lists.infradead.org; Sat, 01 Aug 2026 14:23:23 +0000 Received: by mail-pj2-x03.google.com with SMTP id d9443c01a7336-2ccb0e85312so11214855ad.0 for ; Sat, 01 Aug 2026 07:23:20 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1785594200; x=1786199000; darn=lists.infradead.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:from:to:cc:subject:date :message-id:reply-to:content-type; bh=6YxJTLfbFLaJQNrdCTWQsfkF0vgcKN1ElhQsDv7wQJw=; b=jxQB/pIUIMTXdFYcLWxmM9u6quX+dBDrGrw7xbQXRq5A3Ca3izifAPW9Ux9YGfnCPs 1S4Ria69kROBbADxLFL0PrQ7Ofynf105ZNwO3HQZJ1qI/n6NE7bMvvbQsU68bHPbLO9p clb7L61lI32HdrTo7BQuy6gt38kDFwi0Tu8iXj9v35tZHscCLxaYeORUnYzHyM2nf4GU bNb4Yru9RzNtUODrE8MljFvMARCsvIdaInW/WjyUOS7sRko0J902pBxZmVDxI2mZ3wW0 6KGOIniLOSaIhh7EzRPZgVFVUSxV95kLq6nn1uF9ZNctkpCIOX7aNF5htrNJ+5jc6nnL 7CdQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1785594200; x=1786199000; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:cc:to:from:x-gm-gg:x-gm-message-state:from :to:cc:subject:date:message-id:reply-to:content-type; bh=6YxJTLfbFLaJQNrdCTWQsfkF0vgcKN1ElhQsDv7wQJw=; b=ZZTilVfZSfoADVTeny6ZSiFQrfrQM/mAGMmcAgB+GDRi7JOgWpfBCTbjDOvHMOQyzU qZg9jJsDH6qpqpC6Eynq2RdNdjpcV+RLcSLpKq0B8uWsCrHmdqaklh2fBKPcjAJRz7+2 6IHh4/xfv2RALkcDwIEfYdtCHzHkYWzmbikRq/DtWBd2yMnSc/O8DyBa/iTxKLf+wL9/ B7/aNYwpsUJeXN7f8BMjLiGdRzK+LpFhqOgVQUKyWH23WyjFBUhmXCDzkSEwd9nneDEI zrzLlFMjeNAw4amd+1kYcYD5R4/oRkTGPrm2n71PcbJVAOSEakM6QB4YQE/4FYGbCN+c TmoA== X-Forwarded-Encrypted: i=1; AHgh+Rr99ru98TPnwz3Oe3tqhIKBzA071nyezKDMHHycyuvcDsukzca8BFdmYwaSukn/CpvpbMpan8Tm/Zs=@lists.infradead.org X-Gm-Message-State: AOJu0YxMW6Bkh5D65wo13DfSoJbUKni/i14WqIMX73Ma66A7j2mf2VUT zPHrQXtJrRBMznAZrSi8dqfSFMvpaQFaX2CV5OUWpGDrPDW5yyOhyX5hLWYmoD2yYQs/gc78 X-Gm-Gg: AR+sD10u+Gy/SGqKI6p6O660etjt7kgbXxtvK2qvDv8ZpeLzE3yx9GYCJAgnjhrfY8w rrCD89u7UBGsmzAqZo+qRltGbJt2z5vNvCohOiAgtK6F7wiKZA2x1B9wu6XoXURVi8OHv05nLt6 Ub+8tQ5SoYa7DSyQmvvgYApUvNRUm2o6ljUAPunPMydeo+Sqy7VdtqitO37TJEZ9SSxqFl89jAB V0hEqJBDQnFYMv4upf6B55DRu6u9dyYPKm6sAiQLKKDt6CoycosWfq1PKktB0B8dHi+zz5rOej4 8U6abHdlSGVDd9L0Vg8L55FvdQ92pjkT5i3zDE9AWPuwfaDhK3AGSigihwvJ2hxlxapZMMnbCMs avAITqxvdHcxww05t8N2pYCu2oMkdCPcsXGQ2LcKDuhScTp8jUeJWrdRHHXOLbXY36PSyJSdMBy dGi52Cjbf0dxSIxQj7ZcK1jHw4rr4urHW1RwwHPESTn9DQ5vA3aVT+dNc= X-Received: by 2002:a17:903:22c3:b0:2cc:9473:97c8 with SMTP id d9443c01a7336-2d0521bc958mr36797725ad.15.1785594200194; Sat, 01 Aug 2026 07:23:20 -0700 (PDT) Received: from server.lan ([103.213.4.16]) by smtp.gmail.com with ESMTPSA id d9443c01a7336-2d04ae5ac3dsm18043845ad.23.2026.08.01.07.23.13 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 01 Aug 2026 07:23:19 -0700 (PDT) From: Coia Prant To: Andrew Lunn , "David S . Miller" , Eric Dumazet , Jakub Kicinski , Paolo Abeni , Rob Herring , Krzysztof Kozlowski , Conor Dooley , Heiko Stuebner , Vinod Koul , Maxime Chevallier , Maxime Coquelin , Alexandre Torgue , Lad Prabhakar , Romain Gantois , Heiner Kallweit , Coia Prant Cc: Neil Armstrong , Russell King , Shawn Lin , David Heidelberg , netdev@vger.kernel.org, linux-rockchip@lists.infradead.org, devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-phy@lists.infradead.org, linux-stm32@st-md-mailman.stormreply.com, linux-renesas-soc@vger.kernel.org Subject: [PATCH v2 01/10] net: stmmac: move XPCS lifetime management to platform drivers Date: Sat, 1 Aug 2026 22:22:25 +0800 Message-ID: <20260801142244.679437-3-coiaprant@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260801142244.679437-2-coiaprant@gmail.com> References: <20260801142244.679437-2-coiaprant@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260801_072321_425656_D1D7A1D0 X-CRM114-Status: GOOD ( 25.46 ) X-BeenThere: linux-phy@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Linux Phy Mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "linux-phy" Errors-To: linux-phy-bounces+linux-phy=archiver.kernel.org@lists.infradead.org The current XPCS creation logic in stmmac_pcs_setup() is problematic for several reasons. First, if a device tree specifies a "pcs-handle" but no select_pcs() callback is provided by the platform driver, the created XPCS is never used. The phylink framework requires select_pcs() to actually return the PCS to the core, so the pcs-handle property becomes effectively useless without the matching callback. This is confusing for developers who expect that specifying a pcs-handle in their device tree should be sufficient to enable the PCS. Second, and more critically, when stmmac_pcs_setup() fails to create an XPCS (either because no pcs-handle is present and no pcs_mask is configured), it falls through to the else branch and leaves priv->hw->xpcs as NULL. This will silently override any XPCS that a platform driver may have already set up during its own initialization, for example in a pcs_init() callback or during probe. The platform driver has no way to prevent this override because the common code runs unconditionally after the platform-specific initialization. After commit 93f84152e4ae ("net: stmmac: clean up stmmac_mac_select_pcs()"), the common code no longer falls back to priv->hw->phylink_pcs if select_pcs() is not set. This change reinforces that each platform must manage its own PCS life cycle explicitly, but the XPCS creation code in stmmac_pcs_setup() was not updated to match this new expectation, leaving a gap where platform drivers have no clean way to take control of XPCS creation. Address all of these issues by introducing pcs_init() and pcs_exit() callbacks in plat_stmmacenet_data. These callbacks give platform drivers full control over when and how the XPCS is created, configured, and destroyed. The common stmmac_pcs_setup() and stmmac_pcs_clean() functions are simplified to just call these callbacks, removing the confusing and error-prone XPCS creation logic from the common code. Platforms that do not need an XPCS simply leave the callbacks as NULL and no change in behavior occurs. Platforms that do need an XPCS can now create it with the exact configuration they require, including wrapping it with custom phylink_pcs_ops when necessary. Existing platform drivers (intel, rzn1, socfpga) are updated to use the new callbacks by moving their XPCS creation and cleanup logic into pcs_init() and pcs_exit(). In their pcs_exit() implementations, the pointer to the destroyed PCS is explicitly set to NULL to avoid dangling pointer references. Signed-off-by: Coia Prant --- .../net/ethernet/stmicro/stmmac/dwmac-intel.c | 44 +++++++++++++++++-- .../stmicro/stmmac/dwmac-renesas-gbeth.c | 7 ++- .../net/ethernet/stmicro/stmmac/dwmac-rzn1.c | 7 ++- .../ethernet/stmicro/stmmac/dwmac-socfpga.c | 7 ++- .../net/ethernet/stmicro/stmmac/stmmac_mdio.c | 37 +++------------- 5 files changed, 61 insertions(+), 41 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index 4d207f41a43b3..221b3203a81ed 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c @@ -603,13 +603,47 @@ static void common_default_data(struct plat_stmmacenet_data *plat) plat->mdio_bus_data->needs_reset = true; } +static int intel_mgbe_pcs_init(struct stmmac_priv *priv) +{ + struct fwnode_handle *devnode, *pcsnode; + struct dw_xpcs *xpcs = NULL; + int addr; + + devnode = dev_fwnode(priv->device); + + if (fwnode_property_present(devnode, "pcs-handle")) { + pcsnode = fwnode_find_reference(devnode, "pcs-handle", 0); + xpcs = xpcs_create_fwnode(pcsnode); + fwnode_handle_put(pcsnode); + } else { + addr = ffs(priv->plat->mdio_bus_data->pcs_mask) - 1; + xpcs = xpcs_create_mdiodev(priv->mii, addr); + } + + if (IS_ERR(xpcs)) + return PTR_ERR(xpcs); + + xpcs_config_eee_mult_fact(xpcs, priv->plat->mult_fact_100ns); + + priv->hw->xpcs = xpcs; + return 0; +} + +static void intel_mgbe_pcs_exit(struct stmmac_priv *priv) +{ + if (!priv->hw->xpcs) + return; + + xpcs_destroy(priv->hw->xpcs); + priv->hw->xpcs = NULL; +} + static struct phylink_pcs *intel_mgbe_select_pcs(struct stmmac_priv *priv, phy_interface_t interface) { - /* plat->mdio_bus_data->has_xpcs has been set true, so there - * should always be an XPCS. The original code would always - * return this if present. - */ + if (!priv->hw->xpcs) + return NULL; + return xpcs_to_phylink_pcs(priv->hw->xpcs); } @@ -733,6 +767,8 @@ static int intel_mgbe_common_data(struct pci_dev *pdev, plat->phy_interface == PHY_INTERFACE_MODE_1000BASEX) { plat->mdio_bus_data->pcs_mask = BIT_U32(INTEL_MGBE_XPCS_ADDR); plat->default_an_inband = true; + plat->pcs_init = intel_mgbe_pcs_init; + plat->pcs_exit = intel_mgbe_pcs_exit; plat->select_pcs = intel_mgbe_select_pcs; } diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-renesas-gbeth.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-renesas-gbeth.c index 19f34e18bfef2..9af32c26f9c14 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-renesas-gbeth.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-renesas-gbeth.c @@ -81,8 +81,11 @@ static int renesas_gmac_pcs_init(struct stmmac_priv *priv) static void renesas_gmac_pcs_exit(struct stmmac_priv *priv) { - if (priv->hw->phylink_pcs) - miic_destroy(priv->hw->phylink_pcs); + if (!priv->hw->phylink_pcs) + return; + + miic_destroy(priv->hw->phylink_pcs); + priv->hw->phylink_pcs = NULL; } static struct phylink_pcs *renesas_gmac_select_pcs(struct stmmac_priv *priv, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c index 13634965bc19a..01df4776edb3f 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-rzn1.c @@ -35,8 +35,11 @@ static int rzn1_dwmac_pcs_init(struct stmmac_priv *priv) static void rzn1_dwmac_pcs_exit(struct stmmac_priv *priv) { - if (priv->hw->phylink_pcs) - miic_destroy(priv->hw->phylink_pcs); + if (!priv->hw->phylink_pcs) + return; + + miic_destroy(priv->hw->phylink_pcs); + priv->hw->phylink_pcs = NULL; } static struct phylink_pcs *rzn1_dwmac_select_pcs(struct stmmac_priv *priv, diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index 1d7f0a57d2889..6d4bc1fe8f751 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -539,8 +539,11 @@ static int socfpga_dwmac_pcs_init(struct stmmac_priv *priv) static void socfpga_dwmac_pcs_exit(struct stmmac_priv *priv) { - if (priv->hw->phylink_pcs) - lynx_pcs_destroy(priv->hw->phylink_pcs); + if (!priv->hw->phylink_pcs) + return; + + lynx_pcs_destroy(priv->hw->phylink_pcs); + priv->hw->phylink_pcs = NULL; } static struct phylink_pcs *socfpga_dwmac_select_pcs(struct stmmac_priv *priv, diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c index afe98ff5bdcb0..d2f77f0c223a7 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -426,36 +426,15 @@ int stmmac_mdio_reset(struct mii_bus *bus) int stmmac_pcs_setup(struct net_device *ndev) { struct stmmac_priv *priv = netdev_priv(ndev); - struct fwnode_handle *devnode, *pcsnode; - struct dw_xpcs *xpcs = NULL; - int addr, ret; - - devnode = dev_fwnode(priv->device); - - if (priv->plat->pcs_init) { - ret = priv->plat->pcs_init(priv); - } else if (fwnode_property_present(devnode, "pcs-handle")) { - pcsnode = fwnode_find_reference(devnode, "pcs-handle", 0); - xpcs = xpcs_create_fwnode(pcsnode); - fwnode_handle_put(pcsnode); - ret = PTR_ERR_OR_ZERO(xpcs); - } else if (priv->plat->mdio_bus_data && - priv->plat->mdio_bus_data->pcs_mask) { - addr = ffs(priv->plat->mdio_bus_data->pcs_mask) - 1; - xpcs = xpcs_create_mdiodev(priv->mii, addr); - ret = PTR_ERR_OR_ZERO(xpcs); - } else { + int ret; + + if (!priv->plat->pcs_init) return 0; - } + ret = priv->plat->pcs_init(priv); if (ret) return dev_err_probe(priv->device, ret, "No xPCS found\n"); - if (xpcs) - xpcs_config_eee_mult_fact(xpcs, priv->plat->mult_fact_100ns); - - priv->hw->xpcs = xpcs; - return 0; } @@ -463,14 +442,10 @@ void stmmac_pcs_clean(struct net_device *ndev) { struct stmmac_priv *priv = netdev_priv(ndev); - if (priv->plat->pcs_exit) - priv->plat->pcs_exit(priv); - - if (!priv->hw->xpcs) + if (!priv->plat->pcs_exit) return; - xpcs_destroy(priv->hw->xpcs); - priv->hw->xpcs = NULL; + priv->plat->pcs_exit(priv); } struct stmmac_clk_rate { -- 2.47.3 -- linux-phy mailing list linux-phy@lists.infradead.org https://lists.infradead.org/mailman/listinfo/linux-phy