From: Emmanuel Grumbach <emmanuel.grumb...@intel.com>

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.grumb...@intel.com>
Signed-off-by: Luca Coelho <luciano.coe...@intel.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 48f028366d51..52f9e8a76124 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c
@@ -1331,6 +1331,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++;
 
@@ -1344,6 +1345,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
@@ -1366,7 +1371,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.14.1

Reply via email to