diff options
-rw-r--r-- | drivers/net/ethernet/sfc/efx.c | 16 |
1 files changed, 12 insertions, 4 deletions
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index 34e51f37b98a..5d5a05f20cea 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c @@ -719,6 +719,7 @@ efx_realloc_channels(struct efx_nic *efx, u32 rxq_entries, u32 txq_entries) unsigned i; int rc; + efx_device_detach_sync(efx); efx_stop_all(efx); efx_fini_channels(efx); @@ -762,6 +763,7 @@ out: efx_init_channels(efx); efx_start_all(efx); + netif_device_attach(efx->net_dev); return rc; rollback: @@ -1530,8 +1532,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)); if (efx_dev_registered(efx)) { netif_tx_stop_all_queues(efx->net_dev); netif_tx_lock_bh(efx->net_dev); @@ -1832,10 +1838,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); + efx_fini_channels(efx); mutex_lock(&efx->mac_lock); @@ -1848,6 +1855,7 @@ static int efx_change_mtu(struct net_device *net_dev, int new_mtu) efx_init_channels(efx); efx_start_all(efx); + netif_device_attach(efx->net_dev); return rc; } |