aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/ethernet
diff options
context:
space:
mode:
authorBen Hutchings <bhutchings@solarflare.com>2013-01-28 19:01:06 +0000
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2013-03-28 12:11:56 -0700
commitbea3099eb4f3f73cc2c311d39ef374eb6aa06f88 (patch)
treedbb773c2bdb86cb7a0f842840e879f63dc6f7083 /drivers/net/ethernet
parent4b8fd2aa494aff51404a4afa0fe36475fd419b76 (diff)
sfc: Detach net device when stopping queues for reconfiguration
[ Upstream commit 29c69a4882641285a854d6d03ca5adbba68c0034 ] We must only ever stop TX queues when they are full or the net device is not 'ready' so far as the net core, and specifically the watchdog, is concerned. Otherwise, the watchdog may fire *immediately* if no packets have been added to the queue in the last 5 seconds. The device is ready if all the following are true: (a) It has a qdisc (b) It is marked present (c) It is running (d) The link is reported up (a) and (c) are normally true, and must not be changed by a driver. (d) is under our control, but fake link changes may disturb userland. This leaves (b). We already mark the device absent during reset and self-test, but we need to do the same during MTU changes and ring reallocation. We don't need to do this when the device is brought down because then (c) is already false. Signed-off-by: Ben Hutchings <bhutchings@solarflare.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/net/ethernet')
-rw-r--r--drivers/net/ethernet/sfc/efx.c16
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c
index 8c81d1c6519..a87f3510741 100644
--- a/drivers/net/ethernet/sfc/efx.c
+++ b/drivers/net/ethernet/sfc/efx.c
@@ -754,6 +754,7 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries)
tx_queue->txd.entries);
}
+ efx_device_detach_sync(efx);
efx_stop_all(efx);
efx_stop_interrupts(efx, true);
@@ -807,6 +808,7 @@ out:
efx_start_interrupts(efx, true);
efx_start_all(efx);
+ netif_device_attach(efx->net_dev);
return rc;
rollback:
@@ -1601,8 +1603,12 @@ static void efx_stop_all(struct efx_nic *efx)
/* Flush efx_mac_work(), refill_workqueue, monitor_work */
efx_flush_all(efx);
- /* Stop the kernel transmit interface late, so the watchdog
- * timer isn't ticking over the flush */
+ /* Stop the kernel transmit interface. This is only valid if
+ * the device is stopped or detached; otherwise the watchdog
+ * may fire immediately.
+ */
+ WARN_ON(netif_running(efx->net_dev) &&
+ netif_device_present(efx->net_dev));
netif_tx_disable(efx->net_dev);
efx_stop_datapath(efx);
@@ -1921,10 +1927,11 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
if (new_mtu > EFX_MAX_MTU)
return -EINVAL;
- efx_stop_all(efx);
-
netif_dbg(efx, drv, efx->net_dev, "changing MTU to %d\n", new_mtu);
+ efx_device_detach_sync(efx);
+ efx_stop_all(efx);
+
mutex_lock(&efx->mac_lock);
/* Reconfigure the MAC before enabling the dma queues so that
* the RX buffers don't overflow */
@@ -1933,6 +1940,7 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu)
mutex_unlock(&efx->mac_lock);
efx_start_all(efx);
+ netif_device_attach(efx->net_dev);
return 0;
}