net: dsa: mv88e6xxx: support in-band signalling on SGMII ports with external PHYs
If an external PHY is connected via SGMII and uses in-band signalling then the auto-negotiated values aren't propagated to the port, resulting in a broken link. See discussion in [0]. This patch adds this propagation. We need to call mv88e6xxx_port_setup_mac(), therefore export it from chip.c. Successfully tested on a ZII DTU with 88E6390 switch and an Aquantia AQCS109 PHY connected via SGMII to port 9. [0] https://marc.info/?t=155130287200001&r=1&w=2 Signed-off-by: Heiner Kallweit <hkallweit1@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:

committed by
David S. Miller

orang tua
80f61f19e5
melakukan
72d8b4fdbf
@@ -510,21 +510,48 @@ static void mv88e6390_serdes_irq_link_sgmii(struct mv88e6xxx_chip *chip,
|
||||
int port, int lane)
|
||||
{
|
||||
struct dsa_switch *ds = chip->ds;
|
||||
int duplex = DUPLEX_UNKNOWN;
|
||||
int speed = SPEED_UNKNOWN;
|
||||
int link, err;
|
||||
u16 status;
|
||||
bool up;
|
||||
|
||||
mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
|
||||
MV88E6390_SGMII_STATUS, &status);
|
||||
err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
|
||||
MV88E6390_SGMII_PHY_STATUS, &status);
|
||||
if (err) {
|
||||
dev_err(chip->dev, "can't read SGMII PHY status: %d\n", err);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Status must be read twice in order to give the current link
|
||||
* status. Otherwise the change in link status since the last
|
||||
* read of the register is returned.
|
||||
*/
|
||||
mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
|
||||
MV88E6390_SGMII_STATUS, &status);
|
||||
up = status & MV88E6390_SGMII_STATUS_LINK;
|
||||
link = status & MV88E6390_SGMII_PHY_STATUS_LINK ?
|
||||
LINK_FORCED_UP : LINK_FORCED_DOWN;
|
||||
|
||||
dsa_port_phylink_mac_change(ds, port, up);
|
||||
if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) {
|
||||
duplex = status & MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?
|
||||
DUPLEX_FULL : DUPLEX_HALF;
|
||||
|
||||
switch (status & MV88E6390_SGMII_PHY_STATUS_SPEED_MASK) {
|
||||
case MV88E6390_SGMII_PHY_STATUS_SPEED_1000:
|
||||
speed = SPEED_1000;
|
||||
break;
|
||||
case MV88E6390_SGMII_PHY_STATUS_SPEED_100:
|
||||
speed = SPEED_100;
|
||||
break;
|
||||
case MV88E6390_SGMII_PHY_STATUS_SPEED_10:
|
||||
speed = SPEED_10;
|
||||
break;
|
||||
default:
|
||||
dev_err(chip->dev, "invalid PHY speed\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
err = mv88e6xxx_port_setup_mac(chip, port, link, speed, duplex,
|
||||
PAUSE_OFF, PHY_INTERFACE_MODE_NA);
|
||||
if (err)
|
||||
dev_err(chip->dev, "can't propagate PHY settings to MAC: %d\n",
|
||||
err);
|
||||
else
|
||||
dsa_port_phylink_mac_change(ds, port, link == LINK_FORCED_UP);
|
||||
}
|
||||
|
||||
static int mv88e6390_serdes_irq_enable_sgmii(struct mv88e6xxx_chip *chip,
|
||||
|
Reference in New Issue
Block a user