DORMANTno replies

[PATCH RFC net-next] net: dsa: mv88e6xxx: honor resolved flow control in mac_link_up

From: Luke Howard <hidden>
Date: 2026-07-03 07:26:55
Also in: lkml
Subsystem: marvell 88e6xxx ethernet switch fabric driver, networking drivers, networking [dsa], the rest · Maintainers: Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Vladimir Oltean, Linus Torvalds

Program the pause status resolved by phylink into the Port MAC
Control register when forcing the link up, and return flow control
to hardware resolution when forcing the link down, mirroring the
existing treatment of speed and duplex.

Flow control is programmed before port_sync_link() so that the
port's MAC control is not modified while the link is forced up.
The MAC has a single flow control enable covering both directions;
as the driver only advertises MAC_SYM_PAUSE, rx_pause and tx_pause
are always equal here.

A fixed-link port whose device tree node lacks the "pause" property
now has flow control explicitly disabled while the link is forced
up, rather than being left at the chip's default.

Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Luke Howard <redacted>
---
 drivers/net/dsa/mv88e6xxx/chip.c |  9 +++++++++
 drivers/net/dsa/mv88e6xxx/port.c | 20 ++++++++++++++++++++
 drivers/net/dsa/mv88e6xxx/port.h |  2 ++
 3 files changed, 31 insertions(+)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c
index 80b877c74513d..73c28bf2bf3cb 100644
--- a/drivers/net/dsa/mv88e6xxx/chip.c
+++ b/drivers/net/dsa/mv88e6xxx/chip.c
@@ -974,6 +974,10 @@ static void mv88e6xxx_mac_link_down(struct phylink_config *config,
 	     mode == MLO_AN_FIXED) && ops->port_sync_link)
 		err = ops->port_sync_link(chip, port, mode, false);
 
+	if (!err)
+		err = mv88e6xxx_port_set_force_flow_ctl(chip, port, false,
+							false);
+
 	if (!err && ops->port_set_speed_duplex)
 		err = ops->port_set_speed_duplex(chip, port, SPEED_UNFORCED,
 						 DUPLEX_UNFORCED);
@@ -1012,6 +1016,11 @@ static void mv88e6xxx_mac_link_up(struct phylink_config *config,
 				goto error;
 		}
 
+		err = mv88e6xxx_port_set_force_flow_ctl(chip, port, true,
+							rx_pause);
+		if (err)
+			goto error;
+
 		if (ops->port_sync_link)
 			err = ops->port_sync_link(chip, port, mode, true);
 	}
diff --git a/drivers/net/dsa/mv88e6xxx/port.c b/drivers/net/dsa/mv88e6xxx/port.c
index ea1fab71968a0..7ee802cf3412c 100644
--- a/drivers/net/dsa/mv88e6xxx/port.c
+++ b/drivers/net/dsa/mv88e6xxx/port.c
@@ -182,6 +182,26 @@ int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
 	return 0;
 }
 
+int mv88e6xxx_port_set_force_flow_ctl(struct mv88e6xxx_chip *chip, int port,
+				      bool force, bool value)
+{
+	u16 reg;
+	int err;
+
+	err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
+	if (err)
+		return err;
+
+	reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_FC | MV88E6XXX_PORT_MAC_CTL_FC);
+	if (force) {
+		reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_FC;
+		if (value)
+			reg |= MV88E6XXX_PORT_MAC_CTL_FC;
+	}
+
+	return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
+}
+
 int mv88e6xxx_port_sync_link(struct mv88e6xxx_chip *chip, int port, unsigned int mode, bool isup)
 {
 	const struct mv88e6xxx_ops *ops = chip->info->ops;
diff --git a/drivers/net/dsa/mv88e6xxx/port.h b/drivers/net/dsa/mv88e6xxx/port.h
index 5b6cde9f7406f..f98df6351f5b7 100644
--- a/drivers/net/dsa/mv88e6xxx/port.h
+++ b/drivers/net/dsa/mv88e6xxx/port.h
@@ -485,6 +485,8 @@ int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
 				   phy_interface_t mode);
 
 int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link);
+int mv88e6xxx_port_set_force_flow_ctl(struct mv88e6xxx_chip *chip, int port,
+				      bool force, bool value);
 
 int mv88e6xxx_port_sync_link(struct mv88e6xxx_chip *chip, int port, unsigned int mode, bool isup);
 int mv88e6185_port_sync_link(struct mv88e6xxx_chip *chip, int port, unsigned int mode, bool isup);
---
base-commit: 2bb62a85aff6d4c14a62a476dfabaada3c1cc014
change-id: 20260701-mv88e6xxx-flow-control-cafe32352712

Best regards,
--  
Luke Howard [off-list ref]
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help