Skip to content

Commit f0417e0

Browse files
author
Paolo Abeni
committed
Merge branch 'support-loopback-mode-speed-selection'
Gerhard Engleder says: ==================== Support loopback mode speed selection Previously to commit 6ff3cdd ("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. ==================== Link: https://patch.msgid.link/[email protected] Signed-off-by: Paolo Abeni <[email protected]>
2 parents 3d97da0 + 163d744 commit f0417e0

File tree

16 files changed

+209
-107
lines changed

16 files changed

+209
-107
lines changed

drivers/net/ethernet/engleder/tsnep_main.c

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -221,20 +221,19 @@ static void tsnep_phy_link_status_change(struct net_device *netdev)
221221

222222
static int tsnep_phy_loopback(struct tsnep_adapter *adapter, bool enable)
223223
{
224-
int retval;
225-
226-
retval = phy_loopback(adapter->phydev, enable);
224+
int speed;
227225

228-
/* PHY link state change is not signaled if loopback is enabled, it
229-
* would delay a working loopback anyway, let's ensure that loopback
230-
* is working immediately by setting link mode directly
231-
*/
232-
if (!retval && enable) {
233-
netif_carrier_on(adapter->netdev);
234-
tsnep_set_link_mode(adapter);
226+
if (enable) {
227+
if (adapter->phydev->autoneg == AUTONEG_DISABLE &&
228+
adapter->phydev->speed == SPEED_100)
229+
speed = SPEED_100;
230+
else
231+
speed = SPEED_1000;
232+
} else {
233+
speed = 0;
235234
}
236235

237-
return retval;
236+
return phy_loopback(adapter->phydev, enable, speed);
238237
}
239238

240239
static int tsnep_phy_open(struct tsnep_adapter *adapter)

drivers/net/ethernet/hisilicon/hns/hns_ethtool.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -266,9 +266,9 @@ static int hns_nic_config_phy_loopback(struct phy_device *phy_dev, u8 en)
266266
if (err)
267267
goto out;
268268

269-
err = phy_loopback(phy_dev, true);
269+
err = phy_loopback(phy_dev, true, 0);
270270
} else {
271-
err = phy_loopback(phy_dev, false);
271+
err = phy_loopback(phy_dev, false, 0);
272272
if (err)
273273
goto out;
274274

drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7875,15 +7875,15 @@ static int hclge_enable_phy_loopback(struct hclge_dev *hdev,
78757875
if (ret)
78767876
return ret;
78777877

7878-
return phy_loopback(phydev, true);
7878+
return phy_loopback(phydev, true, 0);
78797879
}
78807880

78817881
static int hclge_disable_phy_loopback(struct hclge_dev *hdev,
78827882
struct phy_device *phydev)
78837883
{
78847884
int ret;
78857885

7886-
ret = phy_loopback(phydev, false);
7886+
ret = phy_loopback(phydev, false, 0);
78877887
if (ret)
78887888
return ret;
78897889

drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_mdio.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ void hclge_mac_start_phy(struct hclge_dev *hdev)
258258
if (!phydev)
259259
return;
260260

261-
phy_loopback(phydev, false);
261+
phy_loopback(phydev, false, 0);
262262

263263
phy_start(phydev);
264264
}

drivers/net/ethernet/stmicro/stmmac/stmmac_selftests.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -382,14 +382,14 @@ static int stmmac_test_phy_loopback(struct stmmac_priv *priv)
382382
if (!priv->dev->phydev)
383383
return -EOPNOTSUPP;
384384

385-
ret = phy_loopback(priv->dev->phydev, true);
385+
ret = phy_loopback(priv->dev->phydev, true, 0);
386386
if (ret)
387387
return ret;
388388

389389
attr.dst = priv->dev->dev_addr;
390390
ret = __stmmac_test_loopback(priv, &attr);
391391

392-
phy_loopback(priv->dev->phydev, false);
392+
phy_loopback(priv->dev->phydev, false, 0);
393393
return ret;
394394
}
395395

@@ -1985,7 +1985,7 @@ void stmmac_selftest_run(struct net_device *dev,
19851985
case STMMAC_LOOPBACK_PHY:
19861986
ret = -EOPNOTSUPP;
19871987
if (dev->phydev)
1988-
ret = phy_loopback(dev->phydev, true);
1988+
ret = phy_loopback(dev->phydev, true, 0);
19891989
if (!ret)
19901990
break;
19911991
fallthrough;
@@ -2018,7 +2018,7 @@ void stmmac_selftest_run(struct net_device *dev,
20182018
case STMMAC_LOOPBACK_PHY:
20192019
ret = -EOPNOTSUPP;
20202020
if (dev->phydev)
2021-
ret = phy_loopback(dev->phydev, false);
2021+
ret = phy_loopback(dev->phydev, false, 0);
20222022
if (!ret)
20232023
break;
20242024
fallthrough;

drivers/net/phy/adin1100.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -215,8 +215,11 @@ static int adin_resume(struct phy_device *phydev)
215215
return adin_set_powerdown_mode(phydev, false);
216216
}
217217

218-
static int adin_set_loopback(struct phy_device *phydev, bool enable)
218+
static int adin_set_loopback(struct phy_device *phydev, bool enable, int speed)
219219
{
220+
if (enable && speed)
221+
return -EOPNOTSUPP;
222+
220223
if (enable)
221224
return phy_set_bits_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_10T1L_CTRL,
222225
BMCR_LOOPBACK);

drivers/net/phy/dp83867.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1009,8 +1009,11 @@ static void dp83867_link_change_notify(struct phy_device *phydev)
10091009
}
10101010
}
10111011

1012-
static int dp83867_loopback(struct phy_device *phydev, bool enable)
1012+
static int dp83867_loopback(struct phy_device *phydev, bool enable, int speed)
10131013
{
1014+
if (enable && speed)
1015+
return -EOPNOTSUPP;
1016+
10141017
return phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK,
10151018
enable ? BMCR_LOOPBACK : 0);
10161019
}

drivers/net/phy/marvell.c

Lines changed: 34 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -2131,52 +2131,52 @@ static void marvell_get_stats_simple(struct phy_device *phydev,
21312131
data[i] = marvell_get_stat_simple(phydev, i);
21322132
}
21332133

2134-
static int m88e1510_loopback(struct phy_device *phydev, bool enable)
2134+
static int m88e1510_loopback(struct phy_device *phydev, bool enable, int speed)
21352135
{
2136+
u16 bmcr_ctl, mscr2_ctl = 0;
21362137
int err;
21372138

2138-
if (enable) {
2139-
u16 bmcr_ctl, mscr2_ctl = 0;
2139+
if (!enable)
2140+
return genphy_loopback(phydev, enable, 0);
21402141

2141-
bmcr_ctl = mii_bmcr_encode_fixed(phydev->speed, phydev->duplex);
2142-
2143-
err = phy_write(phydev, MII_BMCR, bmcr_ctl);
2144-
if (err < 0)
2145-
return err;
2142+
if (speed == SPEED_10 || speed == SPEED_100 || speed == SPEED_1000)
2143+
phydev->speed = speed;
2144+
else if (speed)
2145+
return -EINVAL;
21462146

2147-
if (phydev->speed == SPEED_1000)
2148-
mscr2_ctl = BMCR_SPEED1000;
2149-
else if (phydev->speed == SPEED_100)
2150-
mscr2_ctl = BMCR_SPEED100;
2147+
bmcr_ctl = mii_bmcr_encode_fixed(phydev->speed, phydev->duplex);
21512148

2152-
err = phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE,
2153-
MII_88E1510_MSCR_2, BMCR_SPEED1000 |
2154-
BMCR_SPEED100, mscr2_ctl);
2155-
if (err < 0)
2156-
return err;
2149+
err = phy_write(phydev, MII_BMCR, bmcr_ctl);
2150+
if (err < 0)
2151+
return err;
21572152

2158-
/* Need soft reset to have speed configuration takes effect */
2159-
err = genphy_soft_reset(phydev);
2160-
if (err < 0)
2161-
return err;
2153+
if (phydev->speed == SPEED_1000)
2154+
mscr2_ctl = BMCR_SPEED1000;
2155+
else if (phydev->speed == SPEED_100)
2156+
mscr2_ctl = BMCR_SPEED100;
21622157

2163-
err = phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK,
2164-
BMCR_LOOPBACK);
2158+
err = phy_modify_paged(phydev, MII_MARVELL_MSCR_PAGE,
2159+
MII_88E1510_MSCR_2, BMCR_SPEED1000 |
2160+
BMCR_SPEED100, mscr2_ctl);
2161+
if (err < 0)
2162+
return err;
21652163

2166-
if (!err) {
2167-
/* It takes some time for PHY device to switch
2168-
* into/out-of loopback mode.
2169-
*/
2170-
msleep(1000);
2171-
}
2164+
/* Need soft reset to have speed configuration takes effect */
2165+
err = genphy_soft_reset(phydev);
2166+
if (err < 0)
21722167
return err;
2173-
} else {
2174-
err = phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK, 0);
2175-
if (err < 0)
2176-
return err;
21772168

2178-
return phy_config_aneg(phydev);
2169+
err = phy_modify(phydev, MII_BMCR, BMCR_LOOPBACK,
2170+
BMCR_LOOPBACK);
2171+
2172+
if (!err) {
2173+
/*
2174+
* It takes some time for PHY device to switch into loopback
2175+
* mode.
2176+
*/
2177+
msleep(1000);
21792178
}
2179+
return err;
21802180
}
21812181

21822182
static int marvell_vct5_wait_complete(struct phy_device *phydev)

drivers/net/phy/micrel.c

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,29 @@ static int ksz9021_config_init(struct phy_device *phydev)
10321032
#define MII_KSZ9031RN_EDPD 0x23
10331033
#define MII_KSZ9031RN_EDPD_ENABLE BIT(0)
10341034

1035+
static int ksz9031_set_loopback(struct phy_device *phydev, bool enable,
1036+
int speed)
1037+
{
1038+
u16 ctl = BMCR_LOOPBACK;
1039+
int val;
1040+
1041+
if (!enable)
1042+
return genphy_loopback(phydev, enable, 0);
1043+
1044+
if (speed == SPEED_10 || speed == SPEED_100 || speed == SPEED_1000)
1045+
phydev->speed = speed;
1046+
else if (speed)
1047+
return -EINVAL;
1048+
phydev->duplex = DUPLEX_FULL;
1049+
1050+
ctl |= mii_bmcr_encode_fixed(phydev->speed, phydev->duplex);
1051+
1052+
phy_write(phydev, MII_BMCR, ctl);
1053+
1054+
return phy_read_poll_timeout(phydev, MII_BMSR, val, val & BMSR_LSTATUS,
1055+
5000, 500000, true);
1056+
}
1057+
10351058
static int ksz9031_of_load_skew_values(struct phy_device *phydev,
10361059
const struct device_node *of_node,
10371060
u16 reg, size_t field_sz,
@@ -5565,6 +5588,7 @@ static struct phy_driver ksphy_driver[] = {
55655588
.resume = kszphy_resume,
55665589
.cable_test_start = ksz9x31_cable_test_start,
55675590
.cable_test_get_status = ksz9x31_cable_test_get_status,
5591+
.set_loopback = ksz9031_set_loopback,
55685592
}, {
55695593
.phy_id = PHY_ID_LAN8814,
55705594
.phy_id_mask = MICREL_PHY_ID_MASK,

drivers/net/phy/mxl-gpy.c

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -813,7 +813,7 @@ static void gpy_get_wol(struct phy_device *phydev,
813813
wol->wolopts = priv->wolopts;
814814
}
815815

816-
static int gpy_loopback(struct phy_device *phydev, bool enable)
816+
static int gpy_loopback(struct phy_device *phydev, bool enable, int speed)
817817
{
818818
struct gpy_priv *priv = phydev->priv;
819819
u16 set = 0;
@@ -822,6 +822,9 @@ static int gpy_loopback(struct phy_device *phydev, bool enable)
822822
if (enable) {
823823
u64 now = get_jiffies_64();
824824

825+
if (speed)
826+
return -EOPNOTSUPP;
827+
825828
/* wait until 3 seconds from last disable */
826829
if (time_before64(now, priv->lb_dis_to))
827830
msleep(jiffies64_to_msecs(priv->lb_dis_to - now));
@@ -845,15 +848,15 @@ static int gpy_loopback(struct phy_device *phydev, bool enable)
845848
return 0;
846849
}
847850

848-
static int gpy115_loopback(struct phy_device *phydev, bool enable)
851+
static int gpy115_loopback(struct phy_device *phydev, bool enable, int speed)
849852
{
850853
struct gpy_priv *priv = phydev->priv;
851854

852855
if (enable)
853-
return gpy_loopback(phydev, enable);
856+
return gpy_loopback(phydev, enable, speed);
854857

855858
if (priv->fw_minor > 0x76)
856-
return gpy_loopback(phydev, 0);
859+
return gpy_loopback(phydev, 0, 0);
857860

858861
return genphy_soft_reset(phydev);
859862
}

drivers/net/phy/phy-c45.c

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1228,8 +1228,11 @@ int gen10g_config_aneg(struct phy_device *phydev)
12281228
}
12291229
EXPORT_SYMBOL_GPL(gen10g_config_aneg);
12301230

1231-
int genphy_c45_loopback(struct phy_device *phydev, bool enable)
1231+
int genphy_c45_loopback(struct phy_device *phydev, bool enable, int speed)
12321232
{
1233+
if (enable && speed)
1234+
return -EOPNOTSUPP;
1235+
12331236
return phy_modify_mmd(phydev, MDIO_MMD_PCS, MDIO_CTRL1,
12341237
MDIO_PCS_CTRL1_LOOPBACK,
12351238
enable ? MDIO_PCS_CTRL1_LOOPBACK : 0);

0 commit comments

Comments
 (0)