From 0365a5c2199c7688d55c0decda11193fec489f5a Mon Sep 17 00:00:00 2001 From: Paul Tretiakov Date: Thu, 14 May 2026 22:51:07 +0100 Subject: [PATCH 1/2] net: phy: marvell10g: fix 88X3310 TX/RX broken after second link-up (TG-641) On 88X3310 with PTP enabled, TX and RX stop working from the second ip link set up onwards. The root cause is a race in mv3310_power_up(): the function issues a software reset (SWRST, MV_V2_PORT_CTRL bit 15) followed by msleep(100), but when resume is called again before the previous SWRST has fully completed, the new SWRST is issued while bit 15 is still asserted by the PHY. This corrupts the reset sequence and leaves the data path in a broken state. Fix this by polling MV_V2_PORT_CTRL bit 15 before issuing SWRST, waiting up to 200ms for the PHY to signal it is ready for a new reset (bit 15 = 0). Profiling showed that in normal operation the wait is under 10ms, but occasionally reaches ~157ms. If the poll times out, a warning is emitted and execution continues rather than aborting the power-up sequence. This is only applied to 88X3310 with firmware >= 0.3.0.0, matching the existing guard for the SWRST --- drivers/net/phy/marvell10g.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 94d31bb25b47e..195c5d6147daf 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -405,6 +405,16 @@ static int mv3310_power_up(struct phy_device *phydev) priv->firmware_ver < 0x00030000) return ret; + /* Poll until SWRST reads 0 (PHY ready for a new reset) before issuing + * SWRST. Without this, the second and subsequent link-up sequences + * result in broken TX/RX. The datasheet specifies bit 15 = 1 means + * reset in progress, 0 means normal operation. + */ + if (phy_read_mmd_poll_timeout(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, + ret, !(ret & MV_V2_33X0_PORT_CTRL_SWRST), + 5000, 200000, true)) + phydev_warn(phydev, "SWRST timed out 200ms\n"); + ret = phy_set_bits_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, MV_V2_33X0_PORT_CTRL_SWRST); msleep(100); From e9cf2db16f2b4f8b7eea52531f3714f10afe3ee3 Mon Sep 17 00:00:00 2001 From: Paul Tretiakov Date: Thu, 14 May 2026 23:15:37 +0100 Subject: [PATCH 2/2] net: phy: marvell10g: fix 10GBASE-R host serdes reset after link cycle (TG-641) Issue caused TX/RX to fail on the second and subsequent ip-link-down/up cycles on an 88X3310 PHY paired with an mvpp2 MAC configured for 10GBASE-R: wrong MACTYPE mode in config_init. mv3310_config_init forced MACTYPE to 10GBASER (XFI/SGMII auto-neg). In auto-neg mode the PHY switches its host-side serdes to SGMII at 1G link speed, which causes phylink to invoke mac_prepare/mac_config with a changed interface, which in turn causes mvpp2 to reinitialise the comphy from 10GBASE-R to SGMII. Since the 88X3310 always presents a fixed 10GBASE-R (XFI) serdes toward the MAC, the comphy reconfiguration corrupts the link and RX stays broken. Fix: always select RATE_MATCH mode (MACTYPE 6). In this mode the PHY presents a fixed 10GBASE-R serdes to the MAC and adapts the copper rate internally, so the MAC/comphy never needs reconfiguring across speed changes. Add a copper_multispeed flag to mv3310_mactype so that RATE_MATCH entries still expose SGMII/2.5G/5G in possible_interfaces, allowing phylink to validate and announce all copper speeds to user space. --- drivers/net/phy/marvell10g.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 195c5d6147daf..8d0fd920289bc 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -154,6 +154,11 @@ enum { struct mv3310_mactype { bool valid; bool fixed_interface; + /* PHY copper autoneg supports multiple speeds (1G/2.5G/5G/10G) even + * though the host-side interface is fixed (rate matching). This allows + * phylink to validate and advertise all copper speeds. + */ + bool copper_multispeed; phy_interface_t interface_10g; }; @@ -957,6 +962,7 @@ static const struct mv3310_mactype mv3310_mactypes[] = { [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH] = { .valid = true, .fixed_interface = true, + .copper_multispeed = true, .interface_10g = PHY_INTERFACE_MODE_10GBASER, }, [MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII] = { @@ -991,6 +997,7 @@ static const struct mv3310_mactype mv3340_mactypes[] = { [MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH] = { .valid = true, .fixed_interface = true, + .copper_multispeed = true, .interface_10g = PHY_INTERFACE_MODE_10GBASER, }, [MV_V2_33X0_PORT_CTRL_MACTYPE_USXGMII] = { @@ -1009,7 +1016,7 @@ static void mv3310_fill_possible_interfaces(struct phy_device *phydev) if (mactype->interface_10g != PHY_INTERFACE_MODE_NA) __set_bit(priv->mactype->interface_10g, possible); - if (!mactype->fixed_interface) { + if (!mactype->fixed_interface || mactype->copper_multispeed) { __set_bit(PHY_INTERFACE_MODE_5GBASER, possible); __set_bit(PHY_INTERFACE_MODE_2500BASEX, possible); __set_bit(PHY_INTERFACE_MODE_SGMII, possible); @@ -1047,10 +1054,15 @@ static int mv3310_config_init(struct phy_device *phydev) mv3310_config_init_clear_power_down(phydev); - /* Force XFI/SGMII/Auto-neg mode regardless of strap configuration */ + /* Force XFI/SGMII/Auto-neg mode regardless of strap configuration. + /* Default to rate-match mode so the host serdes stays fixed at 10GBASE-R + * regardless of copper wire speed. This is correct for MACs (e.g. mvpp2) that + * configure their comphy for 10GBASE-R and cannot handle the PHY switching + * the host interface to SGMII on 1G link-up. + */ err = phy_modify_mmd(phydev, MDIO_MMD_VEND2, MV_V2_PORT_CTRL, MV_V2_33X0_PORT_CTRL_MACTYPE_MASK, - MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER); + MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER_RATE_MATCH); if (err) return err;