diff --git a/drivers/net/phy/marvell10g.c b/drivers/net/phy/marvell10g.c index 8d0fd920289bc..3b5e746b6ca6e 100644 --- a/drivers/net/phy/marvell10g.c +++ b/drivers/net/phy/marvell10g.c @@ -154,11 +154,6 @@ 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; }; @@ -198,7 +193,6 @@ struct mv3310_ptp_priv *mv3310_ptp_probe(struct phy_device *phydev); int mv3310_ptp_power_up(struct mv3310_ptp_priv *priv); int mv3310_ptp_power_down(struct mv3310_ptp_priv *priv); int mv3310_ptp_start(struct mv3310_ptp_priv *priv); -int mv3310_ptp_update(struct mv3310_ptp_priv *priv); int mv3310_ptp_get_sset_count(struct mv3310_ptp_priv *priv); void mv3310_ptp_get_strings(u8 *data); void mv3310_ptp_get_stats(struct mv3310_ptp_priv *priv, @@ -221,10 +215,6 @@ static inline int mv3310_ptp_start(struct mv3310_ptp_priv *priv) { return 0; } -static inline int mv3310_ptp_update(struct mv3310_ptp_priv *priv) -{ - return 0; -} static inline int mv3310_ptp_get_sset_count(struct mv3310_ptp_priv *priv) { return 0; @@ -962,7 +952,6 @@ 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] = { @@ -997,7 +986,6 @@ 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] = { @@ -1016,7 +1004,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 || mactype->copper_multispeed) { + if (!mactype->fixed_interface) { __set_bit(PHY_INTERFACE_MODE_5GBASER, possible); __set_bit(PHY_INTERFACE_MODE_2500BASEX, possible); __set_bit(PHY_INTERFACE_MODE_SGMII, possible); @@ -1054,15 +1042,10 @@ 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. - /* 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. - */ + /* Force XFI/SGMII/Auto-neg mode regardless of strap configuration */ 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_RATE_MATCH); + MV_V2_33X0_PORT_CTRL_MACTYPE_10GBASER); if (err) return err; @@ -1362,11 +1345,8 @@ static int mv3310_read_status(struct phy_device *phydev) if (err < 0) return err; - if (phydev->link) { - struct mv3310_priv *priv = dev_get_drvdata(&phydev->mdio.dev); + if (phydev->link) mv3310_update_interface(phydev); - mv3310_ptp_update(priv->ptp_priv); - } return 0; } diff --git a/drivers/net/phy/marvell10g_ptp.c b/drivers/net/phy/marvell10g_ptp.c index 02496f847b381..e1d57035a9ecf 100644 --- a/drivers/net/phy/marvell10g_ptp.c +++ b/drivers/net/phy/marvell10g_ptp.c @@ -39,10 +39,17 @@ enum { MV_V2_LINK_RESET_CFG_DEF_VAL = 0x3900, MV_V2_LINK_RESET_CFG_LINK_DOWN = BIT(0), + /* + * Maximum receive unit (MRU) control registers. 1G/2.5G mode and XG + * mode have separate register groups; both are programmed for jumbo + * frames at power-up so no runtime reconfiguration is needed. + */ MV_V2_SMC_1G_MRU_CTRL_REG = 0x8c00, MV_V2_WMC_1G_MRU_CTRL_REG = 0x8e00, MV_V2_SMC_XG_MRU_CTRL_REG = 0x8c02, MV_V2_WMC_XG_MRU_CTRL_REG = 0x8e02, + MV_V2_MRU_MAX = 0x1fff, /* 16382 bytes, XG group: bits [12:0] */ + MV_V2_MRU_1G_MAX = (0x1fff << 2), /* 16382 bytes, 1G/2.5G group: bits [15:2] */ MV_V2_MODE_CFG = 0xf000, MV_V2_MODE_CFG_M_UNIT_PWRUP = BIT(12), @@ -103,7 +110,6 @@ struct mv3310_ptp_priv { struct ptp_clock *clock; struct mutex lock; /* Protects against concurrent MDIO register access */ struct mii_timestamper mii_ts; - int old_speed; /* Last speed used to set MRU */ bool extts_enabled; }; @@ -141,16 +147,12 @@ struct mv3310_ptp_priv *mv3310_ptp_probe(struct phy_device *phydev); int mv3310_ptp_power_up(struct mv3310_ptp_priv *priv); int mv3310_ptp_power_down(struct mv3310_ptp_priv *priv); int mv3310_ptp_start(struct mv3310_ptp_priv *priv); -int mv3310_ptp_update(struct mv3310_ptp_priv *priv); /* Get statistics from the PHY using ethtool */ int mv3310_ptp_get_sset_count(struct mv3310_ptp_priv *priv); void mv3310_ptp_get_strings(u8 *data); void mv3310_ptp_get_stats(struct mv3310_ptp_priv *priv, struct ethtool_stats *stats, u64 *data); -/* General configuration functions */ -static int mv3310_set_mac_mru(struct mv3310_ptp_priv *priv, int speed); - /* Helper functions */ static int mv3310_read_ptp_reg(struct phy_device *phydev, u32 regnum, u32 *regval); @@ -237,7 +239,6 @@ struct mv3310_ptp_priv *mv3310_ptp_probe(struct phy_device *phydev) priv->phydev = phydev; mutex_init(&priv->lock); - priv->old_speed = SPEED_UNKNOWN; priv->extts_enabled = false; /* Setup timestamping */ @@ -285,7 +286,7 @@ int mv3310_ptp_power_up(struct mv3310_ptp_priv *priv) if (!priv) return 0; - + phydev = priv->phydev; mutex_lock(&priv->lock); @@ -307,15 +308,12 @@ int mv3310_ptp_power_up(struct mv3310_ptp_priv *priv) MV_V2_SLC_CFG_GEN_SMC_ADD_CRC | MV_V2_SLC_CFG_GEN_WMC_STRIP_CRC | MV_V2_SLC_CFG_GEN_SMC_STRIP_CRC); - - /* Increase the MRU for the default mode (XG) */ - ret |= mv3310_set_mac_mru(priv, SPEED_10000); - /* Disable store-and-forward mode for egress drop FIFO. Without this setting there are time error spikes of up to 1200ns when performing 1588TC accuracy measurements. */ ret |= mv3310_clear_ptp_reg_bits(phydev, MV_V2_SLC_CFG_GEN, MV_V2_SLC_CFG_GEN_EGR_SF_EN); + unlock_out: mutex_unlock(&priv->lock); return ret; @@ -364,58 +362,30 @@ int mv3310_ptp_start(struct mv3310_ptp_priv *priv) if (ret < 0) dev_err(&phydev->mdio.dev, "failed to enable PTP core: %d\n", ret); - mutex_unlock(&priv->lock); - - return ret; -} - -int mv3310_ptp_update(struct mv3310_ptp_priv *priv) -{ - int ret; - - if (!priv) - return 0; - - mutex_lock(&priv->lock); - ret = mv3310_set_mac_mru(priv, priv->phydev->speed); - mutex_unlock(&priv->lock); - return ret; -} - -static int mv3310_set_mac_mru(struct mv3310_ptp_priv *priv, int speed) -{ - const u32 MAX_MRU = 0x1fff; /* 16382 bytes */ - int ret = 0; - struct phy_device *phydev = priv->phydev; - - if ((priv->old_speed != SPEED_UNKNOWN) && - ((speed < SPEED_5000 && priv->old_speed < SPEED_5000) || - (speed >= SPEED_5000 && priv->old_speed >= SPEED_5000))) { - /* No need to change the MRU if the new speed is in the same speed class */ - priv->old_speed = speed; - return 0; - } - - if (speed < SPEED_5000) { - /* Configuration registers for 1/2.5G mode */ - ret |= mv3310_set_ptp_reg_bits( - phydev, MV_V2_SMC_1G_MRU_CTRL_REG, MAX_MRU << 2U); - ret |= mv3310_set_ptp_reg_bits( - phydev, MV_V2_WMC_1G_MRU_CTRL_REG, MAX_MRU << 2U); - } else { - /* Configuration registers for XG mode */ - ret |= mv3310_write_ptp_reg(phydev, MV_V2_SMC_XG_MRU_CTRL_REG, - MAX_MRU); - ret |= mv3310_write_ptp_reg(phydev, MV_V2_WMC_XG_MRU_CTRL_REG, - MAX_MRU); - } + /* + * Configure maximum MRU for both speed-class register groups so that + * jumbo frames are supported at any copper speed. Done here (after + * SWRST has completed in mv3310_power_up) rather than in ptp_power_up + * because writing PTP registers before SWRST corrupts PHY host SerDes + * state on the subsequent link-up cycle. + * + * XG group (0x8c02/0x8e02): use write_ptp_reg (direct 32-bit write). + * 1G/2.5G group (0x8c00/0x8e00): use set_ptp_reg_bits (read-modify- + * write) to set only the MRU field in bits[15:2] without zeroing the + * adjacent control word at 0x8c01/0x8e01, which write_ptp_reg would do. + */ + ret |= mv3310_write_ptp_reg(phydev, MV_V2_SMC_XG_MRU_CTRL_REG, + MV_V2_MRU_MAX); + ret |= mv3310_write_ptp_reg(phydev, MV_V2_WMC_XG_MRU_CTRL_REG, + MV_V2_MRU_MAX); + ret |= mv3310_set_ptp_reg_bits(phydev, MV_V2_SMC_1G_MRU_CTRL_REG, + MV_V2_MRU_1G_MAX); + ret |= mv3310_set_ptp_reg_bits(phydev, MV_V2_WMC_1G_MRU_CTRL_REG, + MV_V2_MRU_1G_MAX); if (ret < 0) - dev_err_ratelimited(&phydev->mdio.dev, - "failed to set MRU for speed=%d (%d)\n", - speed, ret); - else - priv->old_speed = speed; + dev_err(&phydev->mdio.dev, "failed to set MRU: %d\n", ret); + mutex_unlock(&priv->lock); return ret; }