From 78353a06b7aa098b1dc5bad04970b02cbcf312df 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 | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/drivers/net/dsa/bcm_sf2.c b/drivers/net/dsa/bcm_sf2.c index da90e182ae0e..2b184d2949c7 100644 --- a/drivers/net/dsa/bcm_sf2.c +++ b/drivers/net/dsa/bcm_sf2.c @@ -727,6 +727,10 @@ 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 1: Are RGMII_RXID and RGMII_ID actually supported? + * See FIXME 2 and FIXME 3 below. + */ phy_interface_set_rgmii(interfaces); } @@ -734,6 +738,35 @@ 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 - see FIXME 3. + * So, as pause modes are not configured for other modes, disable + * support for them. + */ + 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) @@ -747,6 +780,10 @@ static void bcm_sf2_sw_mac_config(struct dsa_switch *ds, int port, return; switch (state->interface) { + /* FIXME 2: Are RGMII_RXID and RGMII_ID actually supported? + * This switch statement means that the RGMII control register + * does not get programmed. + */ case PHY_INTERFACE_MODE_RGMII: id_mode_dis = 1; fallthrough; @@ -850,6 +887,10 @@ static void bcm_sf2_sw_mac_link_up(struct dsa_switch *ds, int port, else offset = CORE_STS_OVERRIDE_GMIIP2_PORT(port); + /* FIXME 3: 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 || @@ -1202,6 +1243,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