summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@armlinux.org.uk>2017-05-09 16:54:48 +0100
committerRussell King <rmk+kernel@armlinux.org.uk>2017-05-09 18:08:27 +0100
commit5be9a27de30e6ee5b108f9c4b02def0ecda9f9dc (patch)
treee76435df5a7347d8fc71c5346958d65564dcaf8c
parentb782030fcf3e0fd790f0972a439d4431a2fa0224 (diff)
phylink: switch to relying on rtnetlink lock
Switch to relying on the rtnetlink lock rather than our private config mutex to ensure proper locking. Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
-rw-r--r--drivers/net/phy/phylink.c144
1 files changed, 52 insertions, 92 deletions
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index bc1f2e63d541..f180b947d090 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -18,6 +18,7 @@
#include <linux/phy.h>
#include <linux/phy_fixed.h>
#include <linux/phylink.h>
+#include <linux/rtnetlink.h>
#include <linux/spinlock.h>
#include <linux/workqueue.h>
@@ -42,7 +43,6 @@ struct phylink {
struct list_head node;
struct net_device *netdev;
const struct phylink_mac_ops *ops;
- struct mutex config_mutex;
unsigned long phylink_disable_state; /* bitmask of disables */
struct phy_device *phydev;
@@ -56,7 +56,7 @@ struct phylink {
struct phylink_link_state link_config;
struct gpio_desc *link_gpio;
- struct mutex state_mutex; /* may be taken within config_mutex */
+ struct mutex state_mutex;
struct phylink_link_state phy_state;
struct work_struct resolve;
@@ -463,7 +463,6 @@ struct phylink *phylink_create(struct net_device *ndev, struct device_node *np,
return ERR_PTR(-ENOMEM);
mutex_init(&pl->state_mutex);
- mutex_init(&pl->config_mutex);
INIT_WORK(&pl->resolve, phylink_resolve);
pl->netdev = ndev;
pl->phy_state.interface = iface;
@@ -548,7 +547,6 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy)
if (ret)
return ret;
- mutex_lock(&pl->config_mutex);
phy->phylink = pl;
phy->phy_link_change = phylink_phy_change;
@@ -576,8 +574,6 @@ static int phylink_bringup_phy(struct phylink *pl, struct phy_device *phy)
if (phy->irq > 0)
phy_start_interrupts(phy);
- mutex_unlock(&pl->config_mutex);
-
return 0;
}
@@ -640,7 +636,8 @@ void phylink_disconnect_phy(struct phylink *pl)
{
struct phy_device *phy;
- mutex_lock(&pl->config_mutex);
+ WARN_ON(!lockdep_rtnl_is_held());
+
phy = pl->phydev;
mutex_lock(&pl->state_mutex);
@@ -650,8 +647,6 @@ void phylink_disconnect_phy(struct phylink *pl)
if (phy)
phy_disconnect(phy);
-
- mutex_unlock(&pl->config_mutex);
}
EXPORT_SYMBOL_GPL(phylink_disconnect_phy);
@@ -666,7 +661,7 @@ EXPORT_SYMBOL_GPL(phylink_mac_change);
void phylink_start(struct phylink *pl)
{
- mutex_lock(&pl->config_mutex);
+ WARN_ON(!lockdep_rtnl_is_held());
netdev_info(pl->netdev, "configuring for %s link mode\n",
phylink_an_mode_str(pl->link_an_mode));
@@ -683,34 +678,30 @@ void phylink_start(struct phylink *pl)
if (pl->phydev)
phy_start(pl->phydev);
-
- mutex_unlock(&pl->config_mutex);
}
EXPORT_SYMBOL_GPL(phylink_start);
void phylink_stop(struct phylink *pl)
{
- mutex_lock(&pl->config_mutex);
+ WARN_ON(!lockdep_rtnl_is_held());
if (pl->phydev)
phy_stop(pl->phydev);
set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
flush_work(&pl->resolve);
-
- mutex_unlock(&pl->config_mutex);
}
EXPORT_SYMBOL_GPL(phylink_stop);
void phylink_ethtool_get_wol(struct phylink *pl, struct ethtool_wolinfo *wol)
{
+ WARN_ON(!lockdep_rtnl_is_held());
+
wol->supported = 0;
wol->wolopts = 0;
- mutex_lock(&pl->config_mutex);
if (pl->phydev)
phy_ethtool_get_wol(pl->phydev, wol);
- mutex_unlock(&pl->config_mutex);
}
EXPORT_SYMBOL_GPL(phylink_ethtool_get_wol);
@@ -718,10 +709,10 @@ int phylink_ethtool_set_wol(struct phylink *pl, struct ethtool_wolinfo *wol)
{
int ret = -EOPNOTSUPP;
- mutex_lock(&pl->config_mutex);
+ WARN_ON(!lockdep_rtnl_is_held());
+
if (pl->phydev)
ret = phy_ethtool_set_wol(pl->phydev, wol);
- mutex_unlock(&pl->config_mutex);
return ret;
}
@@ -749,12 +740,14 @@ static void phylink_get_ksettings(const struct phylink_link_state *state,
AUTONEG_DISABLE;
}
-static int __phylink_ethtool_ksettings_get(struct phylink *pl,
- struct ethtool_link_ksettings *kset)
+int phylink_ethtool_ksettings_get(struct phylink *pl,
+ struct ethtool_link_ksettings *kset)
{
struct phylink_link_state link_state;
int ret;
+ WARN_ON(!lockdep_rtnl_is_held());
+
if (pl->phydev) {
ret = phy_ethtool_ksettings_get(pl->phydev, kset);
if (ret)
@@ -795,26 +788,20 @@ static int __phylink_ethtool_ksettings_get(struct phylink *pl,
return 0;
}
-
-int phylink_ethtool_ksettings_get(struct phylink *pl,
- struct ethtool_link_ksettings *kset)
-{
- int ret;
-
- mutex_lock(&pl->config_mutex);
- ret = __phylink_ethtool_ksettings_get(pl, kset);
- mutex_unlock(&pl->config_mutex);
-
- return ret;
-}
EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_get);
-static int __phylink_ethtool_ksettings_set(struct phylink *pl,
- const struct ethtool_link_ksettings *kset)
+int phylink_ethtool_ksettings_set(struct phylink *pl,
+ const struct ethtool_link_ksettings *kset)
{
struct ethtool_link_ksettings our_kset = *kset;
int ret;
+ WARN_ON(!lockdep_rtnl_is_held());
+
+ if (kset->base.autoneg != AUTONEG_DISABLE &&
+ kset->base.autoneg != AUTONEG_ENABLE)
+ return -EINVAL;
+
/* Mask out unsupported advertisments */
linkmode_and(our_kset.link_modes.advertising,
kset->link_modes.advertising, pl->supported);
@@ -886,33 +873,17 @@ static int __phylink_ethtool_ksettings_set(struct phylink *pl,
return ret;
}
-
-int phylink_ethtool_ksettings_set(struct phylink *pl,
- const struct ethtool_link_ksettings *kset)
-{
- int ret;
-
- if (kset->base.autoneg != AUTONEG_DISABLE &&
- kset->base.autoneg != AUTONEG_ENABLE)
- return -EINVAL;
-
- mutex_lock(&pl->config_mutex);
- ret = __phylink_ethtool_ksettings_set(pl, kset);
- mutex_unlock(&pl->config_mutex);
-
- return ret;
-}
EXPORT_SYMBOL_GPL(phylink_ethtool_ksettings_set);
int phylink_ethtool_nway_reset(struct phylink *pl)
{
int ret = 0;
- mutex_lock(&pl->config_mutex);
+ WARN_ON(!lockdep_rtnl_is_held());
+
if (pl->phydev)
ret = phy_restart_aneg(pl->phydev);
phylink_mac_an_restart(pl);
- mutex_unlock(&pl->config_mutex);
return ret;
}
@@ -921,21 +892,21 @@ EXPORT_SYMBOL_GPL(phylink_ethtool_nway_reset);
void phylink_ethtool_get_pauseparam(struct phylink *pl,
struct ethtool_pauseparam *pause)
{
- mutex_lock(&pl->config_mutex);
+ WARN_ON(!lockdep_rtnl_is_held());
pause->autoneg = !!(pl->link_config.pause & MLO_PAUSE_AN);
pause->rx_pause = !!(pl->link_config.pause & MLO_PAUSE_RX);
pause->tx_pause = !!(pl->link_config.pause & MLO_PAUSE_TX);
-
- mutex_unlock(&pl->config_mutex);
}
EXPORT_SYMBOL_GPL(phylink_ethtool_get_pauseparam);
-static int __phylink_ethtool_set_pauseparam(struct phylink *pl,
- struct ethtool_pauseparam *pause)
+int phylink_ethtool_set_pauseparam(struct phylink *pl,
+ struct ethtool_pauseparam *pause)
{
struct phylink_link_state *config = &pl->link_config;
+ WARN_ON(!lockdep_rtnl_is_held());
+
if (!phylink_test(pl->supported, Pause) &&
!phylink_test(pl->supported, Asym_Pause))
return -EOPNOTSUPP;
@@ -977,18 +948,6 @@ static int __phylink_ethtool_set_pauseparam(struct phylink *pl,
return 0;
}
-
-int phylink_ethtool_set_pauseparam(struct phylink *pl,
- struct ethtool_pauseparam *pause)
-{
- int ret;
-
- mutex_lock(&pl->config_mutex);
- ret = __phylink_ethtool_set_pauseparam(pl, pause);
- mutex_unlock(&pl->config_mutex);
-
- return ret;
-}
EXPORT_SYMBOL_GPL(phylink_ethtool_set_pauseparam);
int phylink_ethtool_get_module_info(struct phylink *pl,
@@ -996,12 +955,11 @@ int phylink_ethtool_get_module_info(struct phylink *pl,
{
int ret = -EOPNOTSUPP;
- mutex_lock(&pl->config_mutex);
+ WARN_ON(!lockdep_rtnl_is_held());
+
if (pl->module_ops)
ret = pl->module_ops->get_module_info(pl->module_data,
modinfo);
- mutex_unlock(&pl->config_mutex);
-
return ret;
}
EXPORT_SYMBOL_GPL(phylink_ethtool_get_module_info);
@@ -1011,11 +969,11 @@ int phylink_ethtool_get_module_eeprom(struct phylink *pl,
{
int ret = -EOPNOTSUPP;
- mutex_lock(&pl->config_mutex);
+ WARN_ON(!lockdep_rtnl_is_held());
+
if (pl->module_ops)
ret = pl->module_ops->get_module_eeprom(pl->module_data, ee,
buf);
- mutex_unlock(&pl->config_mutex);
return ret;
}
@@ -1025,10 +983,10 @@ int phylink_init_eee(struct phylink *pl, bool clk_stop_enable)
{
int ret = -EPROTONOSUPPORT;
- mutex_lock(&pl->config_mutex);
+ WARN_ON(!lockdep_rtnl_is_held());
+
if (pl->phydev)
ret = phy_init_eee(pl->phydev, clk_stop_enable);
- mutex_unlock(&pl->config_mutex);
return ret;
}
@@ -1038,10 +996,10 @@ int phylink_get_eee_err(struct phylink *pl)
{
int ret = 0;
- mutex_lock(&pl->config_mutex);
+ WARN_ON(!lockdep_rtnl_is_held());
+
if (pl->phydev)
ret = phy_get_eee_err(pl->phydev);
- mutex_unlock(&pl->config_mutex);
return ret;
}
@@ -1051,10 +1009,10 @@ int phylink_ethtool_get_eee(struct phylink *pl, struct ethtool_eee *eee)
{
int ret = -EOPNOTSUPP;
- mutex_lock(&pl->config_mutex);
+ WARN_ON(!lockdep_rtnl_is_held());
+
if (pl->phydev)
ret = phy_ethtool_get_eee(pl->phydev, eee);
- mutex_unlock(&pl->config_mutex);
return ret;
}
@@ -1064,10 +1022,10 @@ int phylink_ethtool_set_eee(struct phylink *pl, struct ethtool_eee *eee)
{
int ret = -EOPNOTSUPP;
- mutex_lock(&pl->config_mutex);
+ WARN_ON(!lockdep_rtnl_is_held());
+
if (pl->phydev)
ret = phy_ethtool_set_eee(pl->phydev, eee);
- mutex_unlock(&pl->config_mutex);
return ret;
}
@@ -1240,7 +1198,7 @@ int phylink_mii_ioctl(struct phylink *pl, struct ifreq *ifr, int cmd)
struct mii_ioctl_data *mii = if_mii(ifr);
int ret;
- mutex_lock(&pl->config_mutex);
+ WARN_ON(!lockdep_rtnl_is_held());
if (pl->phydev) {
/* PHYs only exist for MLO_AN_PHY and MLO_AN_SGMII */
@@ -1289,8 +1247,6 @@ int phylink_mii_ioctl(struct phylink *pl, struct ifreq *ifr, int cmd)
}
}
- mutex_unlock(&pl->config_mutex);
-
return ret;
}
EXPORT_SYMBOL_GPL(phylink_mii_ioctl);
@@ -1302,13 +1258,13 @@ int phylink_register_module(struct phylink *pl, void *data,
{
int ret = -EBUSY;
- mutex_lock(&pl->config_mutex);
+ WARN_ON(!lockdep_rtnl_is_held());
+
if (!pl->module_ops) {
pl->module_ops = ops;
pl->module_data = data;
ret = 0;
}
- mutex_unlock(&pl->config_mutex);
return ret;
}
@@ -1318,13 +1274,13 @@ int phylink_unregister_module(struct phylink *pl, void *data)
{
int ret = -EINVAL;
- mutex_lock(&pl->config_mutex);
+ WARN_ON(!lockdep_rtnl_is_held());
+
if (pl->module_data == data) {
pl->module_ops = NULL;
pl->module_data = NULL;
ret = 0;
}
- mutex_unlock(&pl->config_mutex);
return ret;
}
@@ -1332,6 +1288,8 @@ EXPORT_SYMBOL_GPL(phylink_unregister_module);
void phylink_disable(struct phylink *pl)
{
+ WARN_ON(!lockdep_rtnl_is_held());
+
set_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state);
flush_work(&pl->resolve);
@@ -1341,6 +1299,8 @@ EXPORT_SYMBOL_GPL(phylink_disable);
void phylink_enable(struct phylink *pl)
{
+ WARN_ON(!lockdep_rtnl_is_held());
+
clear_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state);
phylink_run_resolve(pl);
}
@@ -1352,6 +1312,8 @@ int phylink_set_link(struct phylink *pl, unsigned int mode, u8 port,
__ETHTOOL_DECLARE_LINK_MODE_MASK(mask);
int ret = 0;
+ WARN_ON(!lockdep_rtnl_is_held());
+
netdev_dbg(pl->netdev, "requesting link mode %s with support %*pb\n",
phylink_an_mode_str(mode),
__ETHTOOL_LINK_MODE_MASK_NBITS, support);
@@ -1366,7 +1328,6 @@ int phylink_set_link(struct phylink *pl, unsigned int mode, u8 port,
if (ret && mode != MLO_AN_PHY)
return ret;
- mutex_lock(&pl->config_mutex);
if (mode == MLO_AN_8023Z && pl->phydev) {
ret = -EINVAL;
} else {
@@ -1394,7 +1355,6 @@ int phylink_set_link(struct phylink *pl, unsigned int mode, u8 port,
&pl->phylink_disable_state))
phylink_mac_config(pl, &pl->link_config);
}
- mutex_unlock(&pl->config_mutex);
return ret;
}