Skip to content

Commit

Permalink
bnxt_en: Protect bnxt_set_eee() and bnxt_set_pauseparam() with mutex.
Browse files Browse the repository at this point in the history
All changes related to bp->link_info require the protection of the
link_lock mutex.  It's not sufficient to rely just on RTNL.

Fixes: 163e9ef ("bnxt_en: Fix race when modifying pause settings.")
Reviewed-by: Edwin Peer <[email protected]>
Signed-off-by: Michael Chan <[email protected]>
Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
Michael Chan authored and davem330 committed Sep 21, 2020
1 parent d69753f commit a539069
Showing 1 changed file with 20 additions and 11 deletions.
31 changes: 20 additions & 11 deletions drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
Original file line number Diff line number Diff line change
Expand Up @@ -1788,9 +1788,12 @@ static int bnxt_set_pauseparam(struct net_device *dev,
if (!BNXT_PHY_CFG_ABLE(bp))
return -EOPNOTSUPP;

mutex_lock(&bp->link_lock);
if (epause->autoneg) {
if (!(link_info->autoneg & BNXT_AUTONEG_SPEED))
return -EINVAL;
if (!(link_info->autoneg & BNXT_AUTONEG_SPEED)) {
rc = -EINVAL;
goto pause_exit;
}

link_info->autoneg |= BNXT_AUTONEG_FLOW_CTRL;
if (bp->hwrm_spec_code >= 0x10201)
Expand All @@ -1811,11 +1814,11 @@ static int bnxt_set_pauseparam(struct net_device *dev,
if (epause->tx_pause)
link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_TX;

if (netif_running(dev)) {
mutex_lock(&bp->link_lock);
if (netif_running(dev))
rc = bnxt_hwrm_set_pause(bp);
mutex_unlock(&bp->link_lock);
}

pause_exit:
mutex_unlock(&bp->link_lock);
return rc;
}

Expand Down Expand Up @@ -2552,8 +2555,7 @@ static int bnxt_set_eee(struct net_device *dev, struct ethtool_eee *edata)
struct bnxt *bp = netdev_priv(dev);
struct ethtool_eee *eee = &bp->eee;
struct bnxt_link_info *link_info = &bp->link_info;
u32 advertising =
_bnxt_fw_to_ethtool_adv_spds(link_info->advertising, 0);
u32 advertising;
int rc = 0;

if (!BNXT_PHY_CFG_ABLE(bp))
Expand All @@ -2562,19 +2564,23 @@ static int bnxt_set_eee(struct net_device *dev, struct ethtool_eee *edata)
if (!(bp->flags & BNXT_FLAG_EEE_CAP))
return -EOPNOTSUPP;

mutex_lock(&bp->link_lock);
advertising = _bnxt_fw_to_ethtool_adv_spds(link_info->advertising, 0);
if (!edata->eee_enabled)
goto eee_ok;

if (!(link_info->autoneg & BNXT_AUTONEG_SPEED)) {
netdev_warn(dev, "EEE requires autoneg\n");
return -EINVAL;
rc = -EINVAL;
goto eee_exit;
}
if (edata->tx_lpi_enabled) {
if (bp->lpi_tmr_hi && (edata->tx_lpi_timer > bp->lpi_tmr_hi ||
edata->tx_lpi_timer < bp->lpi_tmr_lo)) {
netdev_warn(dev, "Valid LPI timer range is %d and %d microsecs\n",
bp->lpi_tmr_lo, bp->lpi_tmr_hi);
return -EINVAL;
rc = -EINVAL;
goto eee_exit;
} else if (!bp->lpi_tmr_hi) {
edata->tx_lpi_timer = eee->tx_lpi_timer;
}
Expand All @@ -2584,7 +2590,8 @@ static int bnxt_set_eee(struct net_device *dev, struct ethtool_eee *edata)
} else if (edata->advertised & ~advertising) {
netdev_warn(dev, "EEE advertised %x must be a subset of autoneg advertised speeds %x\n",
edata->advertised, advertising);
return -EINVAL;
rc = -EINVAL;
goto eee_exit;
}

eee->advertised = edata->advertised;
Expand All @@ -2596,6 +2603,8 @@ static int bnxt_set_eee(struct net_device *dev, struct ethtool_eee *edata)
if (netif_running(dev))
rc = bnxt_hwrm_set_link_setting(bp, false, true);

eee_exit:
mutex_unlock(&bp->link_lock);
return rc;
}

Expand Down

0 comments on commit a539069

Please sign in to comment.