aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2008-07-18 14:01:20 -0400
committerJeff Garzik <jgarzik@redhat.com>2008-07-22 19:44:13 -0400
commit8d9853d911b9d3fb767c3886066530c0e39b78ba (patch)
treeff27498e3d6b747bf07e21baa1b27d07be8f58ee
parent9dadae686fce02a02982fc9c0563f6b917217a66 (diff)
sfc: Use a separate workqueue for resets
This avoids deadlock in case a reset is triggered during self-test. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: Jeff Garzik <jgarzik@redhat.com>
-rw-r--r--drivers/net/sfc/efx.c20
-rw-r--r--drivers/net/sfc/net_driver.h5
2 files changed, 21 insertions, 4 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index 7b2015f9e469..7b2a81866232 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -1762,7 +1762,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
1762 1762
1763 efx->reset_pending = method; 1763 efx->reset_pending = method;
1764 1764
1765 queue_work(efx->workqueue, &efx->reset_work); 1765 queue_work(efx->reset_workqueue, &efx->reset_work);
1766} 1766}
1767 1767
1768/************************************************************************** 1768/**************************************************************************
@@ -1907,14 +1907,28 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
1907 goto fail1; 1907 goto fail1;
1908 } 1908 }
1909 1909
1910 efx->reset_workqueue = create_singlethread_workqueue("sfc_reset");
1911 if (!efx->reset_workqueue) {
1912 rc = -ENOMEM;
1913 goto fail2;
1914 }
1915
1910 return 0; 1916 return 0;
1911 1917
1918 fail2:
1919 destroy_workqueue(efx->workqueue);
1920 efx->workqueue = NULL;
1921
1912 fail1: 1922 fail1:
1913 return rc; 1923 return rc;
1914} 1924}
1915 1925
1916static void efx_fini_struct(struct efx_nic *efx) 1926static void efx_fini_struct(struct efx_nic *efx)
1917{ 1927{
1928 if (efx->reset_workqueue) {
1929 destroy_workqueue(efx->reset_workqueue);
1930 efx->reset_workqueue = NULL;
1931 }
1918 if (efx->workqueue) { 1932 if (efx->workqueue) {
1919 destroy_workqueue(efx->workqueue); 1933 destroy_workqueue(efx->workqueue);
1920 efx->workqueue = NULL; 1934 efx->workqueue = NULL;
@@ -1977,7 +1991,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
1977 * scheduled from this point because efx_stop_all() has been 1991 * scheduled from this point because efx_stop_all() has been
1978 * called, we are no longer registered with driverlink, and 1992 * called, we are no longer registered with driverlink, and
1979 * the net_device's have been removed. */ 1993 * the net_device's have been removed. */
1980 flush_workqueue(efx->workqueue); 1994 flush_workqueue(efx->reset_workqueue);
1981 1995
1982 efx_pci_remove_main(efx); 1996 efx_pci_remove_main(efx);
1983 1997
@@ -2098,7 +2112,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
2098 * scheduled since efx_stop_all() has been called, and we 2112 * scheduled since efx_stop_all() has been called, and we
2099 * have not and never have been registered with either 2113 * have not and never have been registered with either
2100 * the rtnetlink or driverlink layers. */ 2114 * the rtnetlink or driverlink layers. */
2101 cancel_work_sync(&efx->reset_work); 2115 flush_workqueue(efx->reset_workqueue);
2102 2116
2103 /* Retry if a recoverably reset event has been scheduled */ 2117 /* Retry if a recoverably reset event has been scheduled */
2104 if ((efx->reset_pending != RESET_TYPE_INVISIBLE) && 2118 if ((efx->reset_pending != RESET_TYPE_INVISIBLE) &&
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index d803b86c647c..219c74a772c3 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -616,7 +616,9 @@ union efx_multicast_hash {
616 * @pci_dev: The PCI device 616 * @pci_dev: The PCI device
617 * @type: Controller type attributes 617 * @type: Controller type attributes
618 * @legacy_irq: IRQ number 618 * @legacy_irq: IRQ number
619 * @workqueue: Workqueue for resets, port reconfigures and the HW monitor 619 * @workqueue: Workqueue for port reconfigures and the HW monitor.
620 * Work items do not hold and must not acquire RTNL.
621 * @reset_workqueue: Workqueue for resets. Work item will acquire RTNL.
620 * @reset_work: Scheduled reset workitem 622 * @reset_work: Scheduled reset workitem
621 * @monitor_work: Hardware monitor workitem 623 * @monitor_work: Hardware monitor workitem
622 * @membase_phys: Memory BAR value as physical address 624 * @membase_phys: Memory BAR value as physical address
@@ -684,6 +686,7 @@ struct efx_nic {
684 const struct efx_nic_type *type; 686 const struct efx_nic_type *type;
685 int legacy_irq; 687 int legacy_irq;
686 struct workqueue_struct *workqueue; 688 struct workqueue_struct *workqueue;
689 struct workqueue_struct *reset_workqueue;
687 struct work_struct reset_work; 690 struct work_struct reset_work;
688 struct delayed_work monitor_work; 691 struct delayed_work monitor_work;
689 resource_size_t membase_phys; 692 resource_size_t membase_phys;