netdev.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH net-next v6 0/7] Support loopback mode speed selection
@ 2025-02-09 19:08 Gerhard Engleder
  2025-02-09 19:08 ` [PATCH net-next v6 1/7] net: phy: Allow loopback speed selection for PHY drivers Gerhard Engleder
                   ` (6 more replies)
  0 siblings, 7 replies; 21+ messages in thread
From: Gerhard Engleder @ 2025-02-09 19:08 UTC (permalink / raw)
  To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni
  Cc: netdev, Gerhard Engleder

Previously to commit 6ff3cddc365b ("net: phylib: do not disable autoneg
for fixed speeds >= 1G") it was possible to select the speed of the
loopback mode by configuring a fixed speed before enabling the loopback
mode. Now autoneg is always enabled for >= 1G and a fixed speed of >= 1G
requires successful autoneg. Thus, the speed of the loopback mode depends
on the link partner for >= 1G. There is no technical reason to depend on
the link partner for loopback mode. With this behavior the loopback mode
is less useful for testing.

Allow PHYs to support optional speed selection for the loopback mode.
This support is implemented for the generic loopback support and for PHY
drivers, which obviously support speed selection for loopback mode.
Additionally, loopback support according to the data sheet is added to
the KSZ9031 PHY.

Extend phy_loopback() to signal link up and down if speed changes,
because a new link speed requires link up signalling.

Use this loopback speed selection in the tsnep driver to select the
loopback mode speed depending the previously active speed. User space
tests with 100 Mbps and 1 Gbps loopback are possible again.

v6:
- add return value documentation to phy_loopback() (Jakub Kicinski)

v5:
- use phy_write() instead of phy_modify() (Russel King)
- add missing inline for export dummies (kernel test robot)

v4:
- resend without changed to RFC v3

RFC v3:
- align set_loopback() of Marvell to Micrel (Andrew Lunn)
- transmit packets in loopback selftests (Andrew Lunn)
- don't flush PHY statemachine in phy_loopback()
- remove setting of carrier on and link mode after phy_loopback() in tsnep

v2:
- signal link up to keep MAC and PHY in sync about speed (Andrew Lunn)

Gerhard Engleder (7):
  net: phy: Allow loopback speed selection for PHY drivers
  net: phy: Support speed selection for PHY loopback
  net: phy: micrel: Add loopback support
  net: phy: marvell: Align set_loopback() implementation
  tsnep: Select speed for loopback
  net: selftests: Export net_test_phy_loopback_*
  tsnep: Add PHY loopback selftests

 drivers/net/ethernet/engleder/Kconfig         |   1 +
 drivers/net/ethernet/engleder/tsnep_main.c    |  21 ++-
 .../net/ethernet/engleder/tsnep_selftests.c   | 153 +++++++++++++++++-
 .../net/ethernet/hisilicon/hns/hns_ethtool.c  |   4 +-
 .../hisilicon/hns3/hns3pf/hclge_main.c        |   4 +-
 .../hisilicon/hns3/hns3pf/hclge_mdio.c        |   2 +-
 .../stmicro/stmmac/stmmac_selftests.c         |   8 +-
 drivers/net/phy/adin1100.c                    |   5 +-
 drivers/net/phy/dp83867.c                     |   5 +-
 drivers/net/phy/marvell.c                     |  68 ++++----
 drivers/net/phy/micrel.c                      |  28 ++++
 drivers/net/phy/mxl-gpy.c                     |  11 +-
 drivers/net/phy/phy-c45.c                     |   5 +-
 drivers/net/phy/phy.c                         |  78 +++++++++
 drivers/net/phy/phy_device.c                  |  43 +----
 drivers/net/phy/xilinx_gmii2rgmii.c           |   7 +-
 include/linux/phy.h                           |  18 ++-
 include/net/selftests.h                       |  19 +++
 net/core/selftests.c                          |  13 +-
 19 files changed, 379 insertions(+), 114 deletions(-)

-- 
2.39.5


^ permalink raw reply	[flat|nested] 21+ messages in thread

* [PATCH net-next v6 1/7] net: phy: Allow loopback speed selection for PHY drivers
  2025-02-09 19:08 [PATCH net-next v6 0/7] Support loopback mode speed selection Gerhard Engleder
@ 2025-02-09 19:08 ` Gerhard Engleder
  2025-02-12  1:53   ` Andrew Lunn
  2025-02-09 19:08 ` [PATCH net-next v6 2/7] net: phy: Support speed selection for PHY loopback Gerhard Engleder
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Gerhard Engleder @ 2025-02-09 19:08 UTC (permalink / raw)
  To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni
  Cc: netdev, Gerhard Engleder

PHY drivers support loopback mode, but it is not possible to select the
speed of the loopback mode. The speed is chosen by the set_loopback()
operation of the PHY driver. Same is valid for genphy_loopback().

There are PHYs that support loopback with different speeds. Extend
set_loopback() to make loopback speed selection possible.

Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>
---
 drivers/net/phy/adin1100.c          |  5 ++++-
 drivers/net/phy/dp83867.c           |  5 ++++-
 drivers/net/phy/marvell.c           |  8 +++++++-
 drivers/net/phy/mxl-gpy.c           | 11 +++++++----
 drivers/net/phy/phy-c45.c           |  5 ++++-
 drivers/net/phy/phy_device.c        | 12 +++++++++---
 drivers/net/phy/xilinx_gmii2rgmii.c |  7 ++++---
 include/linux/phy.h                 | 16 ++++++++++++----
 8 files changed, 51 insertions(+), 18 deletions(-)

diff --git a/drivers/net/phy/adin1100.c b/drivers/net/phy/adin1100.c
index 6bb469429b9d..bd7a47a903ac 100644
--- a/drivers/net/phy/adin1100.c
+++ b/drivers/net/phy/adin1100.c
@@ -215,8 +215,11 @@ static int adin_resume(struct phy_device *phydev)
 	return adin_set_powerdown_mode(phydev, false);
 }
 
-static int adin_set_loopback(struct phy_device *phydev, bool enable)
+static int adin_set_loopback(struct phy_device *phydev, bool enable, int speed)
 {
+	if (enable && speed)
+		return -EOPNOTSUPP;
+
 	if (enable)
 		return phy_set_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_10T1L_CTRL,
 					BMCR_LOOPBACK);
diff --git a/drivers/net/phy/dp83867.c b/drivers/net/phy/dp83867.c
index c1451df430ac..063266cafe9c 100644
--- a/drivers/net/phy/dp83867.c
+++ b/drivers/net/phy/dp83867.c
@@ -1009,8 +1009,11 @@ static void dp83867_link_change_notify(struct phy_device *phydev)
 	}
 }
 
-static int dp83867_loopback(struct phy_device *phydev, bool enable)
+static int dp83867_loopback(struct phy_device *phydev, bool enable, int speed)
 {
+	if (enable && speed)
+		return -EOPNOTSUPP;
+
 	return phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK,
 			  enable ? BMCR_LOOPBACK : 0);
 }
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 44e1927de499..4ed7ec1be74f 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -2131,13 +2131,19 @@ static void marvell_get_stats_simple(struct phy_device *phydev,
 		data[i] = marvell_get_stat_simple(phydev, i);
 }
 
-static int m88e1510_loopback(struct phy_device *phydev, bool enable)
+static int m88e1510_loopback(struct phy_device *phydev, bool enable, int speed)
 {
 	int err;
 
 	if (enable) {
 		u16 bmcr_ctl, mscr2_ctl = 0;
 
+		if (speed == SPEED_10 || speed == SPEED_100 ||
+		    speed == SPEED_1000)
+			phydev->speed = speed;
+		else if (speed)
+			return -EINVAL;
+
 		bmcr_ctl = mii_bmcr_encode_fixed(phydev->speed, phydev->duplex);
 
 		err = phy_write(phydev, MII_BMCR, bmcr_ctl);
diff --git a/drivers/net/phy/mxl-gpy.c b/drivers/net/phy/mxl-gpy.c
index 94d9cb727121..a6cca8d43253 100644
--- a/drivers/net/phy/mxl-gpy.c
+++ b/drivers/net/phy/mxl-gpy.c
@@ -813,7 +813,7 @@ static void gpy_get_wol(struct phy_device *phydev,
 	wol->wolopts = priv->wolopts;
 }
 
-static int gpy_loopback(struct phy_device *phydev, bool enable)
+static int gpy_loopback(struct phy_device *phydev, bool enable, int speed)
 {
 	struct gpy_priv *priv = phydev->priv;
 	u16 set = 0;
@@ -822,6 +822,9 @@ static int gpy_loopback(struct phy_device *phydev, bool enable)
 	if (enable) {
 		u64 now = get_jiffies_64();
 
+		if (speed)
+			return -EOPNOTSUPP;
+
 		/* wait until 3 seconds from last disable */
 		if (time_before64(now, priv->lb_dis_to))
 			msleep(jiffies64_to_msecs(priv->lb_dis_to - now));
@@ -845,15 +848,15 @@ static int gpy_loopback(struct phy_device *phydev, bool enable)
 	return 0;
 }
 
-static int gpy115_loopback(struct phy_device *phydev, bool enable)
+static int gpy115_loopback(struct phy_device *phydev, bool enable, int speed)
 {
 	struct gpy_priv *priv = phydev->priv;
 
 	if (enable)
-		return gpy_loopback(phydev, enable);
+		return gpy_loopback(phydev, enable, speed);
 
 	if (priv->fw_minor > 0x76)
-		return gpy_loopback(phydev, 0);
+		return gpy_loopback(phydev, 0, 0);
 
 	return genphy_soft_reset(phydev);
 }
diff --git a/drivers/net/phy/phy-c45.c b/drivers/net/phy/phy-c45.c
index 0dac08e85304..84c24e8847c3 100644
--- a/drivers/net/phy/phy-c45.c
+++ b/drivers/net/phy/phy-c45.c
@@ -1230,8 +1230,11 @@ int gen10g_config_aneg(struct phy_device *phydev)
 }
 EXPORT_SYMBOL_GPL(gen10g_config_aneg);
 
-int genphy_c45_loopback(struct phy_device *phydev, bool enable)
+int genphy_c45_loopback(struct phy_device *phydev, bool enable, int speed)
 {
+	if (enable && speed)
+		return -EOPNOTSUPP;
+
 	return phy_modify_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1,
 			      MDIO_PCS_CTRL1_LOOPBACK,
 			      enable ? MDIO_PCS_CTRL1_LOOPBACK : 0);
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 46713d27412b..15c797580070 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -2072,9 +2072,9 @@ int phy_loopback(struct phy_device *phydev, bool enable)
 	}
 
 	if (phydev->drv->set_loopback)
-		ret = phydev->drv->set_loopback(phydev, enable);
+		ret = phydev->drv->set_loopback(phydev, enable, 0);
 	else
-		ret = genphy_loopback(phydev, enable);
+		ret = genphy_loopback(phydev, enable, 0);
 
 	if (ret)
 		goto out;
@@ -2843,12 +2843,18 @@ int genphy_resume(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(genphy_resume);
 
-int genphy_loopback(struct phy_device *phydev, bool enable)
+int genphy_loopback(struct phy_device *phydev, bool enable, int speed)
 {
 	if (enable) {
 		u16 ctl = BMCR_LOOPBACK;
 		int ret, val;
 
+		if (speed == SPEED_10 || speed == SPEED_100 ||
+		    speed == SPEED_1000)
+			phydev->speed = speed;
+		else if (speed)
+			return -EINVAL;
+
 		ctl |= mii_bmcr_encode_fixed(phydev->speed, phydev->duplex);
 
 		phy_modify(phydev, MII_BMCR, ~0, ctl);
diff --git a/drivers/net/phy/xilinx_gmii2rgmii.c b/drivers/net/phy/xilinx_gmii2rgmii.c
index 7c51daecf18e..2024d8ef36d9 100644
--- a/drivers/net/phy/xilinx_gmii2rgmii.c
+++ b/drivers/net/phy/xilinx_gmii2rgmii.c
@@ -64,15 +64,16 @@ static int xgmiitorgmii_read_status(struct phy_device *phydev)
 	return 0;
 }
 
-static int xgmiitorgmii_set_loopback(struct phy_device *phydev, bool enable)
+static int xgmiitorgmii_set_loopback(struct phy_device *phydev, bool enable,
+				     int speed)
 {
 	struct gmii2rgmii *priv = mdiodev_get_drvdata(&phydev->mdio);
 	int err;
 
 	if (priv->phy_drv->set_loopback)
-		err = priv->phy_drv->set_loopback(phydev, enable);
+		err = priv->phy_drv->set_loopback(phydev, enable, speed);
 	else
-		err = genphy_loopback(phydev, enable);
+		err = genphy_loopback(phydev, enable, speed);
 	if (err < 0)
 		return err;
 
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 19f076a71f94..4e84df2294d2 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1189,8 +1189,16 @@ struct phy_driver {
 	int (*set_tunable)(struct phy_device *dev,
 			    struct ethtool_tunable *tuna,
 			    const void *data);
-	/** @set_loopback: Set the loopback mood of the PHY */
-	int (*set_loopback)(struct phy_device *dev, bool enable);
+	/**
+	 * @set_loopback: Set the loopback mode of the PHY
+	 * enable selects if the loopback mode is enabled or disabled. If the
+	 * loopback mode is enabled, then the speed of the loopback mode can be
+	 * requested with the speed argument. If the speed argument is zero,
+	 * then any speed can be selected. If the speed argument is > 0, then
+	 * this speed shall be selected for the loopback mode or EOPNOTSUPP
+	 * shall be returned if speed selection is not supported.
+	 */
+	int (*set_loopback)(struct phy_device *dev, bool enable, int speed);
 	/** @get_sqi: Get the signal quality indication */
 	int (*get_sqi)(struct phy_device *dev);
 	/** @get_sqi_max: Get the maximum signal quality indication */
@@ -1993,7 +2001,7 @@ int genphy_read_status(struct phy_device *phydev);
 int genphy_read_master_slave(struct phy_device *phydev);
 int genphy_suspend(struct phy_device *phydev);
 int genphy_resume(struct phy_device *phydev);
-int genphy_loopback(struct phy_device *phydev, bool enable);
+int genphy_loopback(struct phy_device *phydev, bool enable, int speed);
 int genphy_soft_reset(struct phy_device *phydev);
 irqreturn_t genphy_handle_interrupt_no_ack(struct phy_device *phydev);
 
@@ -2035,7 +2043,7 @@ int genphy_c45_pma_baset1_read_master_slave(struct phy_device *phydev);
 int genphy_c45_read_status(struct phy_device *phydev);
 int genphy_c45_baset1_read_status(struct phy_device *phydev);
 int genphy_c45_config_aneg(struct phy_device *phydev);
-int genphy_c45_loopback(struct phy_device *phydev, bool enable);
+int genphy_c45_loopback(struct phy_device *phydev, bool enable, int speed);
 int genphy_c45_pma_resume(struct phy_device *phydev);
 int genphy_c45_pma_suspend(struct phy_device *phydev);
 int genphy_c45_fast_retrain(struct phy_device *phydev, bool enable);
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH net-next v6 2/7] net: phy: Support speed selection for PHY loopback
  2025-02-09 19:08 [PATCH net-next v6 0/7] Support loopback mode speed selection Gerhard Engleder
  2025-02-09 19:08 ` [PATCH net-next v6 1/7] net: phy: Allow loopback speed selection for PHY drivers Gerhard Engleder
@ 2025-02-09 19:08 ` Gerhard Engleder
  2025-02-12  1:48   ` Andrew Lunn
  2025-02-09 19:08 ` [PATCH net-next v6 3/7] net: phy: micrel: Add loopback support Gerhard Engleder
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Gerhard Engleder @ 2025-02-09 19:08 UTC (permalink / raw)
  To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni
  Cc: netdev, Gerhard Engleder

phy_loopback() leaves it to the PHY driver to select the speed of the
loopback mode. Thus, the speed of the loopback mode depends on the PHY
driver in use.

Add support for speed selection to phy_loopback() to enable loopback
with defined speeds. Ensure that link up is signaled if speed changes
as speed is not allowed to change during link up. Link down and up is
necessary for a new speed.

Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>
---
 drivers/net/ethernet/engleder/tsnep_main.c    |  2 +-
 .../net/ethernet/hisilicon/hns/hns_ethtool.c  |  4 +-
 .../hisilicon/hns3/hns3pf/hclge_main.c        |  4 +-
 .../hisilicon/hns3/hns3pf/hclge_mdio.c        |  2 +-
 .../stmicro/stmmac/stmmac_selftests.c         |  8 +-
 drivers/net/phy/phy.c                         | 78 +++++++++++++++++++
 drivers/net/phy/phy_device.c                  | 35 ---------
 include/linux/phy.h                           |  2 +-
 net/core/selftests.c                          |  4 +-
 9 files changed, 91 insertions(+), 48 deletions(-)

diff --git a/drivers/net/ethernet/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c
index 18df6a5cbfc6..a16b12137edb 100644
--- a/drivers/net/ethernet/engleder/tsnep_main.c
+++ b/drivers/net/ethernet/engleder/tsnep_main.c
@@ -230,7 +230,7 @@ static int tsnep_phy_loopback(struct tsnep_adapter *adapter, bool enable)
 {
 	int retval;
 
-	retval = phy_loopback(adapter->phydev, enable);
+	retval = phy_loopback(adapter->phydev, enable, 0);
 
 	/* PHY link state change is not signaled if loopback is enabled, it
 	 * would delay a working loopback anyway, let's ensure that loopback
diff --git a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
index 6c458f037262..60a586a951a0 100644
--- a/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
+++ b/drivers/net/ethernet/hisilicon/hns/hns_ethtool.c
@@ -266,9 +266,9 @@ static int hns_nic_config_phy_loopback(struct phy_device *phy_dev, u8 en)
 		if (err)
 			goto out;
 
-		err = phy_loopback(phy_dev, true);
+		err = phy_loopback(phy_dev, true, 0);
 	} else {
-		err = phy_loopback(phy_dev, false);
+		err = phy_loopback(phy_dev, false, 0);
 		if (err)
 			goto out;
 
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
index 3f17b3073e50..f8161d6eb152 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c
@@ -7875,7 +7875,7 @@ static int hclge_enable_phy_loopback(struct hclge_dev *hdev,
 	if (ret)
 		return ret;
 
-	return phy_loopback(phydev, true);
+	return phy_loopback(phydev, true, 0);
 }
 
 static int hclge_disable_phy_loopback(struct hclge_dev *hdev,
@@ -7883,7 +7883,7 @@ static int hclge_disable_phy_loopback(struct hclge_dev *hdev,
 {
 	int ret;
 
-	ret = phy_loopback(phydev, false);
+	ret = phy_loopback(phydev, false, 0);
 	if (ret)
 		return ret;
 
diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
index 80079657afeb..9a456ebf9b7c 100644
--- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
+++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c
@@ -258,7 +258,7 @@ void hclge_mac_start_phy(struct hclge_dev *hdev)
 	if (!phydev)
 		return;
 
-	phy_loopback(phydev, false);
+	phy_loopback(phydev, false, 0);
 
 	phy_start(phydev);
 }
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
index 3ca1c2a816ff..a01bc394d1ac 100644
--- a/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
+++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c
@@ -382,14 +382,14 @@ static int stmmac_test_phy_loopback(struct stmmac_priv *priv)
 	if (!priv->dev->phydev)
 		return -EOPNOTSUPP;
 
-	ret = phy_loopback(priv->dev->phydev, true);
+	ret = phy_loopback(priv->dev->phydev, true, 0);
 	if (ret)
 		return ret;
 
 	attr.dst = priv->dev->dev_addr;
 	ret = __stmmac_test_loopback(priv, &attr);
 
-	phy_loopback(priv->dev->phydev, false);
+	phy_loopback(priv->dev->phydev, false, 0);
 	return ret;
 }
 
@@ -1985,7 +1985,7 @@ void stmmac_selftest_run(struct net_device *dev,
 		case STMMAC_LOOPBACK_PHY:
 			ret = -EOPNOTSUPP;
 			if (dev->phydev)
-				ret = phy_loopback(dev->phydev, true);
+				ret = phy_loopback(dev->phydev, true, 0);
 			if (!ret)
 				break;
 			fallthrough;
@@ -2018,7 +2018,7 @@ void stmmac_selftest_run(struct net_device *dev,
 		case STMMAC_LOOPBACK_PHY:
 			ret = -EOPNOTSUPP;
 			if (dev->phydev)
-				ret = phy_loopback(dev->phydev, false);
+				ret = phy_loopback(dev->phydev, false, 0);
 			if (!ret)
 				break;
 			fallthrough;
diff --git a/drivers/net/phy/phy.c b/drivers/net/phy/phy.c
index d0c1718e2b16..f9d2999a6526 100644
--- a/drivers/net/phy/phy.c
+++ b/drivers/net/phy/phy.c
@@ -1703,6 +1703,84 @@ void phy_mac_interrupt(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(phy_mac_interrupt);
 
+/**
+ * phy_loopback - Configure loopback mode of PHY
+ * @phydev: target phy_device struct
+ * @enable: enable or disable loopback mode
+ * @speed: enable loopback mode with speed
+ *
+ * Configure loopback mode of PHY and signal link down and link up if speed is
+ * changing.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int phy_loopback(struct phy_device *phydev, bool enable, int speed)
+{
+	bool link_up = false;
+	int ret = 0;
+
+	if (!phydev->drv)
+		return -EIO;
+
+	mutex_lock(&phydev->lock);
+
+	if (enable && phydev->loopback_enabled) {
+		ret = -EBUSY;
+		goto out;
+	}
+
+	if (!enable && !phydev->loopback_enabled) {
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (enable) {
+		/*
+		 * Link up is signaled with a defined speed. If speed changes,
+		 * then first link down and after that link up needs to be
+		 * signaled.
+		 */
+		if (phydev->link && phydev->state == PHY_RUNNING) {
+			/* link is up and signaled */
+			if (speed && phydev->speed != speed) {
+				/* signal link down and up for new speed */
+				phydev->link = false;
+				phydev->state = PHY_NOLINK;
+				phy_link_down(phydev);
+
+				link_up = true;
+			}
+		} else {
+			/* link is not signaled */
+			if (speed) {
+				/* signal link up for new speed */
+				link_up = true;
+			}
+		}
+	}
+
+	if (phydev->drv->set_loopback)
+		ret = phydev->drv->set_loopback(phydev, enable, speed);
+	else
+		ret = genphy_loopback(phydev, enable, speed);
+
+	if (ret)
+		goto out;
+
+	if (link_up) {
+		phydev->link = true;
+		phydev->state = PHY_RUNNING;
+		phy_link_up(phydev);
+	}
+
+	phydev->loopback_enabled = enable;
+
+out:
+	mutex_unlock(&phydev->lock);
+	return ret;
+}
+EXPORT_SYMBOL(phy_loopback);
+
 /**
  * phy_eee_tx_clock_stop_capable() - indicate whether the MAC can stop tx clock
  * @phydev: target phy_device struct
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 15c797580070..139bdebcc6f9 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -2052,41 +2052,6 @@ int phy_resume(struct phy_device *phydev)
 }
 EXPORT_SYMBOL(phy_resume);
 
-int phy_loopback(struct phy_device *phydev, bool enable)
-{
-	int ret = 0;
-
-	if (!phydev->drv)
-		return -EIO;
-
-	mutex_lock(&phydev->lock);
-
-	if (enable && phydev->loopback_enabled) {
-		ret = -EBUSY;
-		goto out;
-	}
-
-	if (!enable && !phydev->loopback_enabled) {
-		ret = -EINVAL;
-		goto out;
-	}
-
-	if (phydev->drv->set_loopback)
-		ret = phydev->drv->set_loopback(phydev, enable, 0);
-	else
-		ret = genphy_loopback(phydev, enable, 0);
-
-	if (ret)
-		goto out;
-
-	phydev->loopback_enabled = enable;
-
-out:
-	mutex_unlock(&phydev->lock);
-	return ret;
-}
-EXPORT_SYMBOL(phy_loopback);
-
 /**
  * phy_reset_after_clk_enable - perform a PHY reset if needed
  * @phydev: target phy_device struct
diff --git a/include/linux/phy.h b/include/linux/phy.h
index 4e84df2294d2..f9723367e2f7 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -1886,7 +1886,7 @@ int phy_init_hw(struct phy_device *phydev);
 int phy_suspend(struct phy_device *phydev);
 int phy_resume(struct phy_device *phydev);
 int __phy_resume(struct phy_device *phydev);
-int phy_loopback(struct phy_device *phydev, bool enable);
+int phy_loopback(struct phy_device *phydev, bool enable, int speed);
 int phy_sfp_connect_phy(void *upstream, struct phy_device *phy);
 void phy_sfp_disconnect_phy(void *upstream, struct phy_device *phy);
 void phy_sfp_attach(void *upstream, struct sfp_bus *bus);
diff --git a/net/core/selftests.c b/net/core/selftests.c
index 8f801e6e3b91..e99ae983fca9 100644
--- a/net/core/selftests.c
+++ b/net/core/selftests.c
@@ -299,7 +299,7 @@ static int net_test_phy_loopback_enable(struct net_device *ndev)
 	if (!ndev->phydev)
 		return -EOPNOTSUPP;
 
-	return phy_loopback(ndev->phydev, true);
+	return phy_loopback(ndev->phydev, true, 0);
 }
 
 static int net_test_phy_loopback_disable(struct net_device *ndev)
@@ -307,7 +307,7 @@ static int net_test_phy_loopback_disable(struct net_device *ndev)
 	if (!ndev->phydev)
 		return -EOPNOTSUPP;
 
-	return phy_loopback(ndev->phydev, false);
+	return phy_loopback(ndev->phydev, false, 0);
 }
 
 static int net_test_phy_loopback_udp(struct net_device *ndev)
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH net-next v6 3/7] net: phy: micrel: Add loopback support
  2025-02-09 19:08 [PATCH net-next v6 0/7] Support loopback mode speed selection Gerhard Engleder
  2025-02-09 19:08 ` [PATCH net-next v6 1/7] net: phy: Allow loopback speed selection for PHY drivers Gerhard Engleder
  2025-02-09 19:08 ` [PATCH net-next v6 2/7] net: phy: Support speed selection for PHY loopback Gerhard Engleder
@ 2025-02-09 19:08 ` Gerhard Engleder
  2025-02-12  1:51   ` Andrew Lunn
  2025-02-09 19:08 ` [PATCH net-next v6 4/7] net: phy: marvell: Align set_loopback() implementation Gerhard Engleder
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Gerhard Engleder @ 2025-02-09 19:08 UTC (permalink / raw)
  To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni
  Cc: netdev, Gerhard Engleder

The KSZ9031 PHYs requires full duplex for loopback mode. Add PHY
specific set_loopback() to ensure this.

Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>
---
 drivers/net/phy/micrel.c | 28 ++++++++++++++++++++++++++++
 1 file changed, 28 insertions(+)

diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 9c0b1c229af6..04c4187e976c 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -1030,6 +1030,33 @@ static int ksz9021_config_init(struct phy_device *phydev)
 #define MII_KSZ9031RN_EDPD		0x23
 #define MII_KSZ9031RN_EDPD_ENABLE	BIT(0)
 
+static int ksz9031_set_loopback(struct phy_device *phydev, bool enable,
+				int speed)
+{
+	u16 ctl = BMCR_LOOPBACK;
+	int ret, val;
+
+	if (!enable)
+		return genphy_loopback(phydev, enable, 0);
+
+	if (speed == SPEED_10 || speed == SPEED_100 || speed == SPEED_1000)
+		phydev->speed = speed;
+	else if (speed)
+		return -EINVAL;
+	phydev->duplex = DUPLEX_FULL;
+
+	ctl |= mii_bmcr_encode_fixed(phydev->speed, phydev->duplex);
+
+	phy_write(phydev, MII_BMCR, ctl);
+
+	ret = phy_read_poll_timeout(phydev, MII_BMSR, val, val & BMSR_LSTATUS,
+				    5000, 500000, true);
+	if (ret)
+		return ret;
+
+	return 0;
+}
+
 static int ksz9031_of_load_skew_values(struct phy_device *phydev,
 				       const struct device_node *of_node,
 				       u16 reg, size_t field_sz,
@@ -5564,6 +5591,7 @@ static struct phy_driver ksphy_driver[] = {
 	.resume		= kszphy_resume,
 	.cable_test_start	= ksz9x31_cable_test_start,
 	.cable_test_get_status	= ksz9x31_cable_test_get_status,
+	.set_loopback	= ksz9031_set_loopback,
 }, {
 	.phy_id		= PHY_ID_LAN8814,
 	.phy_id_mask	= MICREL_PHY_ID_MASK,
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH net-next v6 4/7] net: phy: marvell: Align set_loopback() implementation
  2025-02-09 19:08 [PATCH net-next v6 0/7] Support loopback mode speed selection Gerhard Engleder
                   ` (2 preceding siblings ...)
  2025-02-09 19:08 ` [PATCH net-next v6 3/7] net: phy: micrel: Add loopback support Gerhard Engleder
@ 2025-02-09 19:08 ` Gerhard Engleder
  2025-02-12  1:53   ` Andrew Lunn
  2025-02-09 19:08 ` [PATCH net-next v6 5/7] tsnep: Select speed for loopback Gerhard Engleder
                   ` (2 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Gerhard Engleder @ 2025-02-09 19:08 UTC (permalink / raw)
  To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni
  Cc: netdev, Gerhard Engleder

Use genphy_loopback() to disable loopback like ksz9031_set_loopback().
This way disable loopback is implemented only once within
genphy_loopback() and the set_loopback() implementations look similar.

Also fix comment about msleep() in the out-of loopback case which is not
executed in the out-of loopback case.

Suggested-by: Andrew Lunn <andrew@lunn.ch>
Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>
---
 drivers/net/phy/marvell.c | 72 ++++++++++++++++++---------------------
 1 file changed, 33 insertions(+), 39 deletions(-)

diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 4ed7ec1be74f..ca8b7d97c964 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -2133,56 +2133,50 @@ static void marvell_get_stats_simple(struct phy_device *phydev,
 
 static int m88e1510_loopback(struct phy_device *phydev, bool enable, int speed)
 {
+	u16 bmcr_ctl, mscr2_ctl = 0;
 	int err;
 
-	if (enable) {
-		u16 bmcr_ctl, mscr2_ctl = 0;
+	if (!enable)
+		return genphy_loopback(phydev, enable, 0);
 
-		if (speed == SPEED_10 || speed == SPEED_100 ||
-		    speed == SPEED_1000)
-			phydev->speed = speed;
-		else if (speed)
-			return -EINVAL;
-
-		bmcr_ctl = mii_bmcr_encode_fixed(phydev->speed, phydev->duplex);
-
-		err = phy_write(phydev, MII_BMCR, bmcr_ctl);
-		if (err < 0)
-			return err;
+	if (speed == SPEED_10 || speed == SPEED_100 || speed == SPEED_1000)
+		phydev->speed = speed;
+	else if (speed)
+		return -EINVAL;
 
-		if (phydev->speed == SPEED_1000)
-			mscr2_ctl = BMCR_SPEED1000;
-		else if (phydev->speed == SPEED_100)
-			mscr2_ctl = BMCR_SPEED100;
+	bmcr_ctl = mii_bmcr_encode_fixed(phydev->speed, phydev->duplex);
 
-		err = phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE,
-				       MII_88E1510_MSCR_2, BMCR_SPEED1000 |
-				       BMCR_SPEED100, mscr2_ctl);
-		if (err < 0)
-			return err;
+	err = phy_write(phydev, MII_BMCR, bmcr_ctl);
+	if (err < 0)
+		return err;
 
-		/* Need soft reset to have speed configuration takes effect */
-		err = genphy_soft_reset(phydev);
-		if (err < 0)
-			return err;
+	if (phydev->speed == SPEED_1000)
+		mscr2_ctl = BMCR_SPEED1000;
+	else if (phydev->speed == SPEED_100)
+		mscr2_ctl = BMCR_SPEED100;
 
-		err = phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK,
-				 BMCR_LOOPBACK);
+	err = phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE,
+			       MII_88E1510_MSCR_2, BMCR_SPEED1000 |
+			       BMCR_SPEED100, mscr2_ctl);
+	if (err < 0)
+		return err;
 
-		if (!err) {
-			/* It takes some time for PHY device to switch
-			 * into/out-of loopback mode.
-			 */
-			msleep(1000);
-		}
+	/* Need soft reset to have speed configuration takes effect */
+	err = genphy_soft_reset(phydev);
+	if (err < 0)
 		return err;
-	} else {
-		err = phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK, 0);
-		if (err < 0)
-			return err;
 
-		return phy_config_aneg(phydev);
+	err = phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK,
+			 BMCR_LOOPBACK);
+
+	if (!err) {
+		/*
+		 * It takes some time for PHY device to switch into loopback
+		 * mode.
+		 */
+		msleep(1000);
 	}
+	return err;
 }
 
 static int marvell_vct5_wait_complete(struct phy_device *phydev)
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH net-next v6 5/7] tsnep: Select speed for loopback
  2025-02-09 19:08 [PATCH net-next v6 0/7] Support loopback mode speed selection Gerhard Engleder
                   ` (3 preceding siblings ...)
  2025-02-09 19:08 ` [PATCH net-next v6 4/7] net: phy: marvell: Align set_loopback() implementation Gerhard Engleder
@ 2025-02-09 19:08 ` Gerhard Engleder
  2025-02-12  1:55   ` Andrew Lunn
  2025-02-09 19:08 ` [PATCH net-next v6 6/7] net: selftests: Export net_test_phy_loopback_* Gerhard Engleder
  2025-02-09 19:08 ` [PATCH net-next v6 7/7] tsnep: Add PHY loopback selftests Gerhard Engleder
  6 siblings, 1 reply; 21+ messages in thread
From: Gerhard Engleder @ 2025-02-09 19:08 UTC (permalink / raw)
  To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni
  Cc: netdev, Gerhard Engleder

Use 100 Mbps only if the PHY is configured to this speed. Otherwise use
always the maximum speed of 1000 Mbps.

Also remove explicit setting of carrier on and link mode after loopback.
This is not needed anymore, because phy_loopback() with selected speed
signals the link and the speed to the MAC.

Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>
---
 drivers/net/ethernet/engleder/tsnep_main.c | 21 ++++++++++-----------
 1 file changed, 10 insertions(+), 11 deletions(-)

diff --git a/drivers/net/ethernet/engleder/tsnep_main.c b/drivers/net/ethernet/engleder/tsnep_main.c
index a16b12137edb..d77a5b423c4c 100644
--- a/drivers/net/ethernet/engleder/tsnep_main.c
+++ b/drivers/net/ethernet/engleder/tsnep_main.c
@@ -228,20 +228,19 @@ static void tsnep_phy_link_status_change(struct net_device *netdev)
 
 static int tsnep_phy_loopback(struct tsnep_adapter *adapter, bool enable)
 {
-	int retval;
-
-	retval = phy_loopback(adapter->phydev, enable, 0);
+	int speed;
 
-	/* PHY link state change is not signaled if loopback is enabled, it
-	 * would delay a working loopback anyway, let's ensure that loopback
-	 * is working immediately by setting link mode directly
-	 */
-	if (!retval && enable) {
-		netif_carrier_on(adapter->netdev);
-		tsnep_set_link_mode(adapter);
+	if (enable) {
+		if (adapter->phydev->autoneg == AUTONEG_DISABLE &&
+		    adapter->phydev->speed == SPEED_100)
+			speed = SPEED_100;
+		else
+			speed = SPEED_1000;
+	} else {
+		speed = 0;
 	}
 
-	return retval;
+	return phy_loopback(adapter->phydev, enable, speed);
 }
 
 static int tsnep_phy_open(struct tsnep_adapter *adapter)
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH net-next v6 6/7] net: selftests: Export net_test_phy_loopback_*
  2025-02-09 19:08 [PATCH net-next v6 0/7] Support loopback mode speed selection Gerhard Engleder
                   ` (4 preceding siblings ...)
  2025-02-09 19:08 ` [PATCH net-next v6 5/7] tsnep: Select speed for loopback Gerhard Engleder
@ 2025-02-09 19:08 ` Gerhard Engleder
  2025-02-12  2:23   ` Andrew Lunn
  2025-02-09 19:08 ` [PATCH net-next v6 7/7] tsnep: Add PHY loopback selftests Gerhard Engleder
  6 siblings, 1 reply; 21+ messages in thread
From: Gerhard Engleder @ 2025-02-09 19:08 UTC (permalink / raw)
  To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni
  Cc: netdev, Gerhard Engleder, Oleksij Rempel

net_selftests() provides a generic set of selftests for netdevs with
PHY. Those selftests rely on an existing link to inherit the speed for
the loopback mode.

net_selftests() is not designed to extend existing selftests of drivers,
but with net_test_phy_loopback_* it contains useful test infrastructure.

Export net_test_phy_loopback_* to enable reuse in existing selftests of
other drivers. This also enables driver specific loopback modes, which
don't rely on an existing link.

Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>
CC: Oleksij Rempel <o.rempel@pengutronix.de>
---
 include/net/selftests.h | 19 +++++++++++++++++++
 net/core/selftests.c    |  9 ++++++---
 2 files changed, 25 insertions(+), 3 deletions(-)

diff --git a/include/net/selftests.h b/include/net/selftests.h
index e65e8d230d33..a13237c33e58 100644
--- a/include/net/selftests.h
+++ b/include/net/selftests.h
@@ -6,6 +6,10 @@
 
 #if IS_ENABLED(CONFIG_NET_SELFTESTS)
 
+int net_test_phy_loopback_udp(struct net_device *ndev);
+int net_test_phy_loopback_udp_mtu(struct net_device *ndev);
+int net_test_phy_loopback_tcp(struct net_device *ndev);
+
 void net_selftest(struct net_device *ndev, struct ethtool_test *etest,
 		  u64 *buf);
 int net_selftest_get_count(void);
@@ -13,6 +17,21 @@ void net_selftest_get_strings(u8 *data);
 
 #else
 
+static inline int net_test_phy_loopback_udp(struct net_device *ndev)
+{
+	return 0;
+}
+
+static inline int net_test_phy_loopback_udp_mtu(struct net_device *ndev)
+{
+	return 0;
+}
+
+static inline int net_test_phy_loopback_tcp(struct net_device *ndev)
+{
+	return 0;
+}
+
 static inline void net_selftest(struct net_device *ndev, struct ethtool_test *etest,
 				u64 *buf)
 {
diff --git a/net/core/selftests.c b/net/core/selftests.c
index e99ae983fca9..d4e0e2eff991 100644
--- a/net/core/selftests.c
+++ b/net/core/selftests.c
@@ -310,15 +310,16 @@ static int net_test_phy_loopback_disable(struct net_device *ndev)
 	return phy_loopback(ndev->phydev, false, 0);
 }
 
-static int net_test_phy_loopback_udp(struct net_device *ndev)
+int net_test_phy_loopback_udp(struct net_device *ndev)
 {
 	struct net_packet_attrs attr = { };
 
 	attr.dst = ndev->dev_addr;
 	return __net_test_loopback(ndev, &attr);
 }
+EXPORT_SYMBOL_GPL(net_test_phy_loopback_udp);
 
-static int net_test_phy_loopback_udp_mtu(struct net_device *ndev)
+int net_test_phy_loopback_udp_mtu(struct net_device *ndev)
 {
 	struct net_packet_attrs attr = { };
 
@@ -326,8 +327,9 @@ static int net_test_phy_loopback_udp_mtu(struct net_device *ndev)
 	attr.max_size = ndev->mtu;
 	return __net_test_loopback(ndev, &attr);
 }
+EXPORT_SYMBOL_GPL(net_test_phy_loopback_udp_mtu);
 
-static int net_test_phy_loopback_tcp(struct net_device *ndev)
+int net_test_phy_loopback_tcp(struct net_device *ndev)
 {
 	struct net_packet_attrs attr = { };
 
@@ -335,6 +337,7 @@ static int net_test_phy_loopback_tcp(struct net_device *ndev)
 	attr.tcp = true;
 	return __net_test_loopback(ndev, &attr);
 }
+EXPORT_SYMBOL_GPL(net_test_phy_loopback_tcp);
 
 static const struct net_test {
 	char name[ETH_GSTRING_LEN];
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* [PATCH net-next v6 7/7] tsnep: Add PHY loopback selftests
  2025-02-09 19:08 [PATCH net-next v6 0/7] Support loopback mode speed selection Gerhard Engleder
                   ` (5 preceding siblings ...)
  2025-02-09 19:08 ` [PATCH net-next v6 6/7] net: selftests: Export net_test_phy_loopback_* Gerhard Engleder
@ 2025-02-09 19:08 ` Gerhard Engleder
  6 siblings, 0 replies; 21+ messages in thread
From: Gerhard Engleder @ 2025-02-09 19:08 UTC (permalink / raw)
  To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni
  Cc: netdev, Gerhard Engleder

Add loopback selftests on PHY level. This enables quick testing of
loopback functionality to ensure working loopback for testing.

Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>
---
 drivers/net/ethernet/engleder/Kconfig         |   1 +
 .../net/ethernet/engleder/tsnep_selftests.c   | 153 +++++++++++++++++-
 2 files changed, 150 insertions(+), 4 deletions(-)

diff --git a/drivers/net/ethernet/engleder/Kconfig b/drivers/net/ethernet/engleder/Kconfig
index 3df6bf476ae7..8245a9c4377d 100644
--- a/drivers/net/ethernet/engleder/Kconfig
+++ b/drivers/net/ethernet/engleder/Kconfig
@@ -32,6 +32,7 @@ config TSNEP_SELFTESTS
 	bool "TSN endpoint self test support"
 	default n
 	depends on TSNEP
+	imply NET_SELFTESTS
 	help
 	  This enables self test support within the TSN endpoint driver.
 
diff --git a/drivers/net/ethernet/engleder/tsnep_selftests.c b/drivers/net/ethernet/engleder/tsnep_selftests.c
index 8a9145f93147..c9857e5a8033 100644
--- a/drivers/net/ethernet/engleder/tsnep_selftests.c
+++ b/drivers/net/ethernet/engleder/tsnep_selftests.c
@@ -4,12 +4,15 @@
 #include "tsnep.h"
 
 #include <net/pkt_sched.h>
+#include <net/selftests.h>
 
 enum tsnep_test {
 	TSNEP_TEST_ENABLE = 0,
 	TSNEP_TEST_TAPRIO,
 	TSNEP_TEST_TAPRIO_CHANGE,
 	TSNEP_TEST_TAPRIO_EXTENSION,
+	TSNEP_TEST_PHY_1000_LOOPBACK,
+	TSNEP_TEST_PHY_100_LOOPBACK,
 };
 
 static const char tsnep_test_strings[][ETH_GSTRING_LEN] = {
@@ -17,6 +20,8 @@ static const char tsnep_test_strings[][ETH_GSTRING_LEN] = {
 	"TAPRIO                (offline)",
 	"TAPRIO change         (offline)",
 	"TAPRIO extension      (offline)",
+	"PHY 1000Mbps loopback (offline)",
+	"PHY 100Mbps loopback  (offline)",
 };
 
 #define TSNEP_TEST_COUNT (sizeof(tsnep_test_strings) / ETH_GSTRING_LEN)
@@ -754,6 +759,133 @@ static bool tsnep_test_taprio_extension(struct tsnep_adapter *adapter)
 	return false;
 }
 
+static bool test_loopback(struct tsnep_adapter *adapter, int speed)
+{
+	struct phy_device *phydev = adapter->phydev;
+	int retval;
+
+	retval = phy_loopback(phydev, true, speed);
+	if (retval || !phydev->loopback_enabled || !phydev->link ||
+	    phydev->speed != speed)
+		return false;
+
+	retval = net_test_phy_loopback_udp(adapter->netdev);
+	if (retval)
+		return false;
+
+	retval = net_test_phy_loopback_udp_mtu(adapter->netdev);
+	if (retval)
+		return false;
+
+	retval = net_test_phy_loopback_tcp(adapter->netdev);
+	if (retval)
+		return false;
+
+	retval = phy_loopback(phydev, false, 0);
+	if (retval || phydev->loopback_enabled)
+		return false;
+
+	return true;
+}
+
+static bool set_speed(struct tsnep_adapter *adapter, int speed)
+{
+	struct ethtool_link_ksettings cmd;
+	int retval;
+
+	retval = tsnep_ethtool_ops.get_link_ksettings(adapter->netdev, &cmd);
+	if (retval)
+		return false;
+
+	if (speed) {
+		cmd.base.speed = speed;
+		cmd.base.duplex = DUPLEX_FULL;
+		cmd.base.autoneg = AUTONEG_DISABLE;
+	} else {
+		cmd.base.autoneg = AUTONEG_ENABLE;
+	}
+
+	retval = tsnep_ethtool_ops.set_link_ksettings(adapter->netdev, &cmd);
+	if (retval)
+		return false;
+
+	return true;
+}
+
+static bool tsnep_test_phy_1000_loopback(struct tsnep_adapter *adapter)
+{
+	if (!adapter->netdev->phydev)
+		return false;
+
+	if (!test_loopback(adapter, 1000))
+		goto failed;
+
+	/* after autonegotiation */
+	if (!set_speed(adapter, 0))
+		goto failed;
+	if (!test_loopback(adapter, 1000))
+		goto failed;
+
+	/* after 100Mbps fixed speed */
+	if (!set_speed(adapter, 100))
+		goto failed;
+	if (!test_loopback(adapter, 1000))
+		goto failed;
+
+	/* after 1000Mbps fixed speed */
+	if (!set_speed(adapter, 1000))
+		goto failed;
+	if (!test_loopback(adapter, 1000))
+		goto failed;
+
+	if (!set_speed(adapter, 0))
+		goto failed;
+
+	return true;
+
+failed:
+	phy_loopback(adapter->phydev, false, 0);
+	set_speed(adapter, 0);
+	return false;
+}
+
+static bool tsnep_test_phy_100_loopback(struct tsnep_adapter *adapter)
+{
+	if (!adapter->netdev->phydev)
+		return false;
+
+	if (!test_loopback(adapter, 100))
+		goto failed;
+
+	/* after autonegotiation */
+	if (!set_speed(adapter, 0))
+		goto failed;
+	if (!test_loopback(adapter, 100))
+		goto failed;
+
+	/* 100Mbps fixed speed */
+	if (!set_speed(adapter, 100))
+		goto failed;
+	if (!test_loopback(adapter, 100))
+		goto failed;
+
+	/* 1000Mbps fixed speed */
+	if (!set_speed(adapter, 1000))
+		goto failed;
+	if (!test_loopback(adapter, 100))
+		goto failed;
+
+	if (!set_speed(adapter, 0))
+		goto failed;
+
+	return true;
+
+failed:
+	phy_loopback(adapter->phydev, false, 0);
+	set_speed(adapter, 0);
+	return false;
+}
+
 int tsnep_ethtool_get_test_count(void)
 {
 	return TSNEP_TEST_COUNT;
@@ -768,15 +900,14 @@ void tsnep_ethtool_self_test(struct net_device *netdev,
 			     struct ethtool_test *eth_test, u64 *data)
 {
 	struct tsnep_adapter *adapter = netdev_priv(netdev);
+	int i;
 
 	eth_test->len = TSNEP_TEST_COUNT;
 
 	if (eth_test->flags != ETH_TEST_FL_OFFLINE) {
 		/* no tests are done online */
-		data[TSNEP_TEST_ENABLE] = 0;
-		data[TSNEP_TEST_TAPRIO] = 0;
-		data[TSNEP_TEST_TAPRIO_CHANGE] = 0;
-		data[TSNEP_TEST_TAPRIO_EXTENSION] = 0;
+		for (i = 0; i < TSNEP_TEST_COUNT; i++)
+			data[i] = 0;
 
 		return;
 	}
@@ -808,4 +939,18 @@ void tsnep_ethtool_self_test(struct net_device *netdev,
 		eth_test->flags |= ETH_TEST_FL_FAILED;
 		data[TSNEP_TEST_TAPRIO_EXTENSION] = 1;
 	}
+
+	if (tsnep_test_phy_1000_loopback(adapter)) {
+		data[TSNEP_TEST_PHY_1000_LOOPBACK] = 0;
+	} else {
+		eth_test->flags |= ETH_TEST_FL_FAILED;
+		data[TSNEP_TEST_PHY_1000_LOOPBACK] = 1;
+	}
+
+	if (tsnep_test_phy_100_loopback(adapter)) {
+		data[TSNEP_TEST_PHY_100_LOOPBACK] = 0;
+	} else {
+		eth_test->flags |= ETH_TEST_FL_FAILED;
+		data[TSNEP_TEST_PHY_100_LOOPBACK] = 1;
+	}
 }
-- 
2.39.5


^ permalink raw reply related	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next v6 2/7] net: phy: Support speed selection for PHY loopback
  2025-02-09 19:08 ` [PATCH net-next v6 2/7] net: phy: Support speed selection for PHY loopback Gerhard Engleder
@ 2025-02-12  1:48   ` Andrew Lunn
  2025-02-12 20:01     ` Gerhard Engleder
  0 siblings, 1 reply; 21+ messages in thread
From: Andrew Lunn @ 2025-02-12  1:48 UTC (permalink / raw)
  To: Gerhard Engleder; +Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev

> +int phy_loopback(struct phy_device *phydev, bool enable, int speed)
> +{
> +	bool link_up = false;
> +	int ret = 0;
> +
> +	if (!phydev->drv)
> +		return -EIO;
> +
> +	mutex_lock(&phydev->lock);
> +
> +	if (enable && phydev->loopback_enabled) {
> +		ret = -EBUSY;
> +		goto out;
> +	}
> +
> +	if (!enable && !phydev->loopback_enabled) {
> +		ret = -EINVAL;
> +		goto out;
> +	}
> +
> +	if (enable) {
> +		/*
> +		 * Link up is signaled with a defined speed. If speed changes,
> +		 * then first link down and after that link up needs to be
> +		 * signaled.
> +		 */
> +		if (phydev->link && phydev->state == PHY_RUNNING) {
> +			/* link is up and signaled */
> +			if (speed && phydev->speed != speed) {
> +				/* signal link down and up for new speed */
> +				phydev->link = false;
> +				phydev->state = PHY_NOLINK;
> +				phy_link_down(phydev);

If you set the link down here...

> +
> +				link_up = true;
> +			}
> +		} else {
> +			/* link is not signaled */
> +			if (speed) {
> +				/* signal link up for new speed */
> +				link_up = true;
> +			}
> +		}
> +	}
> +
> +	if (phydev->drv->set_loopback)
> +		ret = phydev->drv->set_loopback(phydev, enable, speed);
> +	else
> +		ret = genphy_loopback(phydev, enable, speed);
> +
> +	if (ret)
> +		goto out;

and this fails, you leave the link down. You should make an attempt to
restore the link to the old state before returning the error.

	Andrew

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next v6 3/7] net: phy: micrel: Add loopback support
  2025-02-09 19:08 ` [PATCH net-next v6 3/7] net: phy: micrel: Add loopback support Gerhard Engleder
@ 2025-02-12  1:51   ` Andrew Lunn
  2025-02-12 20:03     ` Gerhard Engleder
  0 siblings, 1 reply; 21+ messages in thread
From: Andrew Lunn @ 2025-02-12  1:51 UTC (permalink / raw)
  To: Gerhard Engleder; +Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev

> +	ret = phy_read_poll_timeout(phydev, MII_BMSR, val, val & BMSR_LSTATUS,
> +				    5000, 500000, true);
> +	if (ret)
> +		return ret;
> +
> +	return 0;

This can be simplified to jus

        return phy_read_poll_timeout(...);

    Andrew

---
pw-bot: cr

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next v6 4/7] net: phy: marvell: Align set_loopback() implementation
  2025-02-09 19:08 ` [PATCH net-next v6 4/7] net: phy: marvell: Align set_loopback() implementation Gerhard Engleder
@ 2025-02-12  1:53   ` Andrew Lunn
  0 siblings, 0 replies; 21+ messages in thread
From: Andrew Lunn @ 2025-02-12  1:53 UTC (permalink / raw)
  To: Gerhard Engleder; +Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev

On Sun, Feb 09, 2025 at 08:08:24PM +0100, Gerhard Engleder wrote:
> Use genphy_loopback() to disable loopback like ksz9031_set_loopback().
> This way disable loopback is implemented only once within
> genphy_loopback() and the set_loopback() implementations look similar.
> 
> Also fix comment about msleep() in the out-of loopback case which is not
> executed in the out-of loopback case.
> 
> Suggested-by: Andrew Lunn <andrew@lunn.ch>
> Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next v6 1/7] net: phy: Allow loopback speed selection for PHY drivers
  2025-02-09 19:08 ` [PATCH net-next v6 1/7] net: phy: Allow loopback speed selection for PHY drivers Gerhard Engleder
@ 2025-02-12  1:53   ` Andrew Lunn
  0 siblings, 0 replies; 21+ messages in thread
From: Andrew Lunn @ 2025-02-12  1:53 UTC (permalink / raw)
  To: Gerhard Engleder; +Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev

On Sun, Feb 09, 2025 at 08:08:21PM +0100, Gerhard Engleder wrote:
> PHY drivers support loopback mode, but it is not possible to select the
> speed of the loopback mode. The speed is chosen by the set_loopback()
> operation of the PHY driver. Same is valid for genphy_loopback().
> 
> There are PHYs that support loopback with different speeds. Extend
> set_loopback() to make loopback speed selection possible.
> 
> Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next v6 5/7] tsnep: Select speed for loopback
  2025-02-09 19:08 ` [PATCH net-next v6 5/7] tsnep: Select speed for loopback Gerhard Engleder
@ 2025-02-12  1:55   ` Andrew Lunn
  0 siblings, 0 replies; 21+ messages in thread
From: Andrew Lunn @ 2025-02-12  1:55 UTC (permalink / raw)
  To: Gerhard Engleder; +Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev

On Sun, Feb 09, 2025 at 08:08:25PM +0100, Gerhard Engleder wrote:
> Use 100 Mbps only if the PHY is configured to this speed. Otherwise use
> always the maximum speed of 1000 Mbps.
> 
> Also remove explicit setting of carrier on and link mode after loopback.
> This is not needed anymore, because phy_loopback() with selected speed
> signals the link and the speed to the MAC.
> 
> Signed-off-by: Gerhard Engleder <gerhard@engleder-embedded.com>

Reviewed-by: Andrew Lunn <andrew@lunn.ch>

    Andrew

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next v6 6/7] net: selftests: Export net_test_phy_loopback_*
  2025-02-09 19:08 ` [PATCH net-next v6 6/7] net: selftests: Export net_test_phy_loopback_* Gerhard Engleder
@ 2025-02-12  2:23   ` Andrew Lunn
  2025-02-12 20:13     ` Gerhard Engleder
  0 siblings, 1 reply; 21+ messages in thread
From: Andrew Lunn @ 2025-02-12  2:23 UTC (permalink / raw)
  To: Gerhard Engleder
  Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
	Oleksij Rempel

On Sun, Feb 09, 2025 at 08:08:26PM +0100, Gerhard Engleder wrote:
> net_selftests() provides a generic set of selftests for netdevs with
> PHY. Those selftests rely on an existing link to inherit the speed for
> the loopback mode.
> 
> net_selftests() is not designed to extend existing selftests of drivers,
> but with net_test_phy_loopback_* it contains useful test infrastructure.

It might not of originally been designed for that, but i think it can
be used as an extension. I've done the same for statistics, which uses
the same API.

For get_sset_count() you call net_selftest_get_count() and then add on
the number of driver specific tests. For ethtool_get_strings() first
call net_selftest_get_strings() and then append the driver tests
afterwards. For self_test, first call net_selftest() and then do the
driver specific tests.

I also think you can extend these tests to cover different speeds.
There are plenty of ethtool_test_flags bit free, so you can use one of
them to indicate the reserved value in ethtool_test contains a speed.
Everybody then gains from your work.

	Andrew

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next v6 2/7] net: phy: Support speed selection for PHY loopback
  2025-02-12  1:48   ` Andrew Lunn
@ 2025-02-12 20:01     ` Gerhard Engleder
  0 siblings, 0 replies; 21+ messages in thread
From: Gerhard Engleder @ 2025-02-12 20:01 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev

On 12.02.25 02:48, Andrew Lunn wrote:
>> +int phy_loopback(struct phy_device *phydev, bool enable, int speed)
>> +{
>> +	bool link_up = false;
>> +	int ret = 0;
>> +
>> +	if (!phydev->drv)
>> +		return -EIO;
>> +
>> +	mutex_lock(&phydev->lock);
>> +
>> +	if (enable && phydev->loopback_enabled) {
>> +		ret = -EBUSY;
>> +		goto out;
>> +	}
>> +
>> +	if (!enable && !phydev->loopback_enabled) {
>> +		ret = -EINVAL;
>> +		goto out;
>> +	}
>> +
>> +	if (enable) {
>> +		/*
>> +		 * Link up is signaled with a defined speed. If speed changes,
>> +		 * then first link down and after that link up needs to be
>> +		 * signaled.
>> +		 */
>> +		if (phydev->link && phydev->state == PHY_RUNNING) {
>> +			/* link is up and signaled */
>> +			if (speed && phydev->speed != speed) {
>> +				/* signal link down and up for new speed */
>> +				phydev->link = false;
>> +				phydev->state = PHY_NOLINK;
>> +				phy_link_down(phydev);
> 
> If you set the link down here...
> 
>> +
>> +				link_up = true;
>> +			}
>> +		} else {
>> +			/* link is not signaled */
>> +			if (speed) {
>> +				/* signal link up for new speed */
>> +				link_up = true;
>> +			}
>> +		}
>> +	}
>> +
>> +	if (phydev->drv->set_loopback)
>> +		ret = phydev->drv->set_loopback(phydev, enable, speed);
>> +	else
>> +		ret = genphy_loopback(phydev, enable, speed);
>> +
>> +	if (ret)
>> +		goto out;
> 
> and this fails, you leave the link down. You should make an attempt to
> restore the link to the old state before returning the error.

I will try to do the same as for loopback disable to try to restore the
the link.

Gerhard


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next v6 3/7] net: phy: micrel: Add loopback support
  2025-02-12  1:51   ` Andrew Lunn
@ 2025-02-12 20:03     ` Gerhard Engleder
  0 siblings, 0 replies; 21+ messages in thread
From: Gerhard Engleder @ 2025-02-12 20:03 UTC (permalink / raw)
  To: Andrew Lunn; +Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev



On 12.02.25 02:51, Andrew Lunn wrote:
>> +	ret = phy_read_poll_timeout(phydev, MII_BMSR, val, val & BMSR_LSTATUS,
>> +				    5000, 500000, true);
>> +	if (ret)
>> +		return ret;
>> +
>> +	return 0;
> 
> This can be simplified to jus
> 
>          return phy_read_poll_timeout(...);

Of course! Don't why I missed that.

Gerhard

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next v6 6/7] net: selftests: Export net_test_phy_loopback_*
  2025-02-12  2:23   ` Andrew Lunn
@ 2025-02-12 20:13     ` Gerhard Engleder
  2025-02-12 20:46       ` Andrew Lunn
  0 siblings, 1 reply; 21+ messages in thread
From: Gerhard Engleder @ 2025-02-12 20:13 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
	Oleksij Rempel

On 12.02.25 03:23, Andrew Lunn wrote:
> On Sun, Feb 09, 2025 at 08:08:26PM +0100, Gerhard Engleder wrote:
>> net_selftests() provides a generic set of selftests for netdevs with
>> PHY. Those selftests rely on an existing link to inherit the speed for
>> the loopback mode.
>>
>> net_selftests() is not designed to extend existing selftests of drivers,
>> but with net_test_phy_loopback_* it contains useful test infrastructure.
> 
> It might not of originally been designed for that, but i think it can
> be used as an extension. I've done the same for statistics, which uses
> the same API.
> 
> For get_sset_count() you call net_selftest_get_count() and then add on
> the number of driver specific tests. For ethtool_get_strings() first
> call net_selftest_get_strings() and then append the driver tests
> afterwards. For self_test, first call net_selftest() and then do the
> driver specific tests.
> 
> I also think you can extend these tests to cover different speeds.
> There are plenty of ethtool_test_flags bit free, so you can use one of
> them to indicate the reserved value in ethtool_test contains a speed.
> Everybody then gains from your work.

Reusing the complete test set as extension is not feasible as the first
test requires an existing link and for loopback test no link is
necessary. But yes, I can do better and rework it to reusable tests.
I'm not sure if I will use ethtool_test_flags as IMO ideally all tests
run always to ensure easy use.

Thank you for the review!

Gerhard

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next v6 6/7] net: selftests: Export net_test_phy_loopback_*
  2025-02-12 20:13     ` Gerhard Engleder
@ 2025-02-12 20:46       ` Andrew Lunn
  2025-02-12 21:36         ` Gerhard Engleder
  0 siblings, 1 reply; 21+ messages in thread
From: Andrew Lunn @ 2025-02-12 20:46 UTC (permalink / raw)
  To: Gerhard Engleder
  Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
	Oleksij Rempel

> Reusing the complete test set as extension is not feasible as the first
> test requires an existing link and for loopback test no link is
> necessary. But yes, I can do better and rework it to reusable tests.
> I'm not sure if I will use ethtool_test_flags as IMO ideally all tests
> run always to ensure easy use.

We try to ensure backwards/forwards compatibly between ethtool and the
kernel.

The point about ethtool_test_flags is that for older versions of
ethtool, you have no idea what the reserved field contains. Has it
always been set to zero? If there is a flag indicating reserved
contains a value, you then know it is safe to use it.

At some point, the API needs moving to netlink sockets. It then
becomes a lot easier to add extra parameters, as attributes.

There is also an interesting overlap here and:

https://netdevconf.info/0x19/sessions/talk/open-source-tooling-for-phy-management-and-testing.html

What you are doing is not too dissimilar, although the PRBS is an
802.3 standard concept and typically part of the PCS. There needs to
be some sort of API for configuring the PRBS, maybe as part of ethtool
self tests? If so, the API is going to need extensions.

	Andrew

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next v6 6/7] net: selftests: Export net_test_phy_loopback_*
  2025-02-12 20:46       ` Andrew Lunn
@ 2025-02-12 21:36         ` Gerhard Engleder
  2025-02-12 22:34           ` Andrew Lunn
  0 siblings, 1 reply; 21+ messages in thread
From: Gerhard Engleder @ 2025-02-12 21:36 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
	Oleksij Rempel

On 12.02.25 21:46, Andrew Lunn wrote:
>> Reusing the complete test set as extension is not feasible as the first
>> test requires an existing link and for loopback test no link is
>> necessary. But yes, I can do better and rework it to reusable tests.
>> I'm not sure if I will use ethtool_test_flags as IMO ideally all tests
>> run always to ensure easy use.
> 
> We try to ensure backwards/forwards compatibly between ethtool and the
> kernel.
> 
> The point about ethtool_test_flags is that for older versions of
> ethtool, you have no idea what the reserved field contains. Has it
> always been set to zero? If there is a flag indicating reserved
> contains a value, you then know it is safe to use it.

I'm not sure if I understand the last sentence. Do you mean it is safe
to use a flag that was previously marked as reserved if the clients did
set it to zero, but for ethtool_test_flags this is not the case?

> At some point, the API needs moving to netlink sockets. It then
> becomes a lot easier to add extra parameters, as attributes.
> 
> There is also an interesting overlap here and:
> 
> https://netdevconf.info/0x19/sessions/talk/open-source-tooling-for-phy-management-and-testing.html
> 
> What you are doing is not too dissimilar, although the PRBS is an
> 802.3 standard concept and typically part of the PCS. There needs to
> be some sort of API for configuring the PRBS, maybe as part of ethtool
> self tests? If so, the API is going to need extensions.

Sounds also similar to bit error testing of transceivers. I want to
stress a data link with all supported modes and this is similar.
For me it is sufficient if the driver tests all supported modes, without
any configuration from user space. But extending the API
to enable advanced testing during development and production is
reasonable.

Gerhard


^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next v6 6/7] net: selftests: Export net_test_phy_loopback_*
  2025-02-12 21:36         ` Gerhard Engleder
@ 2025-02-12 22:34           ` Andrew Lunn
  2025-02-12 22:53             ` Russell King (Oracle)
  0 siblings, 1 reply; 21+ messages in thread
From: Andrew Lunn @ 2025-02-12 22:34 UTC (permalink / raw)
  To: Gerhard Engleder
  Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
	Oleksij Rempel

On Wed, Feb 12, 2025 at 10:36:00PM +0100, Gerhard Engleder wrote:
> On 12.02.25 21:46, Andrew Lunn wrote:
> > > Reusing the complete test set as extension is not feasible as the first
> > > test requires an existing link and for loopback test no link is
> > > necessary. But yes, I can do better and rework it to reusable tests.
> > > I'm not sure if I will use ethtool_test_flags as IMO ideally all tests
> > > run always to ensure easy use.
> > 
> > We try to ensure backwards/forwards compatibly between ethtool and the
> > kernel.
> > 
> > The point about ethtool_test_flags is that for older versions of
> > ethtool, you have no idea what the reserved field contains. Has it
> > always been set to zero? If there is a flag indicating reserved
> > contains a value, you then know it is safe to use it.
> 
> I'm not sure if I understand the last sentence. Do you mean it is safe
> to use a flag that was previously marked as reserved if the clients did
> set it to zero, but for ethtool_test_flags this is not the case?

We have:

struct ethtool_test {
	__u32	cmd;
	__u32	flags;
	__u32	reserved;
	__u32	len;
	__u64	data[];
};

where flags takes a bitmap from:

enum ethtool_test_flags {
	ETH_TEST_FL_OFFLINE	= (1 << 0),
	ETH_TEST_FL_FAILED	= (1 << 1),
	ETH_TEST_FL_EXTERNAL_LB	= (1 << 2),
	ETH_TEST_FL_EXTERNAL_LB_DONE	= (1 << 3),
};

I've not looked at ethtool, but it is possible the struct ethtool_test
is on the stack, or the heap, and not zeroed. So reserved contains
random junk. flags is however given a value, bad things would happen
otherwise. So we know the bits which are currently unused should be
zero. A new flag can be added, which indicates user space wants to set
the speed, and that the speed is in the reserved field. Without the
flag being set, reserved contains random junk, with it set, we know we
have a version of ethtool which sets it to a specific value.

It might however be that we cannot rename reserved, it is now part of
the kAPI, and changing it to another name would break the compilation
of something. That is one of the advantages of netlink API, you can
add new attributes without having to worry about breaking older
builds. Unfortunately, the self test is still using the IOCTL, it has
not been converted to netlink.

    Andrew

^ permalink raw reply	[flat|nested] 21+ messages in thread

* Re: [PATCH net-next v6 6/7] net: selftests: Export net_test_phy_loopback_*
  2025-02-12 22:34           ` Andrew Lunn
@ 2025-02-12 22:53             ` Russell King (Oracle)
  0 siblings, 0 replies; 21+ messages in thread
From: Russell King (Oracle) @ 2025-02-12 22:53 UTC (permalink / raw)
  To: Andrew Lunn
  Cc: Gerhard Engleder, hkallweit1, davem, edumazet, kuba, pabeni,
	netdev, Oleksij Rempel

On Wed, Feb 12, 2025 at 11:34:14PM +0100, Andrew Lunn wrote:
> It might however be that we cannot rename reserved, it is now part of
> the kAPI, and changing it to another name would break the compilation
> of something. That is one of the advantages of netlink API, you can
> add new attributes without having to worry about breaking older
> builds. Unfortunately, the self test is still using the IOCTL, it has
> not been converted to netlink.

If you wanted to introduce "speed" where "reserved" is, then could be
done is:

struct ethtool_test {
	__u32	cmd;
	__u32	flags;
	union {
		__u32	reserved;
		__u32	speed;
	};
	__u32	len;
	__u64	data[];
};

That would mean anyone assigning to ethtool_test.reserved would still
continue to work as the union is anonymous.

-- 
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!

^ permalink raw reply	[flat|nested] 21+ messages in thread

end of thread, other threads:[~2025-02-12 22:53 UTC | newest]

Thread overview: 21+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-02-09 19:08 [PATCH net-next v6 0/7] Support loopback mode speed selection Gerhard Engleder
2025-02-09 19:08 ` [PATCH net-next v6 1/7] net: phy: Allow loopback speed selection for PHY drivers Gerhard Engleder
2025-02-12  1:53   ` Andrew Lunn
2025-02-09 19:08 ` [PATCH net-next v6 2/7] net: phy: Support speed selection for PHY loopback Gerhard Engleder
2025-02-12  1:48   ` Andrew Lunn
2025-02-12 20:01     ` Gerhard Engleder
2025-02-09 19:08 ` [PATCH net-next v6 3/7] net: phy: micrel: Add loopback support Gerhard Engleder
2025-02-12  1:51   ` Andrew Lunn
2025-02-12 20:03     ` Gerhard Engleder
2025-02-09 19:08 ` [PATCH net-next v6 4/7] net: phy: marvell: Align set_loopback() implementation Gerhard Engleder
2025-02-12  1:53   ` Andrew Lunn
2025-02-09 19:08 ` [PATCH net-next v6 5/7] tsnep: Select speed for loopback Gerhard Engleder
2025-02-12  1:55   ` Andrew Lunn
2025-02-09 19:08 ` [PATCH net-next v6 6/7] net: selftests: Export net_test_phy_loopback_* Gerhard Engleder
2025-02-12  2:23   ` Andrew Lunn
2025-02-12 20:13     ` Gerhard Engleder
2025-02-12 20:46       ` Andrew Lunn
2025-02-12 21:36         ` Gerhard Engleder
2025-02-12 22:34           ` Andrew Lunn
2025-02-12 22:53             ` Russell King (Oracle)
2025-02-09 19:08 ` [PATCH net-next v6 7/7] tsnep: Add PHY loopback selftests Gerhard Engleder

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).