From 5be9a27de30e6ee5b108f9c4b02def0ecda9f9dc Mon Sep 17 00:00:00 2001 From: Russell King Date: Tue, 9 May 2017 16:54:48 +0100 Subject: 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 --- drivers/net/phy/phylink.c | 144 +++++++++++++++++----------------------------- 1 file 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 #include #include +#include #include #include @@ -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; } -- cgit