[PATCH net 6/6] net: dsa: b53: apply resolved link settings to serial port MACs
From: Florian Fainelli
Date: Wed Oct 21 2026 - 15:19:30 EST
The serial port MAC callbacks leave speed, duplex and pause under the
hardware's autonomous control. In particular, changing phylink's pause
policy cannot affect the MAC when Clause 37 negotiation is in use.
Use the existing MAC override registers for SGMII and 1000BASE-X links,
including PHY and fixed-link negotiation modes. Apply the settings passed
by phylink at link-up and force the MAC link down at link-down. PCS power
and link observation remain independent of the MAC override.
Preserve the existing parallel-port handling, EEE initialization and
BCM5301x CPU-port pause quirk.
Fixes: 0e01491de646 ("net: dsa: b53: Add SerDes support")
Signed-off-by: Florian Fainelli <florian.fainelli@xxxxxxxxxxxx>
---
drivers/net/dsa/b53/b53_common.c | 50 +++++++++++++++-----------------
1 file changed, 23 insertions(+), 27 deletions(-)
diff --git a/drivers/net/dsa/b53/b53_common.c b/drivers/net/dsa/b53/b53_common.c
index b04f9d5f0525..172ada124cbf 100644
--- a/drivers/net/dsa/b53/b53_common.c
+++ b/drivers/net/dsa/b53/b53_common.c
@@ -1600,6 +1600,17 @@ static void b53_phylink_mac_config(struct phylink_config *config,
}
}
+static bool b53_phylink_mac_needs_override(struct b53_device *dev, int port,
+ unsigned int mode,
+ phy_interface_t interface)
+{
+ return mode == MLO_AN_FIXED ||
+ interface == PHY_INTERFACE_MODE_SGMII ||
+ interface == PHY_INTERFACE_MODE_1000BASEX ||
+ (mode == MLO_AN_PHY && is63xx(dev) &&
+ in_range(port, B53_63XX_RGMII0, 4));
+}
+
static void b53_phylink_mac_link_down(struct phylink_config *config,
unsigned int mode,
phy_interface_t interface)
@@ -1608,16 +1619,8 @@ static void b53_phylink_mac_link_down(struct phylink_config *config,
struct b53_device *dev = dp->ds->priv;
int port = dp->index;
- if (mode == MLO_AN_PHY) {
- if (is63xx(dev) && in_range(port, B53_63XX_RGMII0, 4))
- b53_force_link(dev, port, false);
- return;
- }
-
- if (mode == MLO_AN_FIXED) {
+ if (b53_phylink_mac_needs_override(dev, port, mode, interface))
b53_force_link(dev, port, false);
- return;
- }
}
static void b53_phylink_mac_link_up(struct phylink_config *config,
@@ -1633,29 +1636,22 @@ static void b53_phylink_mac_link_up(struct phylink_config *config,
struct ethtool_keee *p = &dev->ports[dp->index].eee;
int port = dp->index;
- if (mode == MLO_AN_PHY) {
- /* Re-negotiate EEE if it was enabled already */
+ /* Re-negotiate EEE if it was enabled already */
+ if (mode == MLO_AN_PHY)
p->eee_enabled = b53_eee_init(ds, port, phydev);
- if (is63xx(dev) && in_range(port, B53_63XX_RGMII0, 4)) {
- b53_force_port_config(dev, port, speed, duplex,
- tx_pause, rx_pause);
- b53_force_link(dev, port, true);
- }
-
+ if (!b53_phylink_mac_needs_override(dev, port, mode, interface))
return;
- }
- if (mode == MLO_AN_FIXED) {
- /* Force flow control on BCM5301x's CPU port */
- if (is5301x(dev) && dsa_is_cpu_port(ds, port))
- tx_pause = rx_pause = true;
-
- b53_force_port_config(dev, port, speed, duplex,
- tx_pause, rx_pause);
- b53_force_link(dev, port, true);
- return;
+ /* Force flow control on BCM5301x's CPU port */
+ if (mode == MLO_AN_FIXED && is5301x(dev) && dsa_is_cpu_port(ds, port)) {
+ tx_pause = true;
+ rx_pause = true;
}
+
+ /* PCS negotiation supplies state; the MAC applies phylink's policy. */
+ b53_force_port_config(dev, port, speed, duplex, tx_pause, rx_pause);
+ b53_force_link(dev, port, true);
}
int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering,
--
2.53.0