net: phy: aquantia: poll status register
The system interface connection status register is not immediately correct upon line side link up. This results in the status being read as OFF and then transitioning to the correct host side link mode with a short delay. This causes the phylink framework passing the OFF status down to all MAC config drivers, resulting in the host side link being misconfigured, which in turn can lead to link flapping or complete packet loss in some cases. Mitigate this by periodically polling the register until it not showing the OFF state. This will be done every 1ms for 10ms, using the same poll/timeout as the processor intensive operation reads. If the phy is still expressing the OFF state after the timeout, then set the link to false and pass the NA interface mode onto the phylink framework. http://nvbugs/4980644 Signed-off-by: Aryan Srivastava <aryan.srivastava@alliedtelesis.co.nz> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Link: https://patch.msgid.link/20241010004935.1774601-1-aryan.srivastava@alliedtelesis.co.nz Signed-off-by: Jakub Kicinski <kuba@kernel.org> (cherry picked from commit 7e5b547cac7a56515b2838b496923e52ec4eeddd) Signed-off-by: Revanth Kumar Uppala <ruppala@nvidia.com> Reviewed-by: Jon Hunter <jonathanh@nvidia.com> Signed-off-by: Vishwaroop A <va@nvidia.com> Acked-by: Noah Wager <noah.wager@canonical.com> Acked-by: Jacob Martin <jacob.martin@canonical.com> Signed-off-by: Noah Wager <noah.wager@canonical.com>
This commit is contained in:
committed by
Noah Wager
parent
888939cc5f
commit
59cf0dd597
@@ -42,6 +42,7 @@
|
||||
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_XAUI 4
|
||||
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_SGMII 6
|
||||
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_RXAUI 7
|
||||
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OFF 9
|
||||
#define MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII 10
|
||||
#define MDIO_PHYXS_VEND_IF_STATUS_TX_READY BIT(12)
|
||||
|
||||
@@ -576,9 +577,19 @@ static int aqr107_read_status(struct phy_device *phydev)
|
||||
if (!phydev->link || phydev->autoneg == AUTONEG_DISABLE)
|
||||
return 0;
|
||||
|
||||
val = phy_read_mmd(phydev, MDIO_MMD_PHYXS, MDIO_PHYXS_VEND_IF_STATUS);
|
||||
if (val < 0)
|
||||
return val;
|
||||
/**
|
||||
* The status register is not immediately correct on line side link up.
|
||||
* Poll periodically until it reflects the correct ON state.
|
||||
* Only return fail for read error, timeout defaults to OFF state.
|
||||
*/
|
||||
ret = phy_read_mmd_poll_timeout(phydev, MDIO_MMD_PHYXS,
|
||||
MDIO_PHYXS_VEND_IF_STATUS, val,
|
||||
(FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val) !=
|
||||
MDIO_PHYXS_VEND_IF_STATUS_TYPE_OFF),
|
||||
AQR107_OP_IN_PROG_SLEEP,
|
||||
AQR107_OP_IN_PROG_TIMEOUT, false);
|
||||
if (ret && ret != -ETIMEDOUT)
|
||||
return ret;
|
||||
|
||||
switch (FIELD_GET(MDIO_PHYXS_VEND_IF_STATUS_TYPE_MASK, val)) {
|
||||
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_KR:
|
||||
@@ -605,7 +616,9 @@ static int aqr107_read_status(struct phy_device *phydev)
|
||||
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OCSGMII:
|
||||
phydev->interface = PHY_INTERFACE_MODE_2500BASEX;
|
||||
break;
|
||||
case MDIO_PHYXS_VEND_IF_STATUS_TYPE_OFF:
|
||||
default:
|
||||
phydev->link = false;
|
||||
phydev->interface = PHY_INTERFACE_MODE_NA;
|
||||
break;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user