summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--drivers/net/phy/aquantia/aquantia_main.c19
1 files changed, 16 insertions, 3 deletions
diff --git a/drivers/net/phy/aquantia/aquantia_main.c b/drivers/net/phy/aquantia/aquantia_main.c
index 6e9dd9cee1fa..4fe757cd7dc7 100644
--- a/drivers/net/phy/aquantia/aquantia_main.c
+++ b/drivers/net/phy/aquantia/aquantia_main.c
@@ -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_AN_VEND_PROV 0xc400
@@ -348,9 +349,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:
@@ -377,7 +388,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;
}