]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
amd-xgbe: add ethtool phy loopback selftest
authorRaju Rangoju <Raju.Rangoju@amd.com>
Fri, 31 Oct 2025 11:15:55 +0000 (16:45 +0530)
committerPaolo Abeni <pabeni@redhat.com>
Thu, 6 Nov 2025 12:38:11 +0000 (13:38 +0100)
Add support for PHY loopback testing via ethtool self-test.
The test uses phy_loopback() which enables PHY-level loopback
through the PHY driver's set_loopback callback if provided,
else uses the genphy_loopback().

Signed-off-by: Raju Rangoju <Raju.Rangoju@amd.com>
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Link: https://patch.msgid.link/20251031111555.774425-3-Raju.Rangoju@amd.com
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/amd/xgbe/xgbe-selftest.c

index 8a3a6279584d38287d24970373f54399a1404dd7..23b9d568a861e361b6a01e9d0c2c0306d1ebd581 100644 (file)
@@ -19,6 +19,7 @@
 
 #define XGBE_LOOPBACK_NONE     0
 #define XGBE_LOOPBACK_MAC      1
+#define XGBE_LOOPBACK_PHY      2
 
 struct xgbe_test {
        char name[ETH_GSTRING_LEN];
@@ -151,11 +152,36 @@ static int xgbe_test_mac_loopback(struct xgbe_prv_data *pdata)
        return __xgbe_test_loopback(pdata, &attr);
 }
 
+static int xgbe_test_phy_loopback(struct xgbe_prv_data *pdata)
+{
+       struct net_packet_attrs attr = {};
+       int ret;
+
+       if (!pdata->netdev->phydev) {
+               netdev_err(pdata->netdev, "phydev not found: cannot start PHY loopback test\n");
+               return -EOPNOTSUPP;
+       }
+
+       ret = phy_loopback(pdata->netdev->phydev, true, 0);
+       if (ret)
+               return ret;
+
+       attr.dst = pdata->netdev->dev_addr;
+       ret = __xgbe_test_loopback(pdata, &attr);
+
+       phy_loopback(pdata->netdev->phydev, false, 0);
+       return ret;
+}
+
 static const struct xgbe_test xgbe_selftests[] = {
        {
                .name = "MAC Loopback   ",
                .lb = XGBE_LOOPBACK_MAC,
                .fn = xgbe_test_mac_loopback,
+       }, {
+               .name = "PHY Loopback   ",
+               .lb = XGBE_LOOPBACK_NONE,
+               .fn = xgbe_test_phy_loopback,
        },
 };
 
@@ -187,6 +213,13 @@ void xgbe_selftest_run(struct net_device *dev,
                ret = 0;
 
                switch (xgbe_selftests[i].lb) {
+               case XGBE_LOOPBACK_PHY:
+                       ret = -EOPNOTSUPP;
+                       if (dev->phydev)
+                               ret = phy_loopback(dev->phydev, true, 0);
+                       if (!ret)
+                               break;
+                       fallthrough;
                case XGBE_LOOPBACK_MAC:
                        ret = xgbe_enable_mac_loopback(pdata);
                        break;
@@ -213,6 +246,13 @@ void xgbe_selftest_run(struct net_device *dev,
                buf[i] = ret;
 
                switch (xgbe_selftests[i].lb) {
+               case XGBE_LOOPBACK_PHY:
+                       ret = -EOPNOTSUPP;
+                       if (dev->phydev)
+                               ret = phy_loopback(dev->phydev, false, 0);
+                       if (!ret)
+                               break;
+                       fallthrough;
                case XGBE_LOOPBACK_MAC:
                        xgbe_disable_mac_loopback(pdata);
                        break;