summaryrefslogtreecommitdiffstats
path: root/drivers/net/sfc
diff options
context:
space:
mode:
authorSteve Hodgson <shodgson@solarflare.com>2008-12-13 06:33:02 +0100
committerDavid S. Miller <davem@davemloft.net>2008-12-13 06:56:21 +0100
commit1ab00629f06fb3c47de6373cd92d086f33775444 (patch)
tree141cd0599bc92c1911c7c487cc515ec1460908cd /drivers/net/sfc
parentsfc: Correct interpretation of second param to ethtool phys_id() (diff)
downloadlinux-1ab00629f06fb3c47de6373cd92d086f33775444.tar.xz
linux-1ab00629f06fb3c47de6373cd92d086f33775444.zip
sfc: Make reset_workqueue driver-global rather than per-NIC
Each reset is serialised by the rtnl_lock anyway, so there's no win per-NIC. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/sfc')
-rw-r--r--drivers/net/sfc/efx.c45
-rw-r--r--drivers/net/sfc/net_driver.h2
2 files changed, 20 insertions, 27 deletions
diff --git a/drivers/net/sfc/efx.c b/drivers/net/sfc/efx.c
index bbc84026dd86..127b4da0a5e7 100644
--- a/drivers/net/sfc/efx.c
+++ b/drivers/net/sfc/efx.c
@@ -39,6 +39,12 @@
*/
static struct workqueue_struct *refill_workqueue;
+/* Reset workqueue. If any NIC has a hardware failure then a reset will be
+ * queued onto this work queue. This is not a per-nic work queue, because
+ * efx_reset_work() acquires the rtnl lock, so resets are naturally serialised.
+ */
+static struct workqueue_struct *reset_workqueue;
+
/**************************************************************************
*
* Configurable values
@@ -1697,7 +1703,7 @@ void efx_schedule_reset(struct efx_nic *efx, enum reset_type type)
efx->reset_pending = method;
- queue_work(efx->reset_workqueue, &efx->reset_work);
+ queue_work(reset_workqueue, &efx->reset_work);
}
/**************************************************************************
@@ -1763,7 +1769,7 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
struct efx_channel *channel;
struct efx_tx_queue *tx_queue;
struct efx_rx_queue *rx_queue;
- int i, rc;
+ int i;
/* Initialise common structures */
memset(efx, 0, sizeof(*efx));
@@ -1832,33 +1838,14 @@ static int efx_init_struct(struct efx_nic *efx, struct efx_nic_type *type,
interrupt_mode);
efx->workqueue = create_singlethread_workqueue("sfc_work");
- if (!efx->workqueue) {
- rc = -ENOMEM;
- goto fail1;
- }
-
- efx->reset_workqueue = create_singlethread_workqueue("sfc_reset");
- if (!efx->reset_workqueue) {
- rc = -ENOMEM;
- goto fail2;
- }
+ if (!efx->workqueue)
+ return -ENOMEM;
return 0;
-
- fail2:
- destroy_workqueue(efx->workqueue);
- efx->workqueue = NULL;
-
- fail1:
- return rc;
}
static void efx_fini_struct(struct efx_nic *efx)
{
- if (efx->reset_workqueue) {
- destroy_workqueue(efx->reset_workqueue);
- efx->reset_workqueue = NULL;
- }
if (efx->workqueue) {
destroy_workqueue(efx->workqueue);
efx->workqueue = NULL;
@@ -1923,7 +1910,7 @@ static void efx_pci_remove(struct pci_dev *pci_dev)
* scheduled from this point because efx_stop_all() has been
* called, we are no longer registered with driverlink, and
* the net_device's have been removed. */
- flush_workqueue(efx->reset_workqueue);
+ cancel_work_sync(&efx->reset_work);
efx_pci_remove_main(efx);
@@ -2045,7 +2032,7 @@ static int __devinit efx_pci_probe(struct pci_dev *pci_dev,
* scheduled since efx_stop_all() has been called, and we
* have not and never have been registered with either
* the rtnetlink or driverlink layers. */
- flush_workqueue(efx->reset_workqueue);
+ cancel_work_sync(&efx->reset_work);
/* Retry if a recoverably reset event has been scheduled */
if ((efx->reset_pending != RESET_TYPE_INVISIBLE) &&
@@ -2121,6 +2108,11 @@ static int __init efx_init_module(void)
rc = -ENOMEM;
goto err_refill;
}
+ reset_workqueue = create_singlethread_workqueue("sfc_reset");
+ if (!reset_workqueue) {
+ rc = -ENOMEM;
+ goto err_reset;
+ }
rc = pci_register_driver(&efx_pci_driver);
if (rc < 0)
@@ -2129,6 +2121,8 @@ static int __init efx_init_module(void)
return 0;
err_pci:
+ destroy_workqueue(reset_workqueue);
+ err_reset:
destroy_workqueue(refill_workqueue);
err_refill:
unregister_netdevice_notifier(&efx_netdev_notifier);
@@ -2141,6 +2135,7 @@ static void __exit efx_exit_module(void)
printk(KERN_INFO "Solarflare NET driver unloading\n");
pci_unregister_driver(&efx_pci_driver);
+ destroy_workqueue(reset_workqueue);
destroy_workqueue(refill_workqueue);
unregister_netdevice_notifier(&efx_netdev_notifier);
diff --git a/drivers/net/sfc/net_driver.h b/drivers/net/sfc/net_driver.h
index e596c9a6a4c4..f91060963475 100644
--- a/drivers/net/sfc/net_driver.h
+++ b/drivers/net/sfc/net_driver.h
@@ -635,7 +635,6 @@ union efx_multicast_hash {
* @legacy_irq: IRQ number
* @workqueue: Workqueue for port reconfigures and the HW monitor.
* Work items do not hold and must not acquire RTNL.
- * @reset_workqueue: Workqueue for resets. Work item will acquire RTNL.
* @reset_work: Scheduled reset workitem
* @monitor_work: Hardware monitor workitem
* @membase_phys: Memory BAR value as physical address
@@ -711,7 +710,6 @@ struct efx_nic {
const struct efx_nic_type *type;
int legacy_irq;
struct workqueue_struct *workqueue;
- struct workqueue_struct *reset_workqueue;
struct work_struct reset_work;
struct delayed_work monitor_work;
resource_size_t membase_phys;