]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
net: phy: micrel: Fix the KSZ9131 MDI-X status issue
authorRaju Lakkaraju <Raju.Lakkaraju@microchip.com>
Thu, 25 Jul 2024 07:11:25 +0000 (12:41 +0530)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 11 Aug 2024 10:57:53 +0000 (12:57 +0200)
[ Upstream commit 84383b5ef4cd21b4a67de92afdc05a03b5247db9 ]

The MDIX status is not accurately reflecting the current state after the link
partner has manually altered its MDIX configuration while operating in forced
mode.

Access information about Auto mdix completion and pair selection from the
KSZ9131's Auto/MDI/MDI-X status register

Fixes: b64e6a8794d9 ("net: phy: micrel: Add PHY Auto/MDI/MDI-X set driver for KSZ9131")
Signed-off-by: Raju Lakkaraju <Raju.Lakkaraju@microchip.com>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Link: https://patch.msgid.link/20240725071125.13960-1-Raju.Lakkaraju@microchip.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
drivers/net/phy/micrel.c

index ebafedde0ab745467a130225a1620ac47d0cd7df..0803b6e83cf74c22d7dd340773e4652c5886f514 100644 (file)
@@ -1389,6 +1389,8 @@ static int ksz9131_config_init(struct phy_device *phydev)
        const struct device *dev_walker;
        int ret;
 
+       phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
+
        dev_walker = &phydev->mdio.dev;
        do {
                of_node = dev_walker->of_node;
@@ -1438,28 +1440,30 @@ static int ksz9131_config_init(struct phy_device *phydev)
 #define MII_KSZ9131_AUTO_MDIX          0x1C
 #define MII_KSZ9131_AUTO_MDI_SET       BIT(7)
 #define MII_KSZ9131_AUTO_MDIX_SWAP_OFF BIT(6)
+#define MII_KSZ9131_DIG_AXAN_STS       0x14
+#define MII_KSZ9131_DIG_AXAN_STS_LINK_DET      BIT(14)
+#define MII_KSZ9131_DIG_AXAN_STS_A_SELECT      BIT(12)
 
 static int ksz9131_mdix_update(struct phy_device *phydev)
 {
        int ret;
 
-       ret = phy_read(phydev, MII_KSZ9131_AUTO_MDIX);
-       if (ret < 0)
-               return ret;
-
-       if (ret & MII_KSZ9131_AUTO_MDIX_SWAP_OFF) {
-               if (ret & MII_KSZ9131_AUTO_MDI_SET)
-                       phydev->mdix_ctrl = ETH_TP_MDI;
-               else
-                       phydev->mdix_ctrl = ETH_TP_MDI_X;
+       if (phydev->mdix_ctrl != ETH_TP_MDI_AUTO) {
+               phydev->mdix = phydev->mdix_ctrl;
        } else {
-               phydev->mdix_ctrl = ETH_TP_MDI_AUTO;
-       }
+               ret = phy_read(phydev, MII_KSZ9131_DIG_AXAN_STS);
+               if (ret < 0)
+                       return ret;
 
-       if (ret & MII_KSZ9131_AUTO_MDI_SET)
-               phydev->mdix = ETH_TP_MDI;
-       else
-               phydev->mdix = ETH_TP_MDI_X;
+               if (ret & MII_KSZ9131_DIG_AXAN_STS_LINK_DET) {
+                       if (ret & MII_KSZ9131_DIG_AXAN_STS_A_SELECT)
+                               phydev->mdix = ETH_TP_MDI;
+                       else
+                               phydev->mdix = ETH_TP_MDI_X;
+               } else {
+                       phydev->mdix = ETH_TP_MDI_INVALID;
+               }
+       }
 
        return 0;
 }