From: Maxime Chevallier <maxime.chevallier@bootlin.com>
To: vadik likholetov <vadikas@gmail.com>, netdev@vger.kernel.org
Cc: andrew@lunn.ch, andrew+netdev@lunn.ch, davem@davemloft.net,
edumazet@google.com, kuba@kernel.org, pabeni@redhat.com,
thierry.reding@kernel.org, jonathanh@nvidia.com,
vbhadram@nvidia.com, linux-tegra@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: [PATCH net v2] net: stmmac: enable the MAC on link up for all supported speeds
Date: Sun, 12 Jul 2026 11:02:58 +0200 [thread overview]
Message-ID: <bab33e22-b346-47d3-9b22-4646e68c6983@bootlin.com> (raw)
In-Reply-To: <20260712065522.30241-1-vadikas@gmail.com>
Hi,
When sending a new iteration, it should be a standalone thread, and not
a reply to the previous version. Patchwork seems to have picked it up, so
I _think_ it's ok for this one though :)
On 7/12/26 08:55, vadik likholetov wrote:
> stmmac_mac_link_down() clears the MAC's transmit and receive enable bits.
> stmmac_mac_link_up() is expected to set them again through
> stmmac_mac_set(..., true), but it first switches on the negotiated speed
> and returns early for a speed the switch does not list. The MAC is then
> left gated off.
>
> The speed selection is split into three switches, keyed on the interface.
> The generic branch -- taken for everything that is neither USXGMII nor
> XLGMII, so including PHY_INTERFACE_MODE_10GBASER -- lists only SPEED_2500,
> SPEED_1000, SPEED_100 and SPEED_10.
>
> MGBE on Tegra234 runs 10GBASE-R into an Aquantia AQR113C. That PHY does
> rate matching, so phylink_link_up() replaces the media speed with the
> MAC-side interface speed before calling into the MAC:
>
> case RATE_MATCH_PAUSE:
> speed = phylink_interface_max_speed(link_state.interface);
> duplex = DUPLEX_FULL;
>
> The driver is therefore called as
>
> stmmac_mac_link_up(interface=10GBASER, speed=10000, duplex=1)
>
> which falls through to "default: return;". The interface stops passing
> traffic after the first link flap.
>
> The failure is easy to misread. The link still comes up, because the PHY
> is polled over MDIO and needs no MAC, so the interface reports carrier 1
> at the media speed. The DMA is untouched, so its start bits stay set and
> descriptors are still consumed. Only the MAC itself is gated off: the
> receiver counts nothing (mmc_rx_framecount_gb stops advancing, RE is 0)
> and nothing reaches the wire (TE is 0). The interface survives boot only
> because stmmac_hw_setup(), called from ndo_open, enables the MAC
> unconditionally -- so the problem appears only once the cable has been
> unplugged and plugged back in, and "ip link set dev <ethX> down && ip
> link set dev <ethX> up" appears to fix it.
>
> The interface is not what the speed bits depend on: with the single
> exception of 2.5G, which is selected through the XGMII block on USXGMII
> and through the regular speed bits otherwise, each speed maps to one
> field of struct mac_link. The per-interface switches are speed
> validation, and phylink already validates the speed against
> priv->hw->link.caps. So collapse the three switches into one keyed on the
> speed alone, keeping the interface test only for the 2.5G case. This
> covers 10G on 10GBASE-R, and equally 5G, and 1G/100/10 on USXGMII, all of
> which hit "default: return;" today.
>
> A core that does not support a speed leaves the corresponding mac_link
> field at 0, and phylink will not offer it that speed in the first place.
> For dwxgmac2 at 10G, link.xgmii.speed10000 is XGMAC_CONFIG_SS_10000,
> which is 0 and is the correct speed selection for a 10GBASE-R MAC: ctrl
> then equals old_ctrl, the register write is skipped, and execution
> reaches stmmac_mac_set(..., true).
>
> Log an error in the default case, since a speed with no entry here leaves
> the MAC disabled and the symptom does not point at the cause.
>
> Fixes: d8ca113724e7 ("net: stmmac: tegra: Add MGBE support")
> Suggested-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
> Signed-off-by: vadik likholetov <vadikas@gmail.com>
> ---
> v2:
> - Collapse the three per-interface switches into a single switch on the
> speed, rather than adding SPEED_10000 to the generic branch, which
> left SPEED_5000 and the USXGMII sub-1G speeds broken (Maxime).
> - netdev_err() in the default case (Andrew).
>
> Fixes tag: the missing speeds predate the commit cited above. I picked
> d8ca113724e7 because MGBE is the first in-tree user to reach it -- it
> needs a 10GBASE-R interface driven by a rate-matching PHY, so that
> phylink hands the MAC a 10G speed. Happy to re-target it.
>
> Verified on an AGX Orin devkit (Tegra234 MGBE0 + AQR113C), before and
> after, on the same board and cable. MAC registers read with `ethtool -d`,
> after a physical unplug and replug:
>
> stock MAC_TX_CONFIG 0x00010000 (TE=0)
> MAC_RX_CONFIG 0x3ff022c0 (RE=0)
> rx_packets frozen, DHCP lease lost
>
> patched MAC_TX_CONFIG 0x00010001 (TE=1)
> MAC_RX_CONFIG 0x3ff022c1 (RE=1)
> rx_packets keeps climbing, DHCP lease retained
>
> Only the 10GBASE-R path is covered by hardware here; the other speeds are
> by inspection. Testing was done with MGBE0 handed to a VM via
> vfio-platform, so the driver ran in a guest; the MAC register evidence
> above is read from the device itself and the code path is not
> virtualisation-specific.
>
> .../net/ethernet/stmicro/stmmac/stmmac_main.c | 92 ++++++++-----------
> 1 file changed, 37 insertions(+), 55 deletions(-)
>
> diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> index 2a0d7eff8..fa9f88e51 100644
> --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
> @@ -1083,63 +1083,45 @@ static void stmmac_mac_link_up(struct phylink_config *config,
> old_ctrl = readl(priv->ioaddr + MAC_CTRL_REG);
> ctrl = old_ctrl & ~priv->hw->link.speed_mask;
>
> - if (interface == PHY_INTERFACE_MODE_USXGMII) {
> - switch (speed) {
> - case SPEED_10000:
> - ctrl |= priv->hw->link.xgmii.speed10000;
> - break;
> - case SPEED_5000:
> - ctrl |= priv->hw->link.xgmii.speed5000;
> - break;
> - case SPEED_2500:
> + switch (speed) {
> + case SPEED_100000:
> + ctrl |= priv->hw->link.xlgmii.speed100000;
> + break;
> + case SPEED_50000:
> + ctrl |= priv->hw->link.xlgmii.speed50000;
> + break;
> + case SPEED_40000:
> + ctrl |= priv->hw->link.xlgmii.speed40000;
> + break;
> + case SPEED_25000:
> + ctrl |= priv->hw->link.xlgmii.speed25000;
> + break;
> + case SPEED_10000:
> + ctrl |= priv->hw->link.xgmii.speed10000;
> + break;
> + case SPEED_5000:
> + ctrl |= priv->hw->link.xgmii.speed5000;
> + break;
> + case SPEED_2500:
> + if (interface == PHY_INTERFACE_MODE_USXGMII)
> ctrl |= priv->hw->link.xgmii.speed2500;
> - break;
> - default:
> - return;
> - }
> - } else if (interface == PHY_INTERFACE_MODE_XLGMII) {
> - switch (speed) {
> - case SPEED_100000:
> - ctrl |= priv->hw->link.xlgmii.speed100000;
> - break;
> - case SPEED_50000:
> - ctrl |= priv->hw->link.xlgmii.speed50000;
> - break;
> - case SPEED_40000:
> - ctrl |= priv->hw->link.xlgmii.speed40000;
> - break;
> - case SPEED_25000:
> - ctrl |= priv->hw->link.xlgmii.speed25000;
> - break;
> - case SPEED_10000:
> - ctrl |= priv->hw->link.xgmii.speed10000;
> - break;
> - case SPEED_2500:
> - ctrl |= priv->hw->link.speed2500;
> - break;
> - case SPEED_1000:
> - ctrl |= priv->hw->link.speed1000;
> - break;
> - default:
> - return;
> - }
> - } else {
> - switch (speed) {
> - case SPEED_2500:
> + else
> ctrl |= priv->hw->link.speed2500;
> - break;
> - case SPEED_1000:
> - ctrl |= priv->hw->link.speed1000;
> - break;
> - case SPEED_100:
> - ctrl |= priv->hw->link.speed100;
> - break;
> - case SPEED_10:
> - ctrl |= priv->hw->link.speed10;
> - break;
> - default:
> - return;
> - }
> + break;
> + case SPEED_1000:
> + ctrl |= priv->hw->link.speed1000;
> + break;
> + case SPEED_100:
> + ctrl |= priv->hw->link.speed100;
> + break;
> + case SPEED_10:
> + ctrl |= priv->hw->link.speed10;
> + break;
> + default:
> + netdev_err(priv->dev,
> + "unsupported speed %d on %s, leaving the MAC disabled\n",
> + speed, phy_modes(interface));
You should probably be using phy_speed_to_str() to print the speed.
Thanks,
Maxime
prev parent reply other threads:[~2026-07-12 9:03 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-10 12:09 [PATCH net] net: stmmac: enable the MAC on link up at 10G on 10GBASE-R vadik likholetov
2026-07-10 13:30 ` Maxime Chevallier
2026-07-10 16:49 ` Andrew Lunn
2026-07-12 6:55 ` [PATCH net v2] net: stmmac: enable the MAC on link up for all supported speeds vadik likholetov
2026-07-12 9:02 ` Maxime Chevallier [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=bab33e22-b346-47d3-9b22-4646e68c6983@bootlin.com \
--to=maxime.chevallier@bootlin.com \
--cc=andrew+netdev@lunn.ch \
--cc=andrew@lunn.ch \
--cc=davem@davemloft.net \
--cc=edumazet@google.com \
--cc=jonathanh@nvidia.com \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-tegra@vger.kernel.org \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=thierry.reding@kernel.org \
--cc=vadikas@gmail.com \
--cc=vbhadram@nvidia.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox