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 71F32C982C3 for ; Tue, 15 Sep 2026 12:39:04 +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=aPxtBLp8BHuWw/f3CdZJHj5sLEZvKFSCHJB+Ci84iAQ=; b=zch5jzVz/z8dgE eyjRLU6gUivvXuqlZFBSyYdrCHQrJishwALwJc71ictHVZyCWDljk+1pFfYfz3Xsqdfh9yefMX1eq TWOhT4/UCZqc4yMu2KJJXAKYs+XGOZfMfK07mhKmMfqWPsGiisVCvDHmeNQ+uFkvEgnuYEgpFryI2 7dEkZGlWSHeton79CfaJpB2nmwf1swXXoZAGM1YYuOSLd07uL2bzvBlhwdDuAGU+KgwoxhqH1CVTE 4efN3qpswRkKjTPkbkO15zd+m9Rn29k+Ypt7KUWSBb8cpXA8baSIZtek5oSO22bZK243o7IrxTK6h 8LAOqEOJMJ8k700DA9Gw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1x6SRC-00000006X8R-04MZ; Tue, 15 Sep 2026 12:39:02 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1x6SQp-00000006WjD-0RxR for linux-rockchip@bombadil.infradead.org; Tue, 15 Sep 2026 12:38:39 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Transfer-Encoding:MIME-Version :References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=qN2MkU81Lz1KMvwh0OIvKliZyK5cNgEHJk5t3+uaHA8=; b=d1bgSO5ESGc7eVYy1COrw/oBay hkbGjhxbwDPHuFeG7WSXrnOTQSmbtT8+ilb8/i5PK7I8n5aXDHKXb2lb2y8NQb+zWH9IO8JnDR3wZ Bss18G3YUtAcy6AoMEOl5kn0lyaCT1VwI1gIVzX10j25nGolOo21SW6J2gHi7IxwR20+NgU+uuB6Z PcoP0RZOz3+4k8RiDnuYBP0xRxmK/P/UQp4PtMgcaXqa4QeRahV2fIdtp4h8OjJ0QeL1dOTUJqNcS UQYIuLZgD4+DqgXLJ1/+a/8FGqPuSoeLJTJdV1ILnLteLrf3A9lj7VxGJl90Y9h5f4nDmsCHqN3hE 8d32uFww==; Received: from mail-pj2-x0a.google.com ([2607:f8b0:4864:39::a]) by desiato.infradead.org with esmtps (Exim 4.99.2 #2 (Red Hat Linux)) id 1x6SQl-00000006kEl-3FrO for linux-rockchip@lists.infradead.org; Tue, 15 Sep 2026 12:38:38 +0000 Received: by mail-pj2-x0a.google.com with SMTP id 98e67ed59e1d1-39ded0d7f52so1311875a91.0 for ; Tue, 15 Sep 2026 05:38:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789475914; x=1790080714; 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=qN2MkU81Lz1KMvwh0OIvKliZyK5cNgEHJk5t3+uaHA8=; b=TR12Z4eoFIT+HlApbVGWWZgVDE1UQjjG+/7czaqr3kdJHrAfVvzkuhdfV51lGSsqGX CIh9FIkzljvlJZRM0FEmJeNesRR4SbfkZ67VM8Zg65V99XtyiPTWggiVLRI4XCAZs7X6 efn12GYkihdvSdiftC3l0EU8RNwHzsWJQl5xjlNNSeeAINW3xqyNRTih7NHpi+Y71CUD p7mHnewTRV9qq6eOn+5R73UNjhgFfd/nMyKjKNQd5NR9NGgb30QbFJ7ySeE+0sGjeK1e qQGh1gQSJ+/Ad+WukVsyJ8UOXGbga86x9JZDa+v2PwsRZfTl7zLqnG4Crd2mdh8du9Ct 5ccw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789475914; x=1790080714; 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=qN2MkU81Lz1KMvwh0OIvKliZyK5cNgEHJk5t3+uaHA8=; b=PEzisrYuQv6mX3+hwrYNzo9Rrf6d2wJu3UNOqBMF4gIbV23uh9qhg4nXQIe0gOhW06 +64MaUirVpQ1jxFA0rv4z7Bk+andoNU43ieN8XIp+WGBSjtcq4IFD0wJUqJOHmZs9GhB eHllWi7iEST7vB42A1ya74/jlr9NIefHMf77sNvQTV46yVBHcf6KnjrbMfa6fQOcycBD lhY6xJgYA6TRrdnG4RVASYWllx2p/1WwonfY5HKujSUJQRPhi3lu9O8ESqoEwnwB/ON1 A7zM9E6itjcDXXr9tP7j/COpt2vpfdZ4BhsoYM/P077biAiwFv14L6+ub4LZ+IoqncKs /Sog== X-Forwarded-Encrypted: i=1; AKwUvBzY376g7fRVthyt7u+jVlzxMrwp77LmIb1cyt4ulbFTrnA2Au3aB2XOPilcQ/WnO3pHjbLWdD8RfdqfUR+LRw==@lists.infradead.org X-Gm-Message-State: AFuF++mN7WePreV8RCu4XC5WjvRcPsBO/UVWn7XL7QXSnL+VG+DC9eTe tKliMm9R1/OoCl7wSk7v1N1olOnSJCitSABJtLd/0nYFDYtjNYjGSxJU X-Gm-Gg: AYBFou0ll0sbhneWB5WchA7TyCwjBdG2lIjdKOswT5eQf93oUckFhWRqjWh6f6Jkw6o pc7g19IMGiFTwnzDzJX7SdSiTaSt0e4ggbQBub0JUdMayRU303Hlo0SavkRh87X7texOKCDh+nL R2sAyew74FL6vU8+h8EY/YfKXyvAXUgzS6aAr6W402LJ6Mx01mMKWZmGWa/sr2kElWJZra02RjG ebgFZO+vIKzAGMx6jCOJ9QSSx2JPjmKLTv329/9OmbUJHYAC2qKV5jtqcvSH+KZy94LL9t/N9wb d2aWPKNnhQ5UGS7Ww8CGn+rGxzLY5QEqcvzDRfA2SWq/79l/ErhWjTt1DbSMIVK85rHt+bVPyZi RAFioynGc03ixe1wxuPXmJT1v0vn0+T6QwR7VPwMjH4Nq3Cn7eFjC69W02E4znDW38Xol54T/m/ MLRpRrlEegAzhiWyLnwkVAysThejAoh4LWQZVL3Juc7ZJP91kXGOmJaQ+NW4PrG77juwWY8g== X-Received: by 2002:a17:90b:1811:b0:395:7fff:a08f with SMTP id 98e67ed59e1d1-39e106b649dmr1483983a91.0.1789475913321; Tue, 15 Sep 2026 05:38:33 -0700 (PDT) Received: from server.lan ([168.138.199.194]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-39dfdd28acbsm5307259a91.10.2026.09.15.05.38.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 15 Sep 2026 05:38:32 -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 net-next v6 01/11] net: stmmac: move XPCS lifetime management to platform drivers Date: Tue, 15 Sep 2026 20:37:50 +0800 Message-ID: <20260915123802.1561724-2-coiaprant@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260915123802.1561724-1-coiaprant@gmail.com> References: <20260915123802.1561724-1-coiaprant@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260915_133836_546781_FA6907CA X-CRM114-Status: GOOD ( 23.43 ) X-BeenThere: linux-rockchip@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Upstream kernel work for Rockchip platforms List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Sender: "Linux-rockchip" Errors-To: linux-rockchip-bounces+linux-rockchip=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 a platform driver sets pcs_init() and creates an XPCS inside that callback, the common code afterwards still runs unconditionally and overwrites priv->hw->xpcs with the local xpcs variable, which stays NULL. The platform driver has no way to prevent this override because the common code runs 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 simplifying the existing pcs_init() and pcs_exit() dispatch in stmmac_pcs_setup() and stmmac_pcs_clean(). The common stmmac_pcs_setup() now calls plat->pcs_init() if present, and stmmac_pcs_clean() calls plat->pcs_exit() if present, 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. The Intel mGbE glue is updated to create its XPCS inside its own pcs_init() implementation, and the renesas-gbeth, rzn1 and socfpga pcs_exit() callbacks now explicitly clear priv->hw->phylink_pcs after destroying the PCS to avoid dangling pointer references. Reviewed-by: Maxime Chevallier 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 | 39 +++------------- 5 files changed, 62 insertions(+), 42 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index f5f9fa67ecd77..4308dccbf2570 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; + 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..7396b68899c66 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -426,35 +426,14 @@ 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 dev_err_probe(priv->device, ret, "Failed to initialize PCS\n"); 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-rockchip mailing list Linux-rockchip@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-rockchip 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 0B4ACC88E7B for ; Tue, 15 Sep 2026 12:39:02 +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=tnwFdNXGT+m/cqUXYCYJFU+SuwTo0oH//EvKFbSYWtA=; b=Knr5rlZVGWFNT3 ZlXBd4x3Iu79KOryt1FspaBycDHDCht9TcVfkqSo1K6yiDlYixYJKhqYyYlO20iO5XTPAm3ffS+UT Gr63ouV2tPuGsyNy3mZuOcZ60z8dtIc5LpXNoX+u0YV/h3293Wv9BIT7+5jH9a9IkLjb51+k6P3Q9 HgyeS6TnOqpDT1pYtz+SJ9dO8NFWnTf/5QKZ2ZO8u8eiOYYx1LaTpZJAPFLQ3JmtTilKx57FiSjtv xxBg6zQLs6vgJAqr+wdYrlfS3rAaKqc5KppfPEZJfPKp9mz4Wd+sZxX9hl0U4teQPcAt1u+RpLf49 RmU9ncZIjEvNCU0FPupw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.99.1 #2 (Red Hat Linux)) id 1x6SRB-00000006X7H-2coZ; Tue, 15 Sep 2026 12:39:01 +0000 Received: from desiato.infradead.org ([2001:8b0:10b:1:d65d:64ff:fe57:4e05]) by bombadil.infradead.org with esmtps (Exim 4.99.1 #2 (Red Hat Linux)) id 1x6SQp-00000006WjC-0O4S for linux-phy@bombadil.infradead.org; Tue, 15 Sep 2026 12:38:39 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=desiato.20200630; h=Content-Transfer-Encoding:MIME-Version :References:In-Reply-To:Message-ID:Date:Subject:Cc:To:From:Sender:Reply-To: Content-Type:Content-ID:Content-Description; bh=qN2MkU81Lz1KMvwh0OIvKliZyK5cNgEHJk5t3+uaHA8=; b=d1bgSO5ESGc7eVYy1COrw/oBay hkbGjhxbwDPHuFeG7WSXrnOTQSmbtT8+ilb8/i5PK7I8n5aXDHKXb2lb2y8NQb+zWH9IO8JnDR3wZ Bss18G3YUtAcy6AoMEOl5kn0lyaCT1VwI1gIVzX10j25nGolOo21SW6J2gHi7IxwR20+NgU+uuB6Z PcoP0RZOz3+4k8RiDnuYBP0xRxmK/P/UQp4PtMgcaXqa4QeRahV2fIdtp4h8OjJ0QeL1dOTUJqNcS UQYIuLZgD4+DqgXLJ1/+a/8FGqPuSoeLJTJdV1ILnLteLrf3A9lj7VxGJl90Y9h5f4nDmsCHqN3hE 8d32uFww==; Received: from mail-pj2-x0b.google.com ([2607:f8b0:4864:39::b]) by desiato.infradead.org with esmtps (Exim 4.99.2 #2 (Red Hat Linux)) id 1x6SQl-00000006kEj-3Gc0 for linux-phy@lists.infradead.org; Tue, 15 Sep 2026 12:38:38 +0000 Received: by mail-pj2-x0b.google.com with SMTP id 98e67ed59e1d1-398a0a87595so4265692a91.1 for ; Tue, 15 Sep 2026 05:38:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789475914; x=1790080714; 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=qN2MkU81Lz1KMvwh0OIvKliZyK5cNgEHJk5t3+uaHA8=; b=TR12Z4eoFIT+HlApbVGWWZgVDE1UQjjG+/7czaqr3kdJHrAfVvzkuhdfV51lGSsqGX CIh9FIkzljvlJZRM0FEmJeNesRR4SbfkZ67VM8Zg65V99XtyiPTWggiVLRI4XCAZs7X6 efn12GYkihdvSdiftC3l0EU8RNwHzsWJQl5xjlNNSeeAINW3xqyNRTih7NHpi+Y71CUD p7mHnewTRV9qq6eOn+5R73UNjhgFfd/nMyKjKNQd5NR9NGgb30QbFJ7ySeE+0sGjeK1e qQGh1gQSJ+/Ad+WukVsyJ8UOXGbga86x9JZDa+v2PwsRZfTl7zLqnG4Crd2mdh8du9Ct 5ccw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789475914; x=1790080714; 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=qN2MkU81Lz1KMvwh0OIvKliZyK5cNgEHJk5t3+uaHA8=; b=xzuPNpXvaxoEPeO287MwVyibLWDvYt/IPVR7QUd7ojTqod7UT32bK9H98L4q0r3PEF 37FPpDrfPYNK2jhVHitnzwUJPH1yBJc05Y+sf7mmBhAi7MwtH+UyDKEIJ1emYTnRNtPW 4guffwdueSHSDA1gs0PbZoRHMYMmebOq5xjOQWmOWhC6UKFWO8xJDdYShmDD1hbXngDK EBv1XcBeqs7YEKiugjflsrY3J/s9fW4prsb91oqCyDZJ08SlLlaKIS+d6gBQxQw699YI 4LG5Z5uU7RqGUMcGaSRWtZeSCGBoY/rj/wvApdqms/VCvzi1ieLNQ7MYwXjOitvLT82/ sDhQ== X-Forwarded-Encrypted: i=1; AKwUvBwDDmsn8zrQo/WndViPw8g+UOUiuC94o1+RVQpW6TYcoexPwhHfIpVoSbvSiGEd7oezfYbwaj2bbUI=@lists.infradead.org X-Gm-Message-State: AFuF++nnuYJA/ODgY5s3efxRwBy+SaXG64kIhTpOvW97oW4gpFSY5vZ8 X10QsBXfDdbVSe1yCDR6EGir/jFDDnHckASTJX8awQ9HkQf/vTCoq0XI X-Gm-Gg: AYBFou276eImCZfYU0pvxKxw27+KicnWBNpFoFo/6XDPKmQdTjZ3+P3gvCV5YQhA8pM 8+4vV7MOruA3cG/Oau7O2G5jJfKn1t+2YPXOLIs9w/+duFykSRXaCb2F+OlcnK2SGTz8AyQhvN7 bEY6pyrEQZJLM3Zot+Jzbw48OlpnBx0ezNxVA6s3X0cKGJ3zASdyI5bt4kYQQr2KEkMghTbb8gq oS7qkxRJi8Kfxmm+inhXtPjVEBjjJtM2//pIZ5llp4BvArbOa+qFvw1+vWWyDZZSco2J7kjW1Ks LzLFTT7iZ9KrcikBSBNc4xv2tsab7MgN/7mngyAdGb5BxpBUgOcWI193uWKAX4AUA7RIcNKJOyY pnNV01ukvyC24agnzcxiPMaPTzjhVvGlJ9weUVgquqIK1X1A0Mi2UhSeUEeZbCJNYEHZrmNvjyR L5k6SsC4BJrATRvVaG77Xw5prOV6VMNxxB+ssK4+Elt9qHthIB7hVA0DLqM87iwj+Djiaidw== X-Received: by 2002:a17:90b:1811:b0:395:7fff:a08f with SMTP id 98e67ed59e1d1-39e106b649dmr1483983a91.0.1789475913321; Tue, 15 Sep 2026 05:38:33 -0700 (PDT) Received: from server.lan ([168.138.199.194]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-39dfdd28acbsm5307259a91.10.2026.09.15.05.38.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 15 Sep 2026 05:38:32 -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 net-next v6 01/11] net: stmmac: move XPCS lifetime management to platform drivers Date: Tue, 15 Sep 2026 20:37:50 +0800 Message-ID: <20260915123802.1561724-2-coiaprant@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260915123802.1561724-1-coiaprant@gmail.com> References: <20260915123802.1561724-1-coiaprant@gmail.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.9.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20260915_133836_509324_8324B4FB X-CRM114-Status: GOOD ( 23.22 ) 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 a platform driver sets pcs_init() and creates an XPCS inside that callback, the common code afterwards still runs unconditionally and overwrites priv->hw->xpcs with the local xpcs variable, which stays NULL. The platform driver has no way to prevent this override because the common code runs 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 simplifying the existing pcs_init() and pcs_exit() dispatch in stmmac_pcs_setup() and stmmac_pcs_clean(). The common stmmac_pcs_setup() now calls plat->pcs_init() if present, and stmmac_pcs_clean() calls plat->pcs_exit() if present, 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. The Intel mGbE glue is updated to create its XPCS inside its own pcs_init() implementation, and the renesas-gbeth, rzn1 and socfpga pcs_exit() callbacks now explicitly clear priv->hw->phylink_pcs after destroying the PCS to avoid dangling pointer references. Reviewed-by: Maxime Chevallier 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 | 39 +++------------- 5 files changed, 62 insertions(+), 42 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index f5f9fa67ecd77..4308dccbf2570 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; + 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..7396b68899c66 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -426,35 +426,14 @@ 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 dev_err_probe(priv->device, ret, "Failed to initialize PCS\n"); 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 From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj2-f1.google.com (mail-pj2-f1.google.com [74.125.227.129]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B3EEC48CD48 for ; Tue, 15 Sep 2026 12:38:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=74.125.227.129 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789475918; cv=none; b=qRRqLFmElnwHyZ2dSXxYnZeK+RvZASiIYGCjkU7GwVamr33xjWNxDlVnEbXiPwMOh89Wivunu4Ts450zKkTTV83y0b6H1WNPU1qg2DifQdJD5p/bbbPtWjFuNZODcnFY5dn/bnio9j61wGN99A3qK9RfE3XnmwOaSqxoGnYLSkw= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789475918; c=relaxed/simple; bh=gWvVNB1m2Bm2R+CKFSLbBbPCu/GkRF+C5uYpyZkg/fA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=oZBzEso7rbOVDhs3G06ReMDvQutAg+hH/MmQmhxLDzY7PqAjmKqHt0M+4SSgFUElo2/hv7cnbLhJO7HGTpWUw0HohTQ1DORHxyybSVWhCFDJwmOGUANsgEGUA/UJ3Gg/Bko+QNnl3RnsnyPQnC4e1Z3MHuh/pQFmnj8NoPId17g= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com; spf=pass smtp.mailfrom=gmail.com; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b=rkC4FQOk; arc=none smtp.client-ip=74.125.227.129 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=gmail.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com header.b="rkC4FQOk" Received: by mail-pj2-f1.google.com with SMTP id 98e67ed59e1d1-39ded0d7f52so1311873a91.0 for ; Tue, 15 Sep 2026 05:38:34 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20251104; t=1789475914; x=1790080714; darn=vger.kernel.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=qN2MkU81Lz1KMvwh0OIvKliZyK5cNgEHJk5t3+uaHA8=; b=rkC4FQOkYSj8jAGGxlWPzH9zM826nS63hyhvDyC+r9+BhTNBnu3uu/2c5yBw34jV3u WtHTBN7p4Zw2+jLlqqM1H94AeHS2XmDNX9hu0ktCYfyEBEKYHK2RaxN/WVcr89/6IY6x Vfv/KJj5CRuSD9txVibIRQbsq3LL7tcNkGD40/ueQCU/DvucIhv1moC8VPBrILuFcrl6 21kMojQMye1zJyH4H4ucA2VwTTcCspMAHscPDxCS7oGRJl50ZzhWmaE/8pJ9vXfPOlEs Ofxku7n1ShwQcO5do2cPycXOP5XN4EE/AQu10mpjmOzQmL8v0PNuZ2cvN59IFBW5rpoV K4OQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20260707; t=1789475914; x=1790080714; 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=qN2MkU81Lz1KMvwh0OIvKliZyK5cNgEHJk5t3+uaHA8=; b=luuGbO7XYiiCY42OWSm0YniukXqgZ3r5jJK67pTmPywjIOydfaCLMyJk8F/h4ZVDvL PydU0bi9SXQThgKsLcSivIANMXTiOQ4bVvX2a0GhckvtIl82X7PSEdhrGzpbgRAJicsS C9GiM4qb8HiIf39yIX7PggXTzpWZVtKF7TqhUr5tetbt1iTnMxfv7tzRIwOVrtoVe7E8 DmzxZCjxa9nTqtEd345YoZm6ONkYzUgOdnTBbSY+gFYGj9hFnWhs3vA4H0sBivUf/kSz puI8QN1IvDjlcLkVxE8YSkIbzvqwuI7QKWeXydvMHKjuulg1tf0BUm1OAoBliY1NwbMK /RmA== X-Forwarded-Encrypted: i=1; AKwUvBxHwFN9yflnCbDRn1317SH935K942piSkSUQqBaEyIJDb2kb2f706ODPJv839oxSLuQ5qR4kjw=@vger.kernel.org X-Gm-Message-State: AFuF++nVbA/7JqxbjyD7a0bx+eJEXX99HnqKUtburThy/5yjckIlKDyO gsXWrX0jEfJj5YaBcVtmhZvVyxvDe+1l2IeZKkF8adsE3TS0pE+v5pCG X-Gm-Gg: AYBFou37cU/39ltyv3uqaWNPYh44E8rdPHSD8Da2aYa4qcJqqO9DMNi3xhpOwCJ5s8W CyVzBOn0MYguc/Qu77KGwGaepSYBIZKgsrgTD1AF6kU7SujRRhuJVwY1e+V1jdZiP5/XfS0+iIG QTdVD4ec8KzQSEG0AoMKWcEF/kalw4ux1OjYd7WuWdl9H21XQeMAwT7hh7mrVMiSsZ6GphFS1zh m2nioJG40eQe1T92xYRf7jURd8d1+vdS11a1ogjl2+mvHL233GUAzZshImaB6k/bCTETHwanKce Oy/VhJ4lgFKxZqN7A7bg5CgF/C+8OUdP+Ge1JXit3qOro5Li+KqUOaNUDCiSfEVnT0UQvDO9H2G QNH5gdWoV+Ihbb7JDr5LbKW4KKD60My8ldxDwhcVWr5qc0cIOj+ks5W6c/0Sh4Jmnqh/YdlEH11 nKwKuIcTxq70KHc3dHeIzzdjvuHKdZUpCwcdD2SFFY0yfSRIiQ8ZFtmMkffkJEVxOW0uuuag== X-Received: by 2002:a17:90b:1811:b0:395:7fff:a08f with SMTP id 98e67ed59e1d1-39e106b649dmr1483983a91.0.1789475913321; Tue, 15 Sep 2026 05:38:33 -0700 (PDT) Received: from server.lan ([168.138.199.194]) by smtp.gmail.com with ESMTPSA id 98e67ed59e1d1-39dfdd28acbsm5307259a91.10.2026.09.15.05.38.24 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 15 Sep 2026 05:38:32 -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 net-next v6 01/11] net: stmmac: move XPCS lifetime management to platform drivers Date: Tue, 15 Sep 2026 20:37:50 +0800 Message-ID: <20260915123802.1561724-2-coiaprant@gmail.com> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260915123802.1561724-1-coiaprant@gmail.com> References: <20260915123802.1561724-1-coiaprant@gmail.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 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 a platform driver sets pcs_init() and creates an XPCS inside that callback, the common code afterwards still runs unconditionally and overwrites priv->hw->xpcs with the local xpcs variable, which stays NULL. The platform driver has no way to prevent this override because the common code runs 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 simplifying the existing pcs_init() and pcs_exit() dispatch in stmmac_pcs_setup() and stmmac_pcs_clean(). The common stmmac_pcs_setup() now calls plat->pcs_init() if present, and stmmac_pcs_clean() calls plat->pcs_exit() if present, 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. The Intel mGbE glue is updated to create its XPCS inside its own pcs_init() implementation, and the renesas-gbeth, rzn1 and socfpga pcs_exit() callbacks now explicitly clear priv->hw->phylink_pcs after destroying the PCS to avoid dangling pointer references. Reviewed-by: Maxime Chevallier 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 | 39 +++------------- 5 files changed, 62 insertions(+), 42 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c index f5f9fa67ecd77..4308dccbf2570 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; + 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..7396b68899c66 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_mdio.c @@ -426,35 +426,14 @@ 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 dev_err_probe(priv->device, ret, "Failed to initialize PCS\n"); 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