[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Message-Id: <20241013202430.93851-1-gerhard@engleder-embedded.com>
Date: Sun, 13 Oct 2024 22:24:30 +0200
From: Gerhard Engleder <gerhard@...leder-embedded.com>
To: andrew@...n.ch,
hkallweit1@...il.com,
linux@...linux.org.uk,
davem@...emloft.net,
edumazet@...gle.com,
kuba@...nel.org,
pabeni@...hat.com
Cc: netdev@...r.kernel.org,
Gerhard Engleder <gerhard@...leder-embedded.com>
Subject: [PATCH RFC net-next] net: phy: micrel: Improve loopback support if autoneg is enabled
Prior to commit 6ff3cddc365b it was possible to enable loopback with
a defined speed. First a fixed speed was set with ETHTOOL_SLINKSETTINGS
and afterwards the loopback was enabled. This worked, because
genphy_loopback() uses the current speed and duplex. I used this
mechanism to test tsnep in loopback with different speeds. A KSZ9031 PHY
is used.
With commit 6ff3cddc365b for 1000 Mbit/s auto negotiation was enabled.
Setting a fixed speed with ETHTOOL_SLINKSETTINGS does not work anymore
for 1000 Mbit/s as speed and duplex of the PHY now depend on the result
of the auto negotiation. As a result, genphy_loopback() also depends on
the result of the auto negotiation. But enabling loopback shall be
independent of any auto negotiation process.
Make loopback of KSZ9031 PHY work even if current speed and/or duplex of
PHY are unkown because of autoneg.
Fixes: 6ff3cddc365b ("net: phylib: do not disable autoneg for fixed speeds >= 1G")
Signed-off-by: Gerhard Engleder <gerhard@...leder-embedded.com>
---
drivers/net/phy/micrel.c | 27 +++++++++++++++++++++++++++
1 file changed, 27 insertions(+)
diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c
index 65b0a3115e14..3cbe40265190 100644
--- a/drivers/net/phy/micrel.c
+++ b/drivers/net/phy/micrel.c
@@ -1028,6 +1028,32 @@ 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)
+{
+ if (enable) {
+ u16 ctl = BMCR_LOOPBACK;
+ int ret, val;
+
+ if ((phydev->speed != SPEED_10) && (phydev->speed != SPEED_100))
+ phydev->speed = SPEED_1000;
+ phydev->duplex = DUPLEX_FULL;
+
+ ctl |= mii_bmcr_encode_fixed(phydev->speed, phydev->duplex);
+
+ phy_modify(phydev, MII_BMCR, ~0, ctl);
+
+ ret = phy_read_poll_timeout(phydev, MII_BMSR, val,
+ val & BMSR_LSTATUS, 5000, 500000,
+ true);
+ if (ret)
+ return ret;
+ } else {
+ return genphy_loopback(phydev, enable);
+ }
+
+ 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,
@@ -5478,6 +5504,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.2
Powered by blists - more mailing lists