From 0583173691ff6971a33fa3b962ba42096cef4ac8 Mon Sep 17 00:00:00 2001
From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Date: Sun, 6 Aug 2017 13:19:05 +0300
Subject: [PATCH 54/68] iwlwifi: mvm: don't send BAR on flushed frames
References: FATE#322675
Patch-mainline: v4.14-rc1
Git-commit: 114db230d35442e6d3382adc8ac34c944b5cd0eb
When we flush a queue, the packets will have a 'failed'
status but we shouldn't send a BAR. This check was missing.
Because of that, when we got an ampdu_action with
IEEE80211_AMPDU_TX_STOP_FLUSH, we started the following
ping pong with the firmware:
1) Set the station as 'draining'
2) Get a failed Tx status (DRAINED)
3) Send a BAR because of the failed Tx status
(loop of 2 and 3)
This loop wasn't endless since the BAR isn't sent on a
queue that would trigger a "nested" BAR.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Oliver Neukum <oneukum@suse.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 7 ++++++-
1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
index 93c454891eae..172b5e63d3fb 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -1337,6 +1337,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
while (!skb_queue_empty(&skbs)) {
struct sk_buff *skb = __skb_dequeue(&skbs);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
+ bool flushed = false;
skb_freed++;
@@ -1350,6 +1351,10 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
case TX_STATUS_DIRECT_DONE:
info->flags |= IEEE80211_TX_STAT_ACK;
break;
+ case TX_STATUS_FAIL_FIFO_FLUSHED:
+ case TX_STATUS_FAIL_DRAIN_FLOW:
+ flushed = true;
+ break;
case TX_STATUS_FAIL_DEST_PS:
/* the FW should have stopped the queue and not
* return this status
@@ -1372,7 +1377,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
/* Single frame failure in an AMPDU queue => send BAR */
if (info->flags & IEEE80211_TX_CTL_AMPDU &&
!(info->flags & IEEE80211_TX_STAT_ACK) &&
- !(info->flags & IEEE80211_TX_STAT_TX_FILTERED))
+ !(info->flags & IEEE80211_TX_STAT_TX_FILTERED) && !flushed)
info->flags |= IEEE80211_TX_STAT_AMPDU_NO_BACK;
info->flags &= ~IEEE80211_TX_CTL_AMPDU;
--
2.12.3