diff options
-rw-r--r-- | drivers/net/ethernet/sfc/efx.c | 30 |
1 files changed, 12 insertions, 18 deletions
diff --git a/drivers/net/ethernet/sfc/efx.c b/drivers/net/ethernet/sfc/efx.c index c734fba8c99c..893cd78c3a6c 100644 --- a/drivers/net/ethernet/sfc/efx.c +++ b/drivers/net/ethernet/sfc/efx.c | |||
@@ -1060,18 +1060,23 @@ static void efx_start_port(struct efx_nic *efx) | |||
1060 | mutex_lock(&efx->mac_lock); | 1060 | mutex_lock(&efx->mac_lock); |
1061 | efx->port_enabled = true; | 1061 | efx->port_enabled = true; |
1062 | 1062 | ||
1063 | /* efx_mac_work() might have been scheduled after efx_stop_port(), | 1063 | /* Ensure MAC ingress/egress is enabled */ |
1064 | * and then cancelled by efx_flush_all() */ | ||
1065 | efx->type->reconfigure_mac(efx); | 1064 | efx->type->reconfigure_mac(efx); |
1066 | 1065 | ||
1067 | mutex_unlock(&efx->mac_lock); | 1066 | mutex_unlock(&efx->mac_lock); |
1068 | } | 1067 | } |
1069 | 1068 | ||
1070 | /* Prevent efx_mac_work() and efx_monitor() from working */ | 1069 | /* Cancel work for MAC reconfiguration, periodic hardware monitoring |
1070 | * and the async self-test, wait for them to finish and prevent them | ||
1071 | * being scheduled again. This doesn't cover online resets, which | ||
1072 | * should only be cancelled when removing the device. | ||
1073 | */ | ||
1071 | static void efx_stop_port(struct efx_nic *efx) | 1074 | static void efx_stop_port(struct efx_nic *efx) |
1072 | { | 1075 | { |
1073 | netif_dbg(efx, ifdown, efx->net_dev, "stop port\n"); | 1076 | netif_dbg(efx, ifdown, efx->net_dev, "stop port\n"); |
1074 | 1077 | ||
1078 | EFX_ASSERT_RESET_SERIALISED(efx); | ||
1079 | |||
1075 | mutex_lock(&efx->mac_lock); | 1080 | mutex_lock(&efx->mac_lock); |
1076 | efx->port_enabled = false; | 1081 | efx->port_enabled = false; |
1077 | mutex_unlock(&efx->mac_lock); | 1082 | mutex_unlock(&efx->mac_lock); |
@@ -1079,6 +1084,10 @@ static void efx_stop_port(struct efx_nic *efx) | |||
1079 | /* Serialise against efx_set_multicast_list() */ | 1084 | /* Serialise against efx_set_multicast_list() */ |
1080 | netif_addr_lock_bh(efx->net_dev); | 1085 | netif_addr_lock_bh(efx->net_dev); |
1081 | netif_addr_unlock_bh(efx->net_dev); | 1086 | netif_addr_unlock_bh(efx->net_dev); |
1087 | |||
1088 | cancel_delayed_work_sync(&efx->monitor_work); | ||
1089 | efx_selftest_async_cancel(efx); | ||
1090 | cancel_work_sync(&efx->mac_work); | ||
1082 | } | 1091 | } |
1083 | 1092 | ||
1084 | static void efx_fini_port(struct efx_nic *efx) | 1093 | static void efx_fini_port(struct efx_nic *efx) |
@@ -1690,18 +1699,6 @@ static void efx_start_all(struct efx_nic *efx) | |||
1690 | spin_unlock_bh(&efx->stats_lock); | 1699 | spin_unlock_bh(&efx->stats_lock); |
1691 | } | 1700 | } |
1692 | 1701 | ||
1693 | /* Flush all delayed work. Should only be called when no more delayed work | ||
1694 | * will be scheduled. This doesn't flush pending online resets (efx_reset), | ||
1695 | * since we're holding the rtnl_lock at this point. */ | ||
1696 | static void efx_flush_all(struct efx_nic *efx) | ||
1697 | { | ||
1698 | /* Make sure the hardware monitor and event self-test are stopped */ | ||
1699 | cancel_delayed_work_sync(&efx->monitor_work); | ||
1700 | efx_selftest_async_cancel(efx); | ||
1701 | /* Stop scheduled port reconfigurations */ | ||
1702 | cancel_work_sync(&efx->mac_work); | ||
1703 | } | ||
1704 | |||
1705 | /* Quiesce the hardware and software data path, and regular activity | 1702 | /* Quiesce the hardware and software data path, and regular activity |
1706 | * for the port without bringing the link down. Safe to call multiple | 1703 | * for the port without bringing the link down. Safe to call multiple |
1707 | * times with the NIC in almost any state, but interrupts should be | 1704 | * times with the NIC in almost any state, but interrupts should be |
@@ -1725,9 +1722,6 @@ static void efx_stop_all(struct efx_nic *efx) | |||
1725 | efx->type->stop_stats(efx); | 1722 | efx->type->stop_stats(efx); |
1726 | efx_stop_port(efx); | 1723 | efx_stop_port(efx); |
1727 | 1724 | ||
1728 | /* Flush efx_mac_work(), refill_workqueue, monitor_work */ | ||
1729 | efx_flush_all(efx); | ||
1730 | |||
1731 | /* Stop the kernel transmit interface. This is only valid if | 1725 | /* Stop the kernel transmit interface. This is only valid if |
1732 | * the device is stopped or detached; otherwise the watchdog | 1726 | * the device is stopped or detached; otherwise the watchdog |
1733 | * may fire immediately. | 1727 | * may fire immediately. |