diff options
author | Johannes Berg <johannes@sipsolutions.net> | 2021-05-12 12:19:50 +0200 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2021-05-13 13:09:26 -0700 |
commit | 4a5fe57e775188be96359a1934501be45fe5f705 (patch) | |
tree | 7deb194ed59fdaba246ea550c62845ed9f317aba /drivers/net/ethernet/atheros/alx/ethtool.c | |
parent | 13511704f8d7591faf19fdb84f0902dff0535ccb (diff) |
alx: use fine-grained locking instead of RTNL
In the alx driver, all locking depended on the RTNL, but
that causes issues with ipconfig ("ip=..." command line)
because that waits for the netdev to have a carrier while
holding the RTNL, but the alx workers etc. require RTNL,
so the carrier won't be set until the RTNL is dropped and
can be acquired by alx workers. This causes long delays
at boot, as reported by Nikolai Zhubr.
Really the only sensible thing to do here is to not use
the RTNL for everything, but instead have fine-grained
locking for just the driver. Do that, it's not that hard.
Reported-by: Nikolai Zhubr <zhubr.2@gmail.com>
Signed-off-by: Johannes Berg <johannes@sipsolutions.net>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/atheros/alx/ethtool.c')
-rw-r--r-- | drivers/net/ethernet/atheros/alx/ethtool.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/drivers/net/ethernet/atheros/alx/ethtool.c b/drivers/net/ethernet/atheros/alx/ethtool.c index 2f4eabf652e8..f3627157a38a 100644 --- a/drivers/net/ethernet/atheros/alx/ethtool.c +++ b/drivers/net/ethernet/atheros/alx/ethtool.c @@ -163,8 +163,10 @@ static int alx_get_link_ksettings(struct net_device *netdev, } } + mutex_lock(&alx->mtx); cmd->base.speed = hw->link_speed; cmd->base.duplex = hw->duplex; + mutex_unlock(&alx->mtx); ethtool_convert_legacy_u32_to_link_mode(cmd->link_modes.supported, supported); @@ -181,8 +183,7 @@ static int alx_set_link_ksettings(struct net_device *netdev, struct alx_hw *hw = &alx->hw; u32 adv_cfg; u32 advertising; - - ASSERT_RTNL(); + int ret; ethtool_convert_link_mode_to_legacy_u32(&advertising, cmd->link_modes.advertising); @@ -200,7 +201,12 @@ static int alx_set_link_ksettings(struct net_device *netdev, } hw->adv_cfg = adv_cfg; - return alx_setup_speed_duplex(hw, adv_cfg, hw->flowctrl); + + mutex_lock(&alx->mtx); + ret = alx_setup_speed_duplex(hw, adv_cfg, hw->flowctrl); + mutex_unlock(&alx->mtx); + + return ret; } static void alx_get_pauseparam(struct net_device *netdev, @@ -209,10 +215,12 @@ static void alx_get_pauseparam(struct net_device *netdev, struct alx_priv *alx = netdev_priv(netdev); struct alx_hw *hw = &alx->hw; + mutex_lock(&alx->mtx); pause->autoneg = !!(hw->flowctrl & ALX_FC_ANEG && hw->adv_cfg & ADVERTISED_Autoneg); pause->tx_pause = !!(hw->flowctrl & ALX_FC_TX); pause->rx_pause = !!(hw->flowctrl & ALX_FC_RX); + mutex_unlock(&alx->mtx); } @@ -232,7 +240,7 @@ static int alx_set_pauseparam(struct net_device *netdev, if (pause->autoneg) fc |= ALX_FC_ANEG; - ASSERT_RTNL(); + mutex_lock(&alx->mtx); /* restart auto-neg for auto-mode */ if (hw->adv_cfg & ADVERTISED_Autoneg) { @@ -254,6 +262,7 @@ static int alx_set_pauseparam(struct net_device *netdev, alx_cfg_mac_flowcontrol(hw, fc); hw->flowctrl = fc; + mutex_unlock(&alx->mtx); return 0; } |