path: root/drivers/net/ethernet/intel/i40e/i40e_main.c
diff options
authorAlan Brady <alan.brady@intel.com>2018-10-29 11:27:21 -0700
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2018-11-14 10:56:34 -0800
commitd5585b7b6846a6d0f9517afe57be3843150719da (patch)
tree319e38ef420619753b59fbb993014a8e89781752 /drivers/net/ethernet/intel/i40e/i40e_main.c
parenti40e: suppress bogus error message (diff)
i40e: prevent overlapping tx_timeout recover
If a TX hang occurs, we attempt to recover by incrementally resetting. If we're starved for CPU time, it's possible the reset doesn't actually complete (or even fire) before another tx_timeout fires causing us to fly through the different resets without actually doing them. This adds a bit to set and check if a timeout recovery is already pending and, if so, bail out of tx_timeout. The bit will get cleared at the end of i40e_rebuild when reset is complete. Signed-off-by: Alan Brady <alan.brady@intel.com> Tested-by: Andrew Bowers <andrewx.bowers@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
Diffstat (limited to '')
1 files changed, 5 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c
index d4461eec26bd..47f0fdadbac9 100644
--- a/drivers/net/ethernet/intel/i40e/i40e_main.c
+++ b/drivers/net/ethernet/intel/i40e/i40e_main.c
@@ -338,6 +338,10 @@ static void i40e_tx_timeout(struct net_device *netdev)
(pf->tx_timeout_last_recovery + netdev->watchdog_timeo)))
return; /* don't do any new action before the next timeout */
+ /* don't kick off another recovery if one is already pending */
+ if (test_and_set_bit(__I40E_TIMEOUT_RECOVERY_PENDING, pf->state))
+ return;
if (tx_ring) {
head = i40e_get_head(tx_ring);
/* Read interrupt register */
@@ -9631,6 +9635,7 @@ end_core_reset:
clear_bit(__I40E_RESET_FAILED, pf->state);
clear_bit(__I40E_RESET_RECOVERY_PENDING, pf->state);
+ clear_bit(__I40E_TIMEOUT_RECOVERY_PENDING, pf->state);