Skip to content

Commit 2f987d4

Browse files
lunndavem330
authored andcommitted
net: phy: Add locks to ethtool functions
The phydev lock should be held while accessing members of phydev, or calling into the driver. Signed-off-by: Andrew Lunn <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 3365777 commit 2f987d4

File tree

1 file changed

+66
-18
lines changed

1 file changed

+66
-18
lines changed

drivers/net/phy/phy.c

Lines changed: 66 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1069,27 +1069,35 @@ EXPORT_SYMBOL(phy_ethtool_ksettings_set);
10691069
int phy_speed_down(struct phy_device *phydev, bool sync)
10701070
{
10711071
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv_tmp);
1072-
int ret;
1072+
int ret = 0;
1073+
1074+
mutex_lock(&phydev->lock);
10731075

10741076
if (phydev->autoneg != AUTONEG_ENABLE)
1075-
return 0;
1077+
goto out;
10761078

10771079
linkmode_copy(adv_tmp, phydev->advertising);
10781080

10791081
ret = phy_speed_down_core(phydev);
10801082
if (ret)
1081-
return ret;
1083+
goto out;
10821084

10831085
linkmode_copy(phydev->adv_old, adv_tmp);
10841086

1085-
if (linkmode_equal(phydev->advertising, adv_tmp))
1086-
return 0;
1087+
if (linkmode_equal(phydev->advertising, adv_tmp)) {
1088+
ret = 0;
1089+
goto out;
1090+
}
10871091

10881092
ret = phy_config_aneg(phydev);
10891093
if (ret)
1090-
return ret;
1094+
goto out;
1095+
1096+
ret = sync ? phy_poll_aneg_done(phydev) : 0;
1097+
out:
1098+
mutex_unlock(&phydev->lock);
10911099

1092-
return sync ? phy_poll_aneg_done(phydev) : 0;
1100+
return ret;
10931101
}
10941102
EXPORT_SYMBOL_GPL(phy_speed_down);
10951103

@@ -1102,21 +1110,28 @@ EXPORT_SYMBOL_GPL(phy_speed_down);
11021110
int phy_speed_up(struct phy_device *phydev)
11031111
{
11041112
__ETHTOOL_DECLARE_LINK_MODE_MASK(adv_tmp);
1113+
int ret = 0;
1114+
1115+
mutex_lock(&phydev->lock);
11051116

11061117
if (phydev->autoneg != AUTONEG_ENABLE)
1107-
return 0;
1118+
goto out;
11081119

11091120
if (linkmode_empty(phydev->adv_old))
1110-
return 0;
1121+
goto out;
11111122

11121123
linkmode_copy(adv_tmp, phydev->advertising);
11131124
linkmode_copy(phydev->advertising, phydev->adv_old);
11141125
linkmode_zero(phydev->adv_old);
11151126

11161127
if (linkmode_equal(phydev->advertising, adv_tmp))
1117-
return 0;
1128+
goto out;
1129+
1130+
ret = phy_config_aneg(phydev);
1131+
out:
1132+
mutex_unlock(&phydev->lock);
11181133

1119-
return phy_config_aneg(phydev);
1134+
return ret;
11201135
}
11211136
EXPORT_SYMBOL_GPL(phy_speed_up);
11221137

@@ -1500,10 +1515,16 @@ EXPORT_SYMBOL(phy_init_eee);
15001515
*/
15011516
int phy_get_eee_err(struct phy_device *phydev)
15021517
{
1518+
int ret;
1519+
15031520
if (!phydev->drv)
15041521
return -EIO;
15051522

1506-
return phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_WK_ERR);
1523+
mutex_lock(&phydev->lock);
1524+
ret = phy_read_mmd(phydev, MDIO_MMD_PCS, MDIO_PCS_EEE_WK_ERR);
1525+
mutex_unlock(&phydev->lock);
1526+
1527+
return ret;
15071528
}
15081529
EXPORT_SYMBOL(phy_get_eee_err);
15091530

@@ -1517,10 +1538,16 @@ EXPORT_SYMBOL(phy_get_eee_err);
15171538
*/
15181539
int phy_ethtool_get_eee(struct phy_device *phydev, struct ethtool_eee *data)
15191540
{
1541+
int ret;
1542+
15201543
if (!phydev->drv)
15211544
return -EIO;
15221545

1523-
return genphy_c45_ethtool_get_eee(phydev, data);
1546+
mutex_lock(&phydev->lock);
1547+
ret = genphy_c45_ethtool_get_eee(phydev, data);
1548+
mutex_unlock(&phydev->lock);
1549+
1550+
return ret;
15241551
}
15251552
EXPORT_SYMBOL(phy_ethtool_get_eee);
15261553

@@ -1533,10 +1560,16 @@ EXPORT_SYMBOL(phy_ethtool_get_eee);
15331560
*/
15341561
int phy_ethtool_set_eee(struct phy_device *phydev, struct ethtool_eee *data)
15351562
{
1563+
int ret;
1564+
15361565
if (!phydev->drv)
15371566
return -EIO;
15381567

1539-
return genphy_c45_ethtool_set_eee(phydev, data);
1568+
mutex_lock(&phydev->lock);
1569+
ret = genphy_c45_ethtool_set_eee(phydev, data);
1570+
mutex_unlock(&phydev->lock);
1571+
1572+
return ret;
15401573
}
15411574
EXPORT_SYMBOL(phy_ethtool_set_eee);
15421575

@@ -1548,8 +1581,15 @@ EXPORT_SYMBOL(phy_ethtool_set_eee);
15481581
*/
15491582
int phy_ethtool_set_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
15501583
{
1551-
if (phydev->drv && phydev->drv->set_wol)
1552-
return phydev->drv->set_wol(phydev, wol);
1584+
int ret;
1585+
1586+
if (phydev->drv && phydev->drv->set_wol) {
1587+
mutex_lock(&phydev->lock);
1588+
ret = phydev->drv->set_wol(phydev, wol);
1589+
mutex_unlock(&phydev->lock);
1590+
1591+
return ret;
1592+
}
15531593

15541594
return -EOPNOTSUPP;
15551595
}
@@ -1563,8 +1603,11 @@ EXPORT_SYMBOL(phy_ethtool_set_wol);
15631603
*/
15641604
void phy_ethtool_get_wol(struct phy_device *phydev, struct ethtool_wolinfo *wol)
15651605
{
1566-
if (phydev->drv && phydev->drv->get_wol)
1606+
if (phydev->drv && phydev->drv->get_wol) {
1607+
mutex_lock(&phydev->lock);
15671608
phydev->drv->get_wol(phydev, wol);
1609+
mutex_unlock(&phydev->lock);
1610+
}
15681611
}
15691612
EXPORT_SYMBOL(phy_ethtool_get_wol);
15701613

@@ -1601,13 +1644,18 @@ EXPORT_SYMBOL(phy_ethtool_set_link_ksettings);
16011644
int phy_ethtool_nway_reset(struct net_device *ndev)
16021645
{
16031646
struct phy_device *phydev = ndev->phydev;
1647+
int ret;
16041648

16051649
if (!phydev)
16061650
return -ENODEV;
16071651

16081652
if (!phydev->drv)
16091653
return -EIO;
16101654

1611-
return phy_restart_aneg(phydev);
1655+
mutex_lock(&phydev->lock);
1656+
ret = phy_restart_aneg(phydev);
1657+
mutex_unlock(&phydev->lock);
1658+
1659+
return ret;
16121660
}
16131661
EXPORT_SYMBOL(phy_ethtool_nway_reset);

0 commit comments

Comments
 (0)