From 1cdb740fb40e55db75837263571ebf9f6a6a84ac Mon Sep 17 00:00:00 2001 From: Andy Gospodarek <gospo@redhat.com> Date: Thu, 8 Apr 2010 20:27:32 -0400 Subject: [PATCH] [net] bnx2: avoid restarting cnic in some contexts Message-id: <20100408202732.GT10880@gospo.rdu.redhat.com> Patchwork-id: 24056 O-Subject: [PATCH RHEL5.6] bnx2: avoid restarting cnic in some contexts Bugzilla: 554706 RH-Acked-by: David S. Miller <davem@redhat.com> This is a backport of a patch from Michael Chan at Broadcom to resolve an issue where the reset of cnic parts can cause a deadlock when the bnx2 device is a slave in a bond and that bond has a vlan associated with it. This workaround prevents the cnic parts from being reset as apparently that is not always needed. Testing has indicated that this will resolve RHBZ 554706, but it is not upstream yet and I have not heard from Michael Chan when he will post it. It is apparently important that this makes 5.5.z, so I am posting it now and have asked Michael about upstream status. I will post an update if needed. --- drivers/net/bnx2.c | 40 +++++++++++++++++++++------------------- 1 files changed, 21 insertions(+), 19 deletions(-) Signed-off-by: Jarod Wilson <jarod@redhat.com> --- drivers/net/bnx2.c | 40 +++++++++++++++++++++------------------- 1 files changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/net/bnx2.c b/drivers/net/bnx2.c index b8012ec..7dbb425 100644 --- a/drivers/net/bnx2.c +++ b/drivers/net/bnx2.c @@ -648,9 +648,10 @@ bnx2_napi_enable(struct bnx2 *bp) } 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); bnx2_disable_int_sync(bp); if (netif_running(bp->dev)) { bnx2_napi_disable(bp); @@ -660,14 +661,15 @@ bnx2_netif_stop(struct bnx2 *bp) } 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 (netif_running(bp->dev)) { netif_wake_queue(bp->dev); bnx2_napi_enable(bp); bnx2_enable_int(bp); - bnx2_cnic_start(bp); + if (start_cnic) + bnx2_cnic_start(bp); } } } @@ -6295,12 +6297,12 @@ bnx2_reset_task(void *data) return; bp->in_reset_task = 1; - bnx2_netif_stop(bp); + bnx2_netif_stop(bp, true); bnx2_init_nic(bp, 1); atomic_set(&bp->intr_sem, 1); - bnx2_netif_start(bp); + bnx2_netif_start(bp, true); bp->in_reset_task = 0; } @@ -6321,7 +6323,7 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp) struct bnx2 *bp = netdev_priv(dev); if (netif_running(dev)) - bnx2_netif_stop(bp); + bnx2_netif_stop(bp, false); bp->vlgrp = vlgrp; @@ -6332,7 +6334,7 @@ bnx2_vlan_rx_register(struct net_device *dev, struct vlan_group *vlgrp) if (bp->flags & BNX2_FLAG_CAN_KEEP_VLAN) bnx2_fw_sync(bp, BNX2_DRV_MSG_CODE_KEEP_VLAN_UPDATE, 0, 1); - bnx2_netif_start(bp); + bnx2_netif_start(bp, false); } #endif @@ -6509,7 +6511,7 @@ bnx2_close(struct net_device *dev) while (bp->in_reset_task) msleep(1); - bnx2_netif_stop(bp); + bnx2_netif_stop(bp, true); bnx2_napi_disable(bp); del_timer_sync(&bp->timer); bnx2_shutdown_chip(bp); @@ -7038,9 +7040,9 @@ bnx2_set_coalesce(struct net_device *dev, struct ethtool_coalesce *coal) bp->stats_ticks &= BNX2_HC_STATS_TICKS_HC_STAT_TICKS; if (netif_running(bp->dev)) { - bnx2_netif_stop(bp); + bnx2_netif_stop(bp, true); bnx2_init_nic(bp, 0); - bnx2_netif_start(bp); + bnx2_netif_start(bp, true); } return 0; @@ -7067,7 +7069,7 @@ static int bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) { if (netif_running(bp->dev)) { - bnx2_netif_stop(bp); + bnx2_netif_stop(bp, true); bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_RESET); bnx2_free_skbs(bp); bnx2_free_mem(bp); @@ -7088,7 +7090,7 @@ bnx2_change_ring_size(struct bnx2 *bp, u32 rx, u32 tx) dev_close(bp->dev); return rc; } - bnx2_netif_start(bp); + bnx2_netif_start(bp, true); } return 0; } @@ -7335,7 +7337,7 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) if (etest->flags & ETH_TEST_FL_OFFLINE) { int i; - bnx2_netif_stop(bp); + bnx2_netif_stop(bp, true); bnx2_reset_chip(bp, BNX2_DRV_MSG_CODE_DIAG); bnx2_free_skbs(bp); @@ -7354,7 +7356,7 @@ bnx2_self_test(struct net_device *dev, struct ethtool_test *etest, u64 *buf) bnx2_shutdown_chip(bp); else { bnx2_init_nic(bp, 1); - bnx2_netif_start(bp); + bnx2_netif_start(bp, true); } /* wait for link up */ @@ -8262,7 +8264,7 @@ bnx2_suspend(struct pci_dev *pdev, pm_message_t state) return 0; flush_scheduled_work(); - bnx2_netif_stop(bp); + bnx2_netif_stop(bp, true); netif_device_detach(dev); del_timer_sync(&bp->timer); bnx2_shutdown_chip(bp); @@ -8284,7 +8286,7 @@ bnx2_resume(struct pci_dev *pdev) bnx2_set_power_state(bp, PCI_D0); netif_device_attach(dev); bnx2_init_nic(bp, 1); - bnx2_netif_start(bp); + bnx2_netif_start(bp, true); return 0; } @@ -8311,7 +8313,7 @@ static pci_ers_result_t bnx2_io_error_detected(struct pci_dev *pdev, } if (netif_running(dev)) { - bnx2_netif_stop(bp); + bnx2_netif_stop(bp, true); del_timer_sync(&bp->timer); bnx2_reset_nic(bp, BNX2_DRV_MSG_CODE_RESET); } @@ -8367,7 +8369,7 @@ static void bnx2_io_resume(struct pci_dev *pdev) rtnl_lock(); if (netif_running(dev)) - bnx2_netif_start(bp); + bnx2_netif_start(bp, true); netif_device_attach(dev); rtnl_unlock(); -- 1.6.6.1