Commit 212f9934 authored by Michael Chan's avatar Michael Chan Committed by David S. Miller

bnx2: Prevent "scheduling while atomic" warning with cnic, bonding and vlan.

The bonding driver calls ndo_vlan_rx_register() while holding bond->lock.
The bnx2 driver calls bnx2_netif_stop() to stop the rx handling while
changing the vlgrp.  The call also stops the cnic driver which sleeps
while the bond->lock is held and cause the warning.

This code path only needs to stop the NAPI rx handling while we are
changing the vlgrp.  Since no reset is going to occur, there is no need
to stop cnic in this case.  By adding a parameter to bnx2_netif_stop()
to skip stopping cnic, we can avoid the warning.
Signed-off-by: default avatarMichael Chan <mchan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent c441b8d2
...@@ -651,9 +651,10 @@ bnx2_napi_enable(struct bnx2 *bp) ...@@ -651,9 +651,10 @@ bnx2_napi_enable(struct bnx2 *bp)
} }
static void static void
bnx2_netif_stop(struct bnx2 *bp) bnx2_netif_stop(struct bnx2 *bp, bool stop_cnic)
{ {
bnx2_cnic_stop(bp); if (stop_cnic)
bnx2_cnic_stop(bp);
if (netif_running(bp->dev)) { if (netif_running(bp->dev)) {
int i; int i;
...@@ -671,14 +672,15 @@ bnx2_netif_stop(struct bnx2 *bp) ...@@ -671,14 +672,15 @@ bnx2_netif_stop(struct bnx2 *bp)
} }
static void static void
bnx2_netif_start(struct bnx2 *bp) bnx2_netif_start(struct bnx2 *bp, bool start_cnic)
{ {
if (atomic_dec_and_test(&bp->intr_sem)) { if (atomic_dec_and_test(&bp->intr_sem)) {
if (netif_running(bp->dev)) { if (netif_running(bp->dev)) {
netif_tx_wake_all_queues(bp->dev); netif_tx_wake_all_queues(bp->dev);
bnx2_napi_enable(bp); bnx2_napi_enable(bp);
bnx2_enable_int(bp); bnx2_enable_int(bp);
bnx2_cnic_start(bp); if (start_cnic)
bnx2_cnic_start(bp);
} }
} }
} }
...@@ -6277,12 +6279,12 @@ bnx2_reset_task(struct work_struct *work) ...@@ -6277,12 +6279,12 @@ bnx2_reset_task(struct work_struct *work)
return; return;
} }
bnx2_netif_stop(bp); bnx2_netif_stop(bp, true);
bnx2_init_nic(bp, 1); bnx2_init_nic(bp, 1);
atomic_set(&bp->intr_sem, 1); atomic_set(&bp->intr_sem, 1);
bnx2_netif_start(bp); bnx2_netif_start(bp, true);
rtnl_unlock(); rtnl_unlock();
} }
...@@ -6324,7 +6326,7 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp) ...@@ -6324,7 +6326,7 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
struct bnx2 *bp = netdev_priv(dev); struct bnx2 *bp = netdev_priv(dev);
if (netif_running(dev)) if (netif_running(dev))
bnx2_netif_stop(bp); bnx2_netif_stop(bp, false);
bp->vlgrp = vlgrp; bp->vlgrp = vlgrp;
...@@ -6335,7 +6337,7 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp) ...@@ -6335,7 +6337,7 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp)
if (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN) if (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN)
bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1); bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1);
bnx2_netif_start(bp); bnx2_netif_start(bp, false);
} }
#endif #endif
...@@ -7055,9 +7057,9 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) ...@@ -7055,9 +7057,9 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal)
bp->stats_ticks &= BNX2_HC_STATS_TICKS_HC_STAT_TICKS; bp->stats_ticks &= BNX2_HC_STATS_TICKS_HC_STAT_TICKS;
if (netif_running(bp->dev)) { if (netif_running(bp->dev)) {
bnx2_netif_stop(bp); bnx2_netif_stop(bp, true);
bnx2_init_nic(bp, 0); bnx2_init_nic(bp, 0);
bnx2_netif_start(bp); bnx2_netif_start(bp, true);
} }
return 0; return 0;
...@@ -7087,7 +7089,7 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) ...@@ -7087,7 +7089,7 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
/* Reset will erase chipset stats; save them */ /* Reset will erase chipset stats; save them */
bnx2_save_stats(bp); bnx2_save_stats(bp);
bnx2_netif_stop(bp); bnx2_netif_stop(bp, true);
bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET);
bnx2_free_skbs(bp); bnx2_free_skbs(bp);
bnx2_free_mem(bp); bnx2_free_mem(bp);
...@@ -7115,7 +7117,7 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) ...@@ -7115,7 +7117,7 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx)
bnx2_setup_cnic_irq_info(bp); bnx2_setup_cnic_irq_info(bp);
mutex_unlock(&bp->cnic_lock); mutex_unlock(&bp->cnic_lock);
#endif #endif
bnx2_netif_start(bp); bnx2_netif_start(bp, true);
} }
return 0; return 0;
} }
...@@ -7368,7 +7370,7 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) ...@@ -7368,7 +7370,7 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
if (etest->flags & ETH_TEST_FL_OFFLINE) { if (etest->flags & ETH_TEST_FL_OFFLINE) {
int i; int i;
bnx2_netif_stop(bp); bnx2_netif_stop(bp, true);
bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_DIAG); bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_DIAG);
bnx2_free_skbs(bp); bnx2_free_skbs(bp);
...@@ -7387,7 +7389,7 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) ...@@ -7387,7 +7389,7 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf)
bnx2_shutdown_chip(bp); bnx2_shutdown_chip(bp);
else { else {
bnx2_init_nic(bp, 1); bnx2_init_nic(bp, 1);
bnx2_netif_start(bp); bnx2_netif_start(bp, true);
} }
/* wait for link up */ /* wait for link up */
...@@ -8381,7 +8383,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state) ...@@ -8381,7 +8383,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state)
return 0; return 0;
flush_scheduled_work(); flush_scheduled_work();
bnx2_netif_stop(bp); bnx2_netif_stop(bp, true);
netif_device_detach(dev); netif_device_detach(dev);
del_timer_sync(&bp->timer); del_timer_sync(&bp->timer);
bnx2_shutdown_chip(bp); bnx2_shutdown_chip(bp);
...@@ -8403,7 +8405,7 @@ bnx2_resume(struct pci_dev *pdev) ...@@ -8403,7 +8405,7 @@ bnx2_resume(struct pci_dev *pdev)
bnx2_set_power_state(bp, PCI_D0); bnx2_set_power_state(bp, PCI_D0);
netif_device_attach(dev); netif_device_attach(dev);
bnx2_init_nic(bp, 1); bnx2_init_nic(bp, 1);
bnx2_netif_start(bp); bnx2_netif_start(bp, true);
return 0; return 0;
} }
...@@ -8430,7 +8432,7 @@ static pci_ers_result_t bnx2_io_error_detected(struct pci_dev *pdev, ...@@ -8430,7 +8432,7 @@ static pci_ers_result_t bnx2_io_error_detected(struct pci_dev *pdev,
} }
if (netif_running(dev)) { if (netif_running(dev)) {
bnx2_netif_stop(bp); bnx2_netif_stop(bp, true);
del_timer_sync(&bp->timer); del_timer_sync(&bp->timer);
bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET); bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET);
} }
...@@ -8487,7 +8489,7 @@ static void bnx2_io_resume(struct pci_dev *pdev) ...@@ -8487,7 +8489,7 @@ static void bnx2_io_resume(struct pci_dev *pdev)
rtnl_lock(); rtnl_lock();
if (netif_running(dev)) if (netif_running(dev))
bnx2_netif_start(bp); bnx2_netif_start(bp, true);
netif_device_attach(dev); netif_device_attach(dev);
rtnl_unlock(); rtnl_unlock();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment