iwlwifi: mvm: don't send BAR on flushed frames

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>
This commit is contained in:
Emmanuel Grumbach 2017-08-06 13:19:05 +03:00 committed by Luca Coelho
parent 3edfb5f44b
commit 114db230d3
1 changed files with 6 additions and 1 deletions

View File

@ -1331,6 +1331,7 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
while (!skb_queue_empty(&skbs)) { while (!skb_queue_empty(&skbs)) {
struct sk_buff *skb = __skb_dequeue(&skbs); struct sk_buff *skb = __skb_dequeue(&skbs);
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
bool flushed = false;
skb_freed++; skb_freed++;
@ -1344,6 +1345,10 @@ static void iwl_mvm_rx_tx_cmd_single(struct iwl_mvm *mvm,
case TX_STATUS_DIRECT_DONE: case TX_STATUS_DIRECT_DONE:
info->flags |= IEEE80211_TX_STAT_ACK; info->flags |= IEEE80211_TX_STAT_ACK;
break; break;
case TX_STATUS_FAIL_FIFO_FLUSHED:
case TX_STATUS_FAIL_DRAIN_FLOW:
flushed = true;
break;
case TX_STATUS_FAIL_DEST_PS: case TX_STATUS_FAIL_DEST_PS:
/* the FW should have stopped the queue and not /* the FW should have stopped the queue and not
* return this status * 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 */ /* Single frame failure in an AMPDU queue => send BAR */
if (info->flags & IEEE80211_TX_CTL_AMPDU && if (info->flags & IEEE80211_TX_CTL_AMPDU &&
!(info->flags & IEEE80211_TX_STAT_ACK) && !(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_STAT_AMPDU_NO_BACK;
info->flags &= ~IEEE80211_TX_CTL_AMPDU; info->flags &= ~IEEE80211_TX_CTL_AMPDU;