diff options
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn-tx.c')
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-agn-tx.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c index c46d50dfbc7c..6321ea2fffa9 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c @@ -588,6 +588,43 @@ int iwlagn_tx_agg_oper(struct iwl_priv *priv, struct ieee80211_vif *vif, &sta_priv->lq_sta.lq, CMD_ASYNC, false); } +static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid) +{ + struct iwl_tid_data *tid_data = &priv->shrd->tid_data[sta_id][tid]; + + lockdep_assert_held(&priv->shrd->sta_lock); + + switch (priv->shrd->tid_data[sta_id][tid].agg.state) { + case IWL_EMPTYING_HW_QUEUE_DELBA: + /* There are no packets for this RA / TID in the HW any more */ + if (tid_data->agg.ssn == tid_data->next_reclaimed) { + IWL_DEBUG_TX_QUEUES(priv, + "Can continue DELBA flow ssn = next_recl =" + " %d", tid_data->next_reclaimed); + iwl_trans_tx_agg_disable(trans(priv), sta_id, tid); + tid_data->agg.state = IWL_AGG_OFF; + iwl_stop_tx_ba_trans_ready(priv, + NUM_IWL_RXON_CTX, + sta_id, tid); + } + break; + case IWL_EMPTYING_HW_QUEUE_ADDBA: + /* There are no packets for this RA / TID in the HW any more */ + if (tid_data->agg.ssn == tid_data->next_reclaimed) { + IWL_DEBUG_TX_QUEUES(priv, + "Can continue ADDBA flow ssn = next_recl =" + " %d", tid_data->next_reclaimed); + tid_data->agg.state = IWL_AGG_ON; + iwl_start_tx_ba_trans_ready(priv, + NUM_IWL_RXON_CTX, + sta_id, tid); + } + break; + default: + break; + } +} + static void iwlagn_non_agg_tx_status(struct iwl_priv *priv, struct iwl_rxon_context *ctx, const u8 *addr1) @@ -965,6 +1002,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_mem_buffer *rxb, /*we can free until ssn % q.n_bd not inclusive */ iwl_trans_reclaim(trans(priv), sta_id, tid, txq_id, ssn, status, &skbs); + iwlagn_check_ratid_empty(priv, sta_id, tid); freed = 0; while (!skb_queue_empty(&skbs)) { skb = __skb_dequeue(&skbs); @@ -1120,6 +1158,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv, priv->shrd->tid_data[sta_id][tid].next_reclaimed = ba_resp_scd_ssn; iwl_trans_reclaim(trans(priv), sta_id, tid, scd_flow, ba_resp_scd_ssn, 0, &reclaimed_skbs); + iwlagn_check_ratid_empty(priv, sta_id, tid); freed = 0; while (!skb_queue_empty(&reclaimed_skbs)) { |