Commit 47e96930 authored by Marek Behún's avatar Marek Behún Committed by Jakub Kicinski

net: dsa: mv88e6xxx: use BMSR_ANEGCOMPLETE bit for filling an_complete

Commit ede359d8 ("net: dsa: mv88e6xxx: Link in pcs_get_state() if AN
is bypassed") added the ability to link if AN was bypassed, and added
filling of state->an_complete field, but set it to true if AN was
enabled in BMCR, not when AN was reported complete in BMSR.

This was done because for some reason, when I wanted to use BMSR value
to infer an_complete, I was looking at BMSR_ANEGCAPABLE bit (which was
always 1), instead of BMSR_ANEGCOMPLETE bit.

Use BMSR_ANEGCOMPLETE for filling state->an_complete.

Fixes: ede359d8 ("net: dsa: mv88e6xxx: Link in pcs_get_state() if AN is bypassed")
Signed-off-by: default avatarMarek Behún <kabel@kernel.org>
Signed-off-by: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 11ec18b1
...@@ -50,22 +50,17 @@ static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip, ...@@ -50,22 +50,17 @@ static int mv88e6390_serdes_write(struct mv88e6xxx_chip *chip,
} }
static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, static int mv88e6xxx_serdes_pcs_get_state(struct mv88e6xxx_chip *chip,
u16 ctrl, u16 status, u16 lpa, u16 bmsr, u16 lpa, u16 status,
struct phylink_link_state *state) struct phylink_link_state *state)
{ {
state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK); state->link = !!(status & MV88E6390_SGMII_PHY_STATUS_LINK);
state->an_complete = !!(bmsr & BMSR_ANEGCOMPLETE);
if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) { if (status & MV88E6390_SGMII_PHY_STATUS_SPD_DPL_VALID) {
/* The Spped and Duplex Resolved register is 1 if AN is enabled /* The Spped and Duplex Resolved register is 1 if AN is enabled
* and complete, or if AN is disabled. So with disabled AN we * and complete, or if AN is disabled. So with disabled AN we
* still get here on link up. But we want to set an_complete * still get here on link up.
* only if AN was enabled, thus we look at BMCR_ANENABLE.
* (According to 802.3-2008 section 22.2.4.2.10, we should be
* able to get this same value from BMSR_ANEGCAPABLE, but tests
* show that these Marvell PHYs don't conform to this part of
* the specificaion - BMSR_ANEGCAPABLE is simply always 1.)
*/ */
state->an_complete = !!(ctrl & BMCR_ANENABLE);
state->duplex = status & state->duplex = status &
MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ? MV88E6390_SGMII_PHY_STATUS_DUPLEX_FULL ?
DUPLEX_FULL : DUPLEX_HALF; DUPLEX_FULL : DUPLEX_HALF;
...@@ -191,12 +186,12 @@ int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, ...@@ -191,12 +186,12 @@ int mv88e6352_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
int lane, struct phylink_link_state *state) int lane, struct phylink_link_state *state)
{ {
u16 lpa, status, ctrl; u16 bmsr, lpa, status;
int err; int err;
err = mv88e6352_serdes_read(chip, MII_BMCR, &ctrl); err = mv88e6352_serdes_read(chip, MII_BMSR, &bmsr);
if (err) { if (err) {
dev_err(chip->dev, "can't read Serdes PHY control: %d\n", err); dev_err(chip->dev, "can't read Serdes BMSR: %d\n", err);
return err; return err;
} }
...@@ -212,7 +207,7 @@ int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port, ...@@ -212,7 +207,7 @@ int mv88e6352_serdes_pcs_get_state(struct mv88e6xxx_chip *chip, int port,
return err; return err;
} }
return mv88e6xxx_serdes_pcs_get_state(chip, ctrl, status, lpa, state); return mv88e6xxx_serdes_pcs_get_state(chip, bmsr, lpa, status, state);
} }
int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port, int mv88e6352_serdes_pcs_an_restart(struct mv88e6xxx_chip *chip, int port,
...@@ -918,13 +913,13 @@ int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port, ...@@ -918,13 +913,13 @@ int mv88e6390_serdes_pcs_config(struct mv88e6xxx_chip *chip, int port,
static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip, static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip,
int port, int lane, struct phylink_link_state *state) int port, int lane, struct phylink_link_state *state)
{ {
u16 lpa, status, ctrl; u16 bmsr, lpa, status;
int err; int err;
err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS, err = mv88e6390_serdes_read(chip, lane, MDIO_MMD_PHYXS,
MV88E6390_SGMII_BMCR, &ctrl); MV88E6390_SGMII_BMSR, &bmsr);
if (err) { if (err) {
dev_err(chip->dev, "can't read Serdes PHY control: %d\n", err); dev_err(chip->dev, "can't read Serdes PHY BMSR: %d\n", err);
return err; return err;
} }
...@@ -942,7 +937,7 @@ static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip, ...@@ -942,7 +937,7 @@ static int mv88e6390_serdes_pcs_get_state_sgmii(struct mv88e6xxx_chip *chip,
return err; return err;
} }
return mv88e6xxx_serdes_pcs_get_state(chip, ctrl, status, lpa, state); return mv88e6xxx_serdes_pcs_get_state(chip, bmsr, lpa, status, state);
} }
static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip, static int mv88e6390_serdes_pcs_get_state_10g(struct mv88e6xxx_chip *chip,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment