| Message ID | 20260917-submit-h616-emac1-v1-v3-1-62cb8316e19b@gmail.com (mailing list archive) |
|---|---|
| State | New |
| Headers |
Return-Path: <linux-sunxi+bounces-26016-sunxi=pue.re@lists.linux.dev>
X-Original-To: noreply@patchwork.local
Delivered-To: noreply@patchwork.local
Received: from sea.lore.kernel.org (sea.lore.kernel.org [172.234.253.10])
by mxe881.netcup.net (Postfix) with ESMTPS id 9F8C71C1FF1
for <noreply@patchwork.local>; Fri, 18 Sep 2026 01:09:50 +0200 (CEST)
Authentication-Results: mxe881;
dkim=pass header.d=gmail.com;
spf=pass (sender IP is 172.234.253.10)
smtp.mailfrom=linux-sunxi+bounces-26016-noreply=patchwork.local@lists.linux.dev
smtp.helo=sea.lore.kernel.org
Received-SPF: pass (mxe881: domain of lists.linux.dev designates
172.234.253.10 as permitted sender) client-ip=172.234.253.10;
envelope-from=linux-sunxi+bounces-26016-noreply=patchwork.local@lists.linux.dev;
helo=sea.lore.kernel.org;
Received: from smtp.subspace.kernel.org (conduit.subspace.kernel.org
[100.90.174.1])
by sea.lore.kernel.org (Postfix) with ESMTP id 3B1EB20305D
for <noreply@patchwork.local>; Thu, 17 Sep 2026 18:07:09 +0000 (UTC)
Received: from localhost.localdomain (localhost.localdomain [127.0.0.1])
by smtp.subspace.kernel.org (Postfix) with ESMTP id EE5E14F3EA4;
Thu, 17 Sep 2026 17:55:25 +0000 (UTC)
Authentication-Results: smtp.subspace.kernel.org;
dkim=pass (2048-bit key) header.d=gmail.com header.i=@gmail.com
header.b="pDeFJ0QN"
X-Original-To: linux-sunxi@lists.linux.dev
Received: from mail-oa2-f12.google.com (mail-oa2-f12.google.com
[74.125.231.76])
(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 72BF54FD265
for <linux-sunxi@lists.linux.dev>; Thu, 17 Sep 2026 17:55:23 +0000 (UTC)
Authentication-Results: smtp.subspace.kernel.org;
arc=none smtp.client-ip=74.125.231.76
ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116;
t=1789667725; cv=none;
b=Nwzyid4cui4nCSCUDuyFyD0hLccmLuB+RvkXK4rFps653BoAqIQWfvFvz2cVfbuat5w80QpgOC58lR0RuZW06WnJLEaYR1GyoaCc32jmNEFRuDBCtH5VhOBaPP59UCob3Ixsw/uqg9/XfIXGoLPqPhlDbUL47ypSlf1vdK35AUo=
ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org;
s=arc-20240116; t=1789667725; c=relaxed/simple;
bh=uRyBjqqvSFltweei6Uy/M5gNvkY89BEG9UdA/vDzq/4=;
h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References:
In-Reply-To:To:Cc;
b=N0siB7KRp/QvN/179uILVmgFL+4ixgXNM6o+dQ2ljlWZLgCbAyqR0iXZe/h+dmzbbiT+1XZxh1TYXZUsJ2sL42+qVjfXv1jrwtVCNllM5y42re+7iB9DlhMvDE57dH28itGl3ywUV2+WwhLmV8DT3Y+q0WpxvCac3FM5sx0w7xk=
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=pDeFJ0QN; arc=none smtp.client-ip=74.125.231.76
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
Received: by mail-oa2-f12.google.com with SMTP id
586e51a60fabf-466ccbd4773so446370fac.2
for <linux-sunxi@lists.linux.dev>;
Thu, 17 Sep 2026 10:55:23 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=gmail.com; s=20251104; t=1789667722; x=1790272522;
darn=lists.linux.dev;
h=cc:to:in-reply-to:references:message-id:content-transfer-encoding
:content-type:mime-version:subject:date:from:from:to:cc:subject:date
:message-id:reply-to:content-type;
bh=epD9LhruE07/QoJcSKVg/dbrndAnrXPsihPLPnVDq64=;
b=pDeFJ0QNA5qm4eCnswI83J9/grvBVwGGmHXm5bdoVHUuJoO0lUrTZS43hnvuFd3NhN
OGKOFg94rDj5F2MhBSlfp5XS1rcKgrWraRxGz/FbS7PQ+Gnl7FKNTTwPWrwN10e/x7HI
luEZ8FtqCVm5bhZpS6j9DbHGX5Ck9sW8cNCb7wv/+Y6VVypImnxoZJ6P1InMWtvoCGp7
ID2VJvOM19k2/nObr55ufJsWw1YXosStK9QFMtPaSHksgdmkGq3s/BO7YTtqlaPErxSn
gEaJc93TubxdVHYSFTCfvjaCbvU7Ol1Vlm5tcBcOlzH2PZ3MPpFxwcQy3cuZMW8hyxBn
56Lw==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
d=1e100.net; s=20260707; t=1789667722; x=1790272522;
h=cc:to:in-reply-to:references:message-id:content-transfer-encoding
:content-type:mime-version:subject:date:from:x-gm-gg
:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to
:content-type;
bh=epD9LhruE07/QoJcSKVg/dbrndAnrXPsihPLPnVDq64=;
b=Tqo5dxy/arXQu6ws2VqK9a5Ws598rNoJ16NoSILsAzi8FZV9spsyJ7Vb9jbQ84pviC
Wtv1gTOvpt6JvSlSxMe/E30sG0br/Ta/y4s61UrFnFOeViu0sY+QVVjSCPbgzPCSmIq0
2n4F6ugyp2R+b356VpqO6pjzf2QmcuSPtVk0mnwroEHz2iDD73dgW8Ft1Th4yphp7A9G
WbYVhh9cJla6CUv2PJfroWLv4oE1UhAPqmXC4GE3cj0b2+QyvcnoTzpkkRRGPKpCbGXK
IaWrmvDNdYTLVPtGvTaecWEv/3XQtLRW1IzVpvGBPFBkfl+mPBM8CLBy8XazCw/5HV5E
prcQ==
X-Forwarded-Encrypted: i=1;
AKwUvBxuKY2qOHW3G4umLUKgVKQ5JnzOVFUCWircC3PnEI/9TIv5XmD+x8TRv4X/hjKxtcgukIN/BpgfBBo4kw==@lists.linux.dev
X-Gm-Message-State: AFuF++kZWjar38V6xvi4mQQMNuuJN6avawN6f4jRglje9ih+8lq1UdCa
EEWPxikDZFTMplNmD+LmTbksX+kG1pi1HBjt2PCPhS3scSR3x2mK+jzu
X-Gm-Gg: AYBFou3W8AU7JNtX5Q8f4VErEjHVIEbOaNuav9fJrJq9OL/3EjR3dSZYJM/g6gu1ZlX
SXFtxvTYRCqPICf0T1vcBEYku92s5JtgTjpsn/WlRg6OHAbzKoV0XlQMT3z8GFMZjD/GRkKVelz
LU+cgKq0gLXdMBHJpITDiQpXmB3PZjZHev81OtH2fjn1dgHhweZ4H0dDVC0yTKHqVle75d9catO
Lao4FzRtlZtNxBFJQIoOrPRtcMwbTK4kji3KOQeqUutnHqMt1DvBMn5ZCrxetTAMuePnyem4pnz
ktkfO30FAOjtotufOacddwFBP4YMMHh2+RwO3WDBE5M11tZKYZFGf33Z8n/0JIgDm2Lyy0j6UZl
7ArJk8fyUlt4Z8fOS2/fe2Yx2U2c9ADVZTu+5LV9n+10ae4Qb3UwKcol+t+xKHBBPoJxOwK/AZv
//70cjy89HU1n3n5iUKy+iBCokGWDyl8y6eh7uMfNs2LfykcpnZkSuwkkagOBSP220g+4+4J3mI
gIq5zzkzdcydSYEMe+m2JZkbbGSAMss9jj7gDevlKY5NlDc8lEi6GKonaZA43oKUSCiECH2J7qm
QPm6C09FvAY+9LyibHvJ3ruw+ZTz8h44yayVPVTa7qC23j9Jnr5WvkCj8inWCnd2EwesgPjhrOA
KtIQ8rzewGmLtZDHGVcBRfiPYPxlPiLQ9
X-Received: by 2002:a05:6870:224b:b0:475:e0a7:9f27 with SMTP id
586e51a60fabf-48476e837dcmr7230581fac.21.1789667722195;
Thu, 17 Sep 2026 10:55:22 -0700 (PDT)
Received: from [127.0.1.1] (174-29-1-49.hlrn.qwest.net. [174.29.1.49])
by smtp.gmail.com with ESMTPSA id
586e51a60fabf-486ab6c1f31sm578446fac.10.2026.09.17.10.55.20
(version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
Thu, 17 Sep 2026 10:55:21 -0700 (PDT)
From: James Hilliard <james.hilliard1@gmail.com>
Date: Thu, 17 Sep 2026 11:55:12 -0600
Subject: [PATCH net-next v3 1/3] net: stmmac: sun8i: reset the MAC after
PHY initialization
Precedence: bulk
X-Mailing-List: linux-sunxi@lists.linux.dev
List-Id: <linux-sunxi.lists.linux.dev>
List-Subscribe: <mailto:linux-sunxi+subscribe@lists.linux.dev>
List-Unsubscribe: <mailto:linux-sunxi+unsubscribe@lists.linux.dev>
MIME-Version: 1.0
Content-Type: text/plain; charset="utf-8"
Content-Transfer-Encoding: 7bit
Message-Id: <20260917-submit-h616-emac1-v1-v3-1-62cb8316e19b@gmail.com>
References: <20260917-submit-h616-emac1-v1-v3-0-62cb8316e19b@gmail.com>
In-Reply-To: <20260917-submit-h616-emac1-v1-v3-0-62cb8316e19b@gmail.com>
To: Richard Genoud <richard.genoud@bootlin.com>,
Andrew Lunn <andrew+netdev@lunn.ch>,
"David S. Miller" <davem@davemloft.net>, Eric Dumazet <edumazet@google.com>,
Jakub Kicinski <kuba@kernel.org>, Paolo Abeni <pabeni@redhat.com>,
Rob Herring <robh@kernel.org>, Krzysztof Kozlowski <krzk+dt@kernel.org>,
Conor Dooley <conor+dt@kernel.org>, Chen-Yu Tsai <wens@kernel.org>,
Jernej Skrabec <jernej.skrabec@gmail.com>,
Samuel Holland <samuel@sholland.org>,
Alexandre Torgue <alexandre.torgue@foss.st.com>,
Giuseppe Cavallaro <peppe.cavallaro@st.com>,
Jose Abreu <joabreu@synopsys.com>,
Maxime Chevallier <maxime.chevallier@bootlin.com>,
Maxime Coquelin <mcoquelin.stm32@gmail.com>
Cc: Maxime Ripard <mripard@kernel.org>,
Alastair D'Silva <alastair@d-silva.org>, netdev@vger.kernel.org,
devicetree@vger.kernel.org, linux-arm-kernel@lists.infradead.org,
linux-sunxi@lists.linux.dev, linux-kernel@vger.kernel.org,
linux-stm32@st-md-mailman.stormreply.com,
James Hilliard <james.hilliard1@gmail.com>
X-Mailer: b4 0.15.2
X-Rspamd-Server: rspamd-worker-8404
X-Spamd-Result: default: False [4.34 / 15.00];
RBL_SENDERSCORE(2.00)[172.234.253.10:from];
SUSPICIOUS_RECIPS(1.50)[];
DMARC_POLICY_SOFTFAIL(1.00)[gmail.com : SPF not aligned (relaxed),
No valid DKIM,none];
MAILLIST(-0.15)[generic];
BAD_REP_POLICIES(0.10)[];
MIME_GOOD(-0.10)[text/plain];
HAS_LIST_UNSUB(-0.01)[];
TAGGED_RCPT(0.00)[netdev,dt];
ARC_ALLOW(0.00)[subspace.kernel.org:s=arc-20240116:i=1];
PRECEDENCE_BULK(0.00)[];
RCVD_VIA_SMTP_AUTH(0.00)[];
FORGED_RECIPIENTS_MAILLIST(0.00)[];
FREEMAIL_CC(0.00)[kernel.org,d-silva.org,vger.kernel.org,lists.infradead.org,lists.linux.dev,st-md-mailman.stormreply.com,gmail.com];
RCPT_COUNT_TWELVE(0.00)[26];
FORGED_SENDER_MAILLIST(0.00)[];
FROM_HAS_DN(0.00)[];
FROM_NEQ_ENVFROM(0.00)[jameshilliard1@gmail.com,linux-sunxi@lists.linux.dev];
ASN(0.00)[asn:63949, ipnet:172.234.224.0/19, country:SG];
FREEMAIL_FROM(0.00)[gmail.com];
R_SPF_ALLOW(0.00)[+ip4:172.234.253.10];
TO_DN_SOME(0.00)[];
RECEIVED_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[74.125.231.76:received,100.90.174.1:received];
RCVD_COUNT_FIVE(0.00)[6];
FREEMAIL_TO(0.00)[bootlin.com,lunn.ch,davemloft.net,google.com,kernel.org,redhat.com,gmail.com,sholland.org,foss.st.com,st.com,synopsys.com];
MIME_TRACE(0.00)[0:+];
TAGGED_FROM(0.00)[bounces-26016-noreply=patchwork.local];
RECEIVED_SPAMHAUS_PBL(0.00)[174.29.1.49:received];
MID_RHS_MATCH_FROM(0.00)[];
RCVD_TLS_LAST(0.00)[];
RBL_SPAMHAUS_BLOCKED_OPENRESOLVER(0.00)[172.234.253.10:from]
X-Rspamd-Queue-Id: 9F8C71C1FF1
X-MORS-Enabled: yes
X-MORS-DOMAIN: patchwork.local
X-MORS-HOSTING: hosting172546
X-MORS-USER: hosting172546
X-getmail-retrieved-from-mailbox: =?utf-8?q?INBOX?=
|
| Series |
net: stmmac: add Allwinner H616 EMAC1 support
|
|
Commit Message
James Hilliard
Sept. 17, 2026, 5:55 p.m. UTC
The MAC software reset needs a running receive clock from the PHY.
Resetting the MAC at the end of probe therefore fails when the PHY driver
has not been loaded or its probe has deferred on a missing supplier. The
failure removes the MAC and its MDIO bus, so loading the missing driver
later cannot recover the interface without reprobing the MAC.
Perform the software reset in the DMA reset callback instead. The stmmac
core calls it during hardware setup after attaching and initializing the
PHY, and resumes a suspended PHY before reopening or resuming the MAC.
Keep the existing register clearing after a successful reset and return
reset errors through the normal hardware-setup error path.
Remove the unconditional reset from probe. Keep the separate H3 MDIO-mux
reset after switching the mux and powering the selected PHY, since it is
needed to latch the selected interface before MDIO accesses.
Signed-off-by: James Hilliard <james.hilliard1@gmail.com>
---
drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 50 +++++++++++------------
1 file changed, 24 insertions(+), 26 deletions(-)
Comments
Hi, On 9/17/26 19:55, James Hilliard wrote: > The MAC software reset needs a running receive clock from the PHY. > Resetting the MAC at the end of probe therefore fails when the PHY driver > has not been loaded or its probe has deferred on a missing supplier. The > failure removes the MAC and its MDIO bus, so loading the missing driver > later cannot recover the interface without reprobing the MAC. > > Perform the software reset in the DMA reset callback instead. The stmmac > core calls it during hardware setup after attaching and initializing the > PHY, and resumes a suspended PHY before reopening or resuming the MAC. > Keep the existing register clearing after a successful reset and return > reset errors through the normal hardware-setup error path. > > Remove the unconditional reset from probe. Keep the separate H3 MDIO-mux > reset after switching the mux and powering the selected PHY, since it is > needed to latch the selected interface before MDIO accesses. > > Signed-off-by: James Hilliard <james.hilliard1@gmail.com> Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com> Maxime > --- > drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c | 50 +++++++++++------------ > 1 file changed, 24 insertions(+), 26 deletions(-) > > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c > index 48c52eb96233..4523a14f5e0c 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c > @@ -269,11 +269,32 @@ static const struct emac_variant emac_variant_h6 = { > #define SYSCON_ETCS_EXT_GMII 0x1 > #define SYSCON_ETCS_INT_GMII 0x2 > > +static int sun8i_dwmac_reset(void __iomem *ioaddr) > +{ > + u32 v; > + > + v = readl(ioaddr + EMAC_BASIC_CTL1); > + writel(v | 0x01, ioaddr + EMAC_BASIC_CTL1); > + > + /* The timeout was previously set to 10ms, but some board (OrangePI0) > + * need more if no cable plugged. 100ms seems OK > + */ > + return readl_poll_timeout(ioaddr + EMAC_BASIC_CTL1, v, > + !(v & 0x01), 100, 100000); > +} > + > /* sun8i_dwmac_dma_reset() - reset the EMAC > * Called from stmmac via stmmac_dma_ops->reset > */ > static int sun8i_dwmac_dma_reset(void __iomem *ioaddr) > { > + int ret; > + > + /* The PHY receive clock must be running for the reset to complete. */ > + ret = sun8i_dwmac_reset(ioaddr); > + if (ret) > + return ret; > + > writel(0, ioaddr + EMAC_RX_CTL1); > writel(0, ioaddr + EMAC_TX_CTL1); > writel(0, ioaddr + EMAC_RX_FRM_FLT); > @@ -738,27 +759,6 @@ static void sun8i_dwmac_flow_ctrl(struct mac_device_info *hw, > writel(v, ioaddr + EMAC_TX_FLOW_CTL); > } > > -static int sun8i_dwmac_reset(struct stmmac_priv *priv) > -{ > - u32 v; > - int err; > - > - v = readl(priv->ioaddr + EMAC_BASIC_CTL1); > - writel(v | 0x01, priv->ioaddr + EMAC_BASIC_CTL1); > - > - /* The timeout was previously set to 10ms, but some board (OrangePI0) > - * need more if no cable plugged. 100ms seems OK > - */ > - err = readl_poll_timeout(priv->ioaddr + EMAC_BASIC_CTL1, v, > - !(v & 0x01), 100, 100000); > - > - if (err) { > - dev_err(priv->device, "EMAC reset timeout\n"); > - return err; > - } > - return 0; > -} > - > /* Search in mdio-mux node for internal PHY node and get its clk/reset */ > static int get_ephy_nodes(struct stmmac_priv *priv) > { > @@ -895,7 +895,9 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child, > /* After changing syscon value, the MAC need reset or it will > * use the last value (and so the last PHY set). > */ > - ret = sun8i_dwmac_reset(priv); > + ret = sun8i_dwmac_reset(priv->ioaddr); > + if (ret) > + dev_err(priv->device, "EMAC reset timeout\n"); > } > return ret; > } > @@ -1217,10 +1219,6 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) > dev_err(&pdev->dev, "Failed to register mux\n"); > goto dwmac_mux; > } > - } else { > - ret = sun8i_dwmac_reset(priv); > - if (ret) > - goto dwmac_remove; > } > > pm_runtime_put(&pdev->dev); >
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider. Critical: 0 · High: 1 (1) · Medium: 3 · Low: 2 If you believe none of the issues are legitimate, please reply to each issue of Medium severity or higher and explain why the AI is wrong. If any of them are legitimate and you plan to respin, please let patchwork know by including "pw-bot: cr" as a separate line at the end of your reply (one such reply per series is enough). - [High] A reset timeout during an MTU-change reopen leaves the still- running netdev owning freed DMA resources, causing a later double free. - [Medium] Incomplete fix: the retained probe-time MAC soft reset in mdio_mux_syscon_switch_fn()… - [Medium] Reset-timeout failure path leaves the EMAC un-quiesced. - [Medium] The MAC reset timeout is shorter than the PHY receive-clock startup interval that IEEE 802.3 permits, so the newly relocated reset… - [Low] The patch fixes a user-visible failure (MAC probe fails and the netdev plus its MDIO bus are torn down when the PHY driver has not… - [Low] Stale comment and vacuous runtime-PM window in sun8i_dwmac_probe(). Pre-existing issues: - [High] Use-after-free on the sun8i_dwmac_probe() `dwmac_mux:` error path. -- net: stmmac: sun8i: reset the MAC after PHY initialization This moves the sun8i EMAC software reset out of probe and into the stmmac ->reset (DMA reset) callback, so it runs during hardware setup once the PHY has been attached and resumed. The H3 MDIO-mux reset after switching the syscon mux is kept, and sun8i_dwmac_reset() now takes an ioaddr instead of a stmmac_priv. A few questions below. > diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c > index 48c52eb962335..4523a14f5e0c3 100644 > --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c > +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c > @@ -269,11 +269,32 @@ static const struct emac_variant emac_variant_h6 = { > #define SYSCON_ETCS_EXT_GMII 0x1 > #define SYSCON_ETCS_INT_GMII 0x2 > > +static int sun8i_dwmac_reset(void __iomem *ioaddr) > +{ > + u32 v; > + > + v = readl(ioaddr + EMAC_BASIC_CTL1); > + writel(v | 0x01, ioaddr + EMAC_BASIC_CTL1); > + > + /* The timeout was previously set to 10ms, but some board (OrangePI0) > + * need more if no cable plugged. 100ms seems OK > + */ > + return readl_poll_timeout(ioaddr + EMAC_BASIC_CTL1, v, > + !(v & 0x01), 100, 100000); > +} [Severity: Medium] Is 100 ms enough for this poll now that the reset runs right after the PHY is brought back out of power-down? sun8i_dwmac_dma_reset() is reached from stmmac_hw_setup(), which is called after phylink_prepare_resume() on the reopen and resume paths. phylink_prepare_resume() says it does not wait for the receive clock: drivers/net/phy/phylink.c:phylink_prepare_resume() { /* IEEE 802.3 22.2.4.1.5 allows PHYs to stop their receive clock * when PDOWN is set. ... Note that 802.3 allows PHYs 500ms before * the clock meets requirements. We do not implement this delay. */ if (pl->config->mac_requires_rxc && phydev && phydev->suspended) phy_resume(phydev); } stmmac sets mac_requires_rxc, so for a PHY that takes longer than 100 ms after leaving PDOWN to produce a valid RXC, would the reset time out and make stmmac_hw_setup() fail on MTU change and on system resume? > /* sun8i_dwmac_dma_reset() - reset the EMAC > * Called from stmmac via stmmac_dma_ops->reset > */ > static int sun8i_dwmac_dma_reset(void __iomem *ioaddr) > { > + int ret; > + > + /* The PHY receive clock must be running for the reset to complete. */ > + ret = sun8i_dwmac_reset(ioaddr); > + if (ret) > + return ret; > + > writel(0, ioaddr + EMAC_RX_CTL1); > writel(0, ioaddr + EMAC_TX_CTL1); > writel(0, ioaddr + EMAC_RX_FRM_FLT); [Severity: Medium] Does this early return leave the EMAC un-quiesced? Two things change on the timeout path. First, sun8i_dwmac_reset() has already set the self-clearing SOFT_RST request (bit 0 of EMAC_BASIC_CTL1) and nothing withdraws it. Second, the register clearing that the ->reset callback previously did unconditionally is now skipped: writel(0, ioaddr + EMAC_RX_CTL1); writel(0, ioaddr + EMAC_TX_CTL1); writel(0, ioaddr + EMAC_RX_FRM_FLT); writel(0, ioaddr + EMAC_RX_DESC_LIST); writel(0, ioaddr + EMAC_TX_DESC_LIST); writel(0, ioaddr + EMAC_INT_EN); writel(0x1FFFFFF, ioaddr + EMAC_INT_STA); The callers do not compensate. In stmmac_main.c, __stmmac_open() reaches init_error: which only returns, unlike irq_error: which calls stmmac_stop_all_dma(). stmmac_resume() likewise just powers down the legacy serdes and returns. On resume the host IRQ is still registered while EMAC_INT_EN keeps the enables from before suspend (stmmac_suspend only calls stmmac_stop_all_dma()) and EMAC_INT_STA is never acknowledged. Should the descriptor lists and interrupt registers still be cleared before returning the error? [Severity: High] Can a reset timeout here turn an MTU change into a double free of the DMA resources? stmmac_change_mtu() releases the interface and reopens it with the new configuration: drivers/net/ethernet/stmicro/stmmac/stmmac_main.c:stmmac_change_mtu() { __stmmac_release(dev); ret = __stmmac_open(dev, dma_conf); if (ret) { free_dma_desc_resources(priv, dma_conf); kfree(dma_conf); netdev_err(priv->dev, "failed reopening the interface after MTU change\n"); return ret; } } __stmmac_open() publishes the new pointers before the fallible setup: memcpy(&priv->dma_conf, dma_conf, sizeof(*dma_conf)); ... phylink_prepare_resume(priv->phylink); ... ret = stmmac_hw_setup(dev); if (ret < 0) goto init_error; struct stmmac_dma_conf embeds rx_queue[] and tx_queue[] by value, so priv->dma_conf ends up with its own copies of the descriptor, buffer and page pool pointers that stmmac_change_mtu() then frees. The interface stays administratively up, and the next close does: drivers/net/ethernet/stmicro/stmmac/stmmac_main.c:__stmmac_release() { /* Release and free the Rx/Tx resources */ free_dma_desc_resources(priv, &priv->dma_conf); } The MTU reopen is also the case where phylink_stop() has just powered the PHY down, so the new -ETIMEDOUT from sun8i_dwmac_dma_reset() is reachable there. The core recovery gap in stmmac_change_mtu() and __stmmac_open() predates this patch, but the commit message says it wants to "return reset errors through the normal hardware-setup error path" - is that path safe to use on sun8i today? [ ... ] > @@ -895,7 +895,9 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child, > /* After changing syscon value, the MAC need reset or it will > * use the last value (and so the last PHY set). > */ > - ret = sun8i_dwmac_reset(priv); > + ret = sun8i_dwmac_reset(priv->ioaddr); > + if (ret) > + dev_err(priv->device, "EMAC reset timeout\n"); > } > return ret; > } [Severity: Medium] Does this call site keep the receive-clock dependency the commit message says it removes? The new comment in sun8i_dwmac_dma_reset() states "The PHY receive clock must be running for the reset to complete", and the core honours that: stmmac_hw_setup() wraps stmmac_init_dma_engine() in phylink_rx_clk_stop_block(), and __stmmac_open()/stmmac_resume() call phylink_prepare_resume() first. mdio_mux_syscon_switch_fn() has neither guarantee. It runs during MAC probe: sun8i_dwmac_register_mdio_mux() mdio_mux_init() of_mdiobus_register(child) mdio_mux_read() mdio_mux_syscon_switch_fn() sun8i_dwmac_reset(priv->ioaddr) so no PHY driver can have been bound yet, and for DWMAC_SUN8I_MDIO_MUX_EXTERNAL_ID the internal EPHY has just been unpowered by sun8i_dwmac_unpower_internal_phy(). On timeout the error propagates out of mdio_mux_read(), the child bus PHY scan fails, and mdio-mux.c drops that child without failing mdio_mux_init() as a whole: drivers/net/mdio/mdio-mux.c:mdio_mux_init() { r = of_mdiobus_register(cb->mii_bus, child_bus_node); if (r) { mdiobus_free(cb->mii_bus); if (r == -EPROBE_DEFER) { ... } devm_kfree(dev, cb); dev_err(dev, "Error: Failed to register MDIO bus for child %pOF: %pe\n", ...); } Would probe then succeed with the external PHY permanently absent, which is the same reprobe-to-recover state the commit describes fixing? Separately, the timeout now only logs. The syscon mux field has already been rewritten and the EPHY power state already changed while the MAC has not latched the new selection - should either be restored before returning? [Severity: High] This isn't a bug introduced by this patch, but the reset kept here makes an existing unbalanced probe teardown easier to reach. When mdio_mux_syscon_switch_fn() has already taken the internal branch, sun8i_dwmac_power_internal_phy() has set gmac->internal_phy_powered, and sun8i_dwmac_register_mdio_mux() then fails (this reset timing out, or of_mdiobus_register() returning -EPROBE_DEFER, or mdio_mux_init() returning -ENODEV for "No acceptable child buses found"), probe takes goto dwmac_mux: drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c:sun8i_dwmac_probe() { dwmac_mux: reset_control_put(gmac->rst_ephy); clk_put(gmac->ephy_clk); dwmac_remove: pm_runtime_put_noidle(&pdev->dev); stmmac_pltfr_remove(pdev); } stmmac_pltfr_remove() -> stmmac_dvr_remove() ends with priv->plat->exit(dev, priv->plat->bsp_priv), which is sun8i_dwmac_exit(): if (gmac->variant->soc_has_internal_phy) sun8i_dwmac_unpower_internal_phy(gmac); and because internal_phy_powered is still true: drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c:sun8i_dwmac_unpower_internal_phy() { if (!gmac->internal_phy_powered) return; clk_disable_unprepare(gmac->ephy_clk); reset_control_assert(gmac->rst_ephy); } Does this use the clk and reset_control after they were put? sun8i_dwmac_remove() uses the other order, unpowering before putting: mdio_mux_uninit(gmac->mux_handle); sun8i_dwmac_unpower_internal_phy(gmac); reset_control_put(gmac->rst_ephy); clk_put(gmac->ephy_clk); > @@ -1217,10 +1219,6 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) > dev_err(&pdev->dev, "Failed to register mux\n"); > goto dwmac_mux; > } > - } else { > - ret = sun8i_dwmac_reset(priv); > - if (ret) > - goto dwmac_remove; > } > > pm_runtime_put(&pdev->dev); [Severity: Low] With this else arm gone, the comment above pm_runtime_get_sync() in sun8i_dwmac_probe() no longer matches the code: /* the MAC is runtime suspended after stmmac_dvr_probe(), so we * need to ensure the MAC resume back before other operations such * as reset. */ pm_runtime_get_sync(&pdev->dev); There is no reset left in probe. The only remaining work between the get_sync and pm_runtime_put() is the if (gmac->variant->soc_has_internal_phy) block, so for v3s, a83t, r40, a64 and h6 the pair now brackets nothing. Should the comment be updated, and should the get/put be moved inside the soc_has_internal_phy branch? [Severity: Low] Should this carry a Fixes: tag and a target tree? The commit fixes a user-visible failure where probe tears down the netdev and its MDIO bus. git blame on the removed if/else and probe-time reset points at 634db83b8265 ("net: stmmac: dwmac-sun8i: add support for mdio-mux"), on top of the original driver 9f93ac8d4085 ("net-next: stmmac: Add dwmac-sun8i").
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c index 48c52eb96233..4523a14f5e0c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-sun8i.c @@ -269,11 +269,32 @@ static const struct emac_variant emac_variant_h6 = { #define SYSCON_ETCS_EXT_GMII 0x1 #define SYSCON_ETCS_INT_GMII 0x2 +static int sun8i_dwmac_reset(void __iomem *ioaddr) +{ + u32 v; + + v = readl(ioaddr + EMAC_BASIC_CTL1); + writel(v | 0x01, ioaddr + EMAC_BASIC_CTL1); + + /* The timeout was previously set to 10ms, but some board (OrangePI0) + * need more if no cable plugged. 100ms seems OK + */ + return readl_poll_timeout(ioaddr + EMAC_BASIC_CTL1, v, + !(v & 0x01), 100, 100000); +} + /* sun8i_dwmac_dma_reset() - reset the EMAC * Called from stmmac via stmmac_dma_ops->reset */ static int sun8i_dwmac_dma_reset(void __iomem *ioaddr) { + int ret; + + /* The PHY receive clock must be running for the reset to complete. */ + ret = sun8i_dwmac_reset(ioaddr); + if (ret) + return ret; + writel(0, ioaddr + EMAC_RX_CTL1); writel(0, ioaddr + EMAC_TX_CTL1); writel(0, ioaddr + EMAC_RX_FRM_FLT); @@ -738,27 +759,6 @@ static void sun8i_dwmac_flow_ctrl(struct mac_device_info *hw, writel(v, ioaddr + EMAC_TX_FLOW_CTL); } -static int sun8i_dwmac_reset(struct stmmac_priv *priv) -{ - u32 v; - int err; - - v = readl(priv->ioaddr + EMAC_BASIC_CTL1); - writel(v | 0x01, priv->ioaddr + EMAC_BASIC_CTL1); - - /* The timeout was previously set to 10ms, but some board (OrangePI0) - * need more if no cable plugged. 100ms seems OK - */ - err = readl_poll_timeout(priv->ioaddr + EMAC_BASIC_CTL1, v, - !(v & 0x01), 100, 100000); - - if (err) { - dev_err(priv->device, "EMAC reset timeout\n"); - return err; - } - return 0; -} - /* Search in mdio-mux node for internal PHY node and get its clk/reset */ static int get_ephy_nodes(struct stmmac_priv *priv) { @@ -895,7 +895,9 @@ static int mdio_mux_syscon_switch_fn(int current_child, int desired_child, /* After changing syscon value, the MAC need reset or it will * use the last value (and so the last PHY set). */ - ret = sun8i_dwmac_reset(priv); + ret = sun8i_dwmac_reset(priv->ioaddr); + if (ret) + dev_err(priv->device, "EMAC reset timeout\n"); } return ret; } @@ -1217,10 +1219,6 @@ static int sun8i_dwmac_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Failed to register mux\n"); goto dwmac_mux; } - } else { - ret = sun8i_dwmac_reset(priv); - if (ret) - goto dwmac_remove; } pm_runtime_put(&pdev->dev);