Commit 55bc3228 authored by Casey Leedom's avatar Casey Leedom Committed by David S. Miller

cxgb3: Avoid flush_workqueue() deadlock.

Don't call flush_workqueue() on the cxgb3 Work Queue in cxgb_down() when
we're being called from the fatal error task ... which is executing on the
cxgb3 Work Queue.
Signed-off-by: default avatarCasey Leedom <leedom@chelsio.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent aa476321
...@@ -1286,7 +1286,7 @@ static int cxgb_up(struct adapter *adap) ...@@ -1286,7 +1286,7 @@ static int cxgb_up(struct adapter *adap)
/* /*
* Release resources when all the ports and offloading have been stopped. * Release resources when all the ports and offloading have been stopped.
*/ */
static void cxgb_down(struct adapter *adapter) static void cxgb_down(struct adapter *adapter, int on_wq)
{ {
t3_sge_stop(adapter); t3_sge_stop(adapter);
spin_lock_irq(&adapter->work_lock); /* sync with PHY intr task */ spin_lock_irq(&adapter->work_lock); /* sync with PHY intr task */
...@@ -1296,7 +1296,8 @@ static void cxgb_down(struct adapter *adapter) ...@@ -1296,7 +1296,8 @@ static void cxgb_down(struct adapter *adapter)
free_irq_resources(adapter); free_irq_resources(adapter);
quiesce_rx(adapter); quiesce_rx(adapter);
t3_sge_stop(adapter); t3_sge_stop(adapter);
flush_workqueue(cxgb3_wq); /* wait for external IRQ handler */ if (!on_wq)
flush_workqueue(cxgb3_wq);/* wait for external IRQ handler */
} }
static void schedule_chk_task(struct adapter *adap) static void schedule_chk_task(struct adapter *adap)
...@@ -1374,7 +1375,7 @@ static int offload_close(struct t3cdev *tdev) ...@@ -1374,7 +1375,7 @@ static int offload_close(struct t3cdev *tdev)
clear_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map); clear_bit(OFFLOAD_DEVMAP_BIT, &adapter->open_device_map);
if (!adapter->open_device_map) if (!adapter->open_device_map)
cxgb_down(adapter); cxgb_down(adapter, 0);
cxgb3_offload_deactivate(adapter); cxgb3_offload_deactivate(adapter);
return 0; return 0;
...@@ -1409,7 +1410,7 @@ static int cxgb_open(struct net_device *dev) ...@@ -1409,7 +1410,7 @@ static int cxgb_open(struct net_device *dev)
return 0; return 0;
} }
static int cxgb_close(struct net_device *dev) static int __cxgb_close(struct net_device *dev, int on_wq)
{ {
struct port_info *pi = netdev_priv(dev); struct port_info *pi = netdev_priv(dev);
struct adapter *adapter = pi->adapter; struct adapter *adapter = pi->adapter;
...@@ -1436,12 +1437,17 @@ static int cxgb_close(struct net_device *dev) ...@@ -1436,12 +1437,17 @@ static int cxgb_close(struct net_device *dev)
cancel_delayed_work_sync(&adapter->adap_check_task); cancel_delayed_work_sync(&adapter->adap_check_task);
if (!adapter->open_device_map) if (!adapter->open_device_map)
cxgb_down(adapter); cxgb_down(adapter, on_wq);
cxgb3_event_notify(&adapter->tdev, OFFLOAD_PORT_DOWN, pi->port_id); cxgb3_event_notify(&adapter->tdev, OFFLOAD_PORT_DOWN, pi->port_id);
return 0; return 0;
} }
static int cxgb_close(struct net_device *dev)
{
return __cxgb_close(dev, 0);
}
static struct net_device_stats *cxgb_get_stats(struct net_device *dev) static struct net_device_stats *cxgb_get_stats(struct net_device *dev)
{ {
struct port_info *pi = netdev_priv(dev); struct port_info *pi = netdev_priv(dev);
...@@ -2862,7 +2868,7 @@ void t3_os_link_fault_handler(struct adapter *adapter, int port_id) ...@@ -2862,7 +2868,7 @@ void t3_os_link_fault_handler(struct adapter *adapter, int port_id)
spin_unlock(&adapter->work_lock); spin_unlock(&adapter->work_lock);
} }
static int t3_adapter_error(struct adapter *adapter, int reset) static int t3_adapter_error(struct adapter *adapter, int reset, int on_wq)
{ {
int i, ret = 0; int i, ret = 0;
...@@ -2877,7 +2883,7 @@ static int t3_adapter_error(struct adapter *adapter, int reset) ...@@ -2877,7 +2883,7 @@ static int t3_adapter_error(struct adapter *adapter, int reset)
struct net_device *netdev = adapter->port[i]; struct net_device *netdev = adapter->port[i];
if (netif_running(netdev)) if (netif_running(netdev))
cxgb_close(netdev); __cxgb_close(netdev, on_wq);
} }
/* Stop SGE timers */ /* Stop SGE timers */
...@@ -2948,7 +2954,7 @@ static void fatal_error_task(struct work_struct *work) ...@@ -2948,7 +2954,7 @@ static void fatal_error_task(struct work_struct *work)
int err = 0; int err = 0;
rtnl_lock(); rtnl_lock();
err = t3_adapter_error(adapter, 1); err = t3_adapter_error(adapter, 1, 1);
if (!err) if (!err)
err = t3_reenable_adapter(adapter); err = t3_reenable_adapter(adapter);
if (!err) if (!err)
...@@ -2998,7 +3004,7 @@ static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev, ...@@ -2998,7 +3004,7 @@ static pci_ers_result_t t3_io_error_detected(struct pci_dev *pdev,
if (state == pci_channel_io_perm_failure) if (state == pci_channel_io_perm_failure)
return PCI_ERS_RESULT_DISCONNECT; return PCI_ERS_RESULT_DISCONNECT;
ret = t3_adapter_error(adapter, 0); ret = t3_adapter_error(adapter, 0, 0);
/* Request a slot reset. */ /* Request a slot reset. */
return PCI_ERS_RESULT_NEED_RESET; return PCI_ERS_RESULT_NEED_RESET;
......
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