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. |
