Skip to content

Commit

Permalink
bnxt_en: Don't use rtnl lock to protect link change logic in workqueue.
Browse files Browse the repository at this point in the history
As a further improvement to the PF/VF link change logic, use a private
mutex instead of the rtnl lock to protect link change logic.  With the
new mutex, we don't have to take the rtnl lock in the workqueue when
we have to handle link related functions.  If the VF and PF drivers
are running on the same host and both take the rtnl lock and one is
waiting for the other, it will cause timeout.  This patch fixes these
timeouts.

Fixes: 90c694b ("bnxt_en: Fix RTNL lock usage on bnxt_update_link().")
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Michael Chan authored and davem330 committed Oct 15, 2017
1 parent c213eae commit e2dc9b6
Show file tree
Hide file tree
Showing 3 changed files with 21 additions and 12 deletions.
25 changes: 13 additions & 12 deletions drivers/net/ethernet/broadcom/bnxt/bnxt.c
Expand Up @@ -6345,7 +6345,9 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
}

if (link_re_init) {
mutex_lock(&bp->link_lock);
rc = bnxt_update_phy_setting(bp);
mutex_unlock(&bp->link_lock);
if (rc)
netdev_warn(bp->dev, "failed to update phy settings\n");
}
Expand Down Expand Up @@ -7043,30 +7045,28 @@ static void bnxt_sp_task(struct work_struct *work)
if (test_and_clear_bit(BNXT_PERIODIC_STATS_SP_EVENT, &bp->sp_event))
bnxt_hwrm_port_qstats(bp);

/* These functions below will clear BNXT_STATE_IN_SP_TASK. They
* must be the last functions to be called before exiting.
*/
if (test_and_clear_bit(BNXT_LINK_CHNG_SP_EVENT, &bp->sp_event)) {
int rc = 0;
int rc;

mutex_lock(&bp->link_lock);
if (test_and_clear_bit(BNXT_LINK_SPEED_CHNG_SP_EVENT,
&bp->sp_event))
bnxt_hwrm_phy_qcaps(bp);

bnxt_rtnl_lock_sp(bp);
if (test_bit(BNXT_STATE_OPEN, &bp->state))
rc = bnxt_update_link(bp, true);
bnxt_rtnl_unlock_sp(bp);
rc = bnxt_update_link(bp, true);
mutex_unlock(&bp->link_lock);
if (rc)
netdev_err(bp->dev, "SP task can't update link (rc: %x)\n",
rc);
}
if (test_and_clear_bit(BNXT_HWRM_PORT_MODULE_SP_EVENT, &bp->sp_event)) {
bnxt_rtnl_lock_sp(bp);
if (test_bit(BNXT_STATE_OPEN, &bp->state))
bnxt_get_port_module_status(bp);
bnxt_rtnl_unlock_sp(bp);
mutex_lock(&bp->link_lock);
bnxt_get_port_module_status(bp);
mutex_unlock(&bp->link_lock);
}
/* These functions below will clear BNXT_STATE_IN_SP_TASK. They
* must be the last functions to be called before exiting.
*/
if (test_and_clear_bit(BNXT_RESET_TASK_SP_EVENT, &bp->sp_event))
bnxt_reset(bp, false);

Expand Down Expand Up @@ -7766,6 +7766,7 @@ static int bnxt_probe_phy(struct bnxt *bp)
rc);
return rc;
}
mutex_init(&bp->link_lock);

rc = bnxt_update_link(bp, false);
if (rc) {
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/broadcom/bnxt/bnxt.h
Expand Up @@ -1290,6 +1290,10 @@ struct bnxt {
unsigned long *ntp_fltr_bmap;
int ntp_fltr_count;

/* To protect link related settings during link changes and
* ethtool settings changes.
*/
struct mutex link_lock;
struct bnxt_link_info link_info;
struct ethtool_eee eee;
u32 lpi_tmr_lo;
Expand Down
4 changes: 4 additions & 0 deletions drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c
Expand Up @@ -1052,6 +1052,7 @@ static int bnxt_get_link_ksettings(struct net_device *dev,
u32 ethtool_speed;

ethtool_link_ksettings_zero_link_mode(lk_ksettings, supported);
mutex_lock(&bp->link_lock);
bnxt_fw_to_ethtool_support_spds(link_info, lk_ksettings);

ethtool_link_ksettings_zero_link_mode(lk_ksettings, advertising);
Expand Down Expand Up @@ -1099,6 +1100,7 @@ static int bnxt_get_link_ksettings(struct net_device *dev,
base->port = PORT_FIBRE;
}
base->phy_address = link_info->phy_addr;
mutex_unlock(&bp->link_lock);

return 0;
}
Expand Down Expand Up @@ -1190,6 +1192,7 @@ static int bnxt_set_link_ksettings(struct net_device *dev,
if (!BNXT_SINGLE_PF(bp))
return -EOPNOTSUPP;

mutex_lock(&bp->link_lock);
if (base->autoneg == AUTONEG_ENABLE) {
BNXT_ETHTOOL_TO_FW_SPDS(fw_advertising, lk_ksettings,
advertising);
Expand Down Expand Up @@ -1234,6 +1237,7 @@ static int bnxt_set_link_ksettings(struct net_device *dev,
rc = bnxt_hwrm_set_link_setting(bp, set_pause, false);

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

Expand Down

0 comments on commit e2dc9b6

Please sign in to comment.