summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2020-06-22 01:05:59 +0100
committerRussell King (Oracle) <rmk+kernel@armlinux.org.uk>2022-01-18 10:17:15 +0000
commite9fa5d2405342be2e16514f90c22b6e2e25b70cd (patch)
tree41ae2580a687107fb0576cf77668042183ce5620 /drivers
parent80cc658950abaa5cf695a1e4f3bb7e1bd83f048f (diff)
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 <rmk+kernel@armlinux.org.uk>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/dsa/bcm_sf2.c34
1 files changed, 34 insertions, 0 deletions
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,