Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f029a2b authored by Michael Chan's avatar Michael Chan Committed by Greg Kroah-Hartman
Browse files

bnxt_en: Protect bnxt_set_eee() and bnxt_set_pauseparam() with mutex.



[ Upstream commit a53906908148d64423398a62c4435efb0d09652c ]

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: 163e9ef63641 ("bnxt_en: Fix race when modifying pause settings.")
Reviewed-by: default avatarEdwin Peer <edwin.peer@broadcom.com>
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 0faf2aa5
Loading
Loading
Loading
Loading
+20 −11
Original line number Diff line number Diff line
@@ -1000,9 +1000,12 @@ static int bnxt_set_pauseparam(struct net_device *dev,
	if (!BNXT_SINGLE_PF(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)
@@ -1023,11 +1026,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);

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

@@ -1671,8 +1674,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_SINGLE_PF(bp))
@@ -1681,19 +1683,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;
		}
@@ -1703,7 +1709,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;
@@ -1715,6 +1722,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;
}