diff options
| author | Serge Semin <fancer.lancer@gmail.com> | 2023-08-14 23:31:16 +0300 |
|---|---|---|
| committer | Serge Semin <fancer.lancer@gmail.com> | 2026-08-13 20:38:18 +0300 |
| commit | cc67886881f55520147cbdf37b8cd122fbbfb084 (patch) | |
| tree | b37cfa5708eacaa0132046cecbed57837a5be6fc | |
| parent | df9d70712eb6b483c8d658b114addafccdd90192 (diff) | |
| download | linux-cc67886881f55520147cbdf37b8cd122fbbfb084.tar.gz linux-cc67886881f55520147cbdf37b8cd122fbbfb084.zip | |
net: phy: marvell-88x2222: Read latched flags twice
Prepare the driver to adding the interrupts support by making sure that
the actual status is handled during the network link state machine work.
Currently it concerns the link status flags in various PHY MMD registers.
They are latched-low so the respective CSRs need to be read twice to get
the actual flag state at the moment of the event handling.
Note there are other latched flags can be discovered in the Marvell
88x2222 registers. For instance AN Page Received status or 1GBase-X Remote
fault status. Since the semantic of the respective events handling may
differ from the link up/down handling procedure, the
mv2222_read_mmd_latched() function is defined to accept an additional
argument forcing the registers double read if it's required by the caller.
Signed-off-by: Serge Semin <fancer.lancer@gmail.com>
| -rw-r--r-- | drivers/net/phy/marvell-88x2222.c | 31 |
1 files changed, 27 insertions, 4 deletions
diff --git a/drivers/net/phy/marvell-88x2222.c b/drivers/net/phy/marvell-88x2222.c index 441626312142..9d21aa3e3d67 100644 --- a/drivers/net/phy/marvell-88x2222.c +++ b/drivers/net/phy/marvell-88x2222.c @@ -347,12 +347,32 @@ static int mv2222_config_aneg(struct phy_device *phydev) return mv2222_enable_aneg(phydev); } +/* The link state and some other fields in the status registers are latched + * low/high so that the momentary events could be detected. Do not double-read + * the status in polling mode to detect such a short flag changes except when + * it's forced to be required (i.e. when the link was already down). + */ +static int mv2222_read_mmd_latched(struct phy_device *phydev, int devad, u32 reg, + bool force) +{ + int ret; + + if (!phy_polling_mode(phydev) || force) { + ret = phy_read_mmd(phydev, devad, reg); + if (ret < 0) + return ret; + } + + return phy_read_mmd(phydev, devad, reg); +} + static int mv2222_aneg_done(struct phy_device *phydev) { int ret; if (mv2222_is_10g_capable(phydev)) { - ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_STAT1); + ret = mv2222_read_mmd_latched(phydev, MDIO_MMD_PCS, MDIO_STAT1, + !phydev->link); if (ret < 0) return ret; @@ -373,7 +393,8 @@ static int mv2222_read_status_10g(struct phy_device *phydev) static int timeout; int val, link = 0; - val = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_STAT1); + val = mv2222_read_mmd_latched(phydev, MDIO_MMD_PCS, MDIO_STAT1, + !phydev->link); if (val < 0) return val; @@ -409,7 +430,8 @@ static int mv2222_read_status_1g(struct phy_device *phydev) static int timeout; int val, link = 0; - val = phy_read_mmd(phydev, MDIO_MMD_PCS, MV_1GBX_STAT); + val = mv2222_read_mmd_latched(phydev, MDIO_MMD_PCS, MV_1GBX_STAT, + !phydev->link); if (val < 0) return val; @@ -471,7 +493,8 @@ static bool mv2222_iface_is_operational(struct phy_device *phydev) return false; } - val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, reg); + val = mv2222_read_mmd_latched(phydev, MDIO_MMD_PHYXS, reg, + !phydev->link); if (val < 0 || !(val & MDIO_STAT1_LSTATUS)) return false; |
