From: Maarten Zanders maarten.zanders@mind.be
stable inclusion from stable-5.10.75 commit 3e287365216330ba5041f7fa1369460ad716f422 bugzilla: 182987 https://gitee.com/openeuler/kernel/issues/I4I3MP
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit 4a3e0aeddf091f00974b02627c157843ce382a24 upstream.
mv88e6xxx_port_ppu_updates() interpretes data in the PORT_STS register incorrectly for internal ports (ie no PPU). In these cases, the PHY_DETECT bit indicates link status. This results in forcing the MAC state whenever the PHY link goes down which is not intended. As a side effect, LED's configured to show link status stay lit even though the physical link is down.
Add a check in mac_link_down and mac_link_up to see if it concerns an external port and only then, look at PPU status.
Fixes: 5d5b231da7ac (net: dsa: mv88e6xxx: use PHY_DETECT in mac_link_up/mac_link_down) Reported-by: Maarten Zanders m.zanders@televic.com Reviewed-by: Maxime Chevallier maxime.chevallier@bootlin.com Signed-off-by: Maarten Zanders maarten.zanders@mind.be Signed-off-by: David S. Miller davem@davemloft.net Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org
Signed-off-by: Chen Jun chenjun102@huawei.com Acked-by: Weilong Chen chenweilong@huawei.com
Signed-off-by: Chen Jun chenjun102@huawei.com --- drivers/net/dsa/mv88e6xxx/chip.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 18388ea5ebd9..afc5500ef8ed 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -726,7 +726,11 @@ static void mv88e6xxx_mac_link_down(struct dsa_switch *ds, int port, ops = chip->info->ops;
mv88e6xxx_reg_lock(chip); - if ((!mv88e6xxx_port_ppu_updates(chip, port) || + /* Internal PHYs propagate their configuration directly to the MAC. + * External PHYs depend on whether the PPU is enabled for this port. + */ + if (((!mv88e6xxx_phy_is_internal(ds, port) && + !mv88e6xxx_port_ppu_updates(chip, port)) || mode == MLO_AN_FIXED) && ops->port_set_link) err = ops->port_set_link(chip, port, LINK_FORCED_DOWN); mv88e6xxx_reg_unlock(chip); @@ -749,7 +753,12 @@ static void mv88e6xxx_mac_link_up(struct dsa_switch *ds, int port, ops = chip->info->ops;
mv88e6xxx_reg_lock(chip); - if (!mv88e6xxx_port_ppu_updates(chip, port) || mode == MLO_AN_FIXED) { + /* Internal PHYs propagate their configuration directly to the MAC. + * External PHYs depend on whether the PPU is enabled for this port. + */ + if ((!mv88e6xxx_phy_is_internal(ds, port) && + !mv88e6xxx_port_ppu_updates(chip, port)) || + mode == MLO_AN_FIXED) { /* FIXME: for an automedia port, should we force the link * down here - what if the link comes up due to "other" media * while we're bringing the port up, how is the exclusivity