From e9fa5d2405342be2e16514f90c22b6e2e25b70cd Mon Sep 17 00:00:00 2001 From: Russell King Date: Mon, 22 Jun 2020 01:05:59 +0100 Subject: net: dsa: bcm_sf2: fix pause mode validation The implementation appears not to appear to support pause modes on anything but RGMII, RGMII_TXID, MII and REVMII interface modes. Let phylink know that detail. Moreover, RGMII_RXID and RGMII_ID appears to be unsupported. (This may not be correct; particularly see the FIXMEs in this patch.) Signed-off-by: Russell King --- drivers/net/dsa/bcm_sf2.c | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) (limited to 'drivers') diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index 114d4ba7716f..9f8a43476093 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -686,6 +686,8 @@ static void bcm_sf2_sw_get_caps(struct dsa_switch *ds, int port, __set_bit(PHY_INTERFACE_MODE_MII, interfaces); __set_bit(PHY_INTERFACE_MODE_REVMII, interfaces); __set_bit(PHY_INTERFACE_MODE_GMII, interfaces); + + /* FIXME: Are RGMII_RXID and RGMII_ID actually supported? */ phy_interface_set_rgmii(interfaces); } @@ -693,6 +695,32 @@ static void bcm_sf2_sw_get_caps(struct dsa_switch *ds, int port, MAC_10 | MAC_100 | MAC_1000; } +static void bcm_sf2_sw_validate(struct dsa_switch *ds, int port, + unsigned long *supported, + struct phylink_link_state *state) +{ + struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds); + __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; + u32 caps; + + caps = dsa_to_port(ds, port)->pl_config.mac_capabilities; + + /* Pause modes are only programmed for these modes */ + if (!(state->interface == PHY_INTERFACE_MODE_RGMII || + state->interface == PHY_INTERFACE_MODE_RGMII_TXID || + state->interface == PHY_INTERFACE_MODE_MII || + state->interface == PHY_INTERFACE_MODE_REVMII)) + caps &= ~(MAC_ASYM_PAUSE | MAC_SYM_PAUSE); + + /* Allow all the expected bits */ + phylink_set(mask, Autoneg); + phylink_set_port_modes(mask); + phylink_get_linkmodes(mask, state->interface, caps); + + linkmode_and(supported, supported, mask); + linkmode_and(state->advertising, state->advertising, mask); +} + static void bcm_sf2_sw_mac_config(struct dsa_switch *ds, int port, unsigned int mode, const struct phylink_link_state *state) @@ -706,6 +734,7 @@ static void bcm_sf2_sw_mac_config(struct dsa_switch *ds, int port, return; switch (state->interface) { + /* FIXME: Are RGMII_RXID and RGMII_ID actually supported? */ case PHY_INTERFACE_MODE_RGMII: id_mode_dis = 1; fallthrough; @@ -806,6 +835,10 @@ static void bcm_sf2_sw_mac_link_up(struct dsa_switch *ds, int port, else offset = CORE_STS_OVERRIDE_GMIIP2_PORT(port); + /* FIXME: Are RGMII_RXID and RGMII_ID actually supported? + * Why are pause modes only supported for a couple of RGMII + * modes? + */ if (interface == PHY_INTERFACE_MODE_RGMII || interface == PHY_INTERFACE_MODE_RGMII_TXID || interface == PHY_INTERFACE_MODE_MII || @@ -1158,6 +1191,7 @@ static const struct dsa_switch_ops bcm_sf2_ops = { .get_ethtool_phy_stats = b53_get_ethtool_phy_stats, .get_phy_flags = bcm_sf2_sw_get_phy_flags, .phylink_get_caps = bcm_sf2_sw_get_caps, + .phylink_validate = bcm_sf2_sw_validate, .phylink_mac_config = bcm_sf2_sw_mac_config, .phylink_mac_link_down = bcm_sf2_sw_mac_link_down, .phylink_mac_link_up = bcm_sf2_sw_mac_link_up, -- cgit