Skip to content

Commit baf18a2

Browse files
committed
net: dsa: mv88e6xxx: honor resolved flow control in mac_link_up
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 <lukeh@padl.com>
1 parent 9b76f18 commit baf18a2

3 files changed

Lines changed: 31 additions & 0 deletions

File tree

drivers/net/dsa/mv88e6xxx/chip.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,6 +1017,10 @@ static void mv88e6xxx_mac_link_down(struct phylink_config *config,
10171017
if (!err && ops->port_set_speed_duplex)
10181018
err = ops->port_set_speed_duplex(chip, port, SPEED_UNFORCED,
10191019
DUPLEX_UNFORCED);
1020+
1021+
if (!err)
1022+
err = mv88e6xxx_port_set_force_flow_ctl(chip, port, false,
1023+
false);
10201024
mv88e6xxx_reg_unlock(chip);
10211025

10221026
if (err)
@@ -1052,6 +1056,11 @@ static void mv88e6xxx_mac_link_up(struct phylink_config *config,
10521056
goto error;
10531057
}
10541058

1059+
err = mv88e6xxx_port_set_force_flow_ctl(chip, port, true,
1060+
rx_pause);
1061+
if (err)
1062+
goto error;
1063+
10551064
if (ops->port_sync_link)
10561065
err = ops->port_sync_link(chip, port, mode, true);
10571066
}

drivers/net/dsa/mv88e6xxx/port.c

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,26 @@ int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link)
182182
return 0;
183183
}
184184

185+
int mv88e6xxx_port_set_force_flow_ctl(struct mv88e6xxx_chip *chip, int port,
186+
bool force, bool value)
187+
{
188+
u16 reg;
189+
int err;
190+
191+
err = mv88e6xxx_port_read(chip, port, MV88E6XXX_PORT_MAC_CTL, &reg);
192+
if (err)
193+
return err;
194+
195+
reg &= ~(MV88E6XXX_PORT_MAC_CTL_FORCE_FC | MV88E6XXX_PORT_MAC_CTL_FC);
196+
if (force) {
197+
reg |= MV88E6XXX_PORT_MAC_CTL_FORCE_FC;
198+
if (value)
199+
reg |= MV88E6XXX_PORT_MAC_CTL_FC;
200+
}
201+
202+
return mv88e6xxx_port_write(chip, port, MV88E6XXX_PORT_MAC_CTL, reg);
203+
}
204+
185205
int mv88e6xxx_port_sync_link(struct mv88e6xxx_chip *chip, int port, unsigned int mode, bool isup)
186206
{
187207
const struct mv88e6xxx_ops *ops = chip->info->ops;

drivers/net/dsa/mv88e6xxx/port.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -511,6 +511,8 @@ int mv88e6390_port_set_rgmii_delay(struct mv88e6xxx_chip *chip, int port,
511511
phy_interface_t mode);
512512

513513
int mv88e6xxx_port_set_link(struct mv88e6xxx_chip *chip, int port, int link);
514+
int mv88e6xxx_port_set_force_flow_ctl(struct mv88e6xxx_chip *chip, int port,
515+
bool force, bool value);
514516

515517
int mv88e6xxx_port_sync_link(struct mv88e6xxx_chip *chip, int port, unsigned int mode, bool isup);
516518
int mv88e6185_port_sync_link(struct mv88e6xxx_chip *chip, int port, unsigned int mode, bool isup);

0 commit comments

Comments
 (0)