aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c32
1 files changed, 19 insertions, 13 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index e2497e7ba926..a51a7cfa5a14 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -1036,7 +1036,7 @@ int iwlagn_tx_agg_start(struct iwl_priv *priv, struct ieee80211_vif *vif,
1036int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif, 1036int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
1037 struct ieee80211_sta *sta, u16 tid) 1037 struct ieee80211_sta *sta, u16 tid)
1038{ 1038{
1039 int tx_fifo_id, txq_id, sta_id, ssn = -1; 1039 int tx_fifo_id, txq_id, sta_id, ssn;
1040 struct iwl_tid_data *tid_data; 1040 struct iwl_tid_data *tid_data;
1041 int write_ptr, read_ptr; 1041 int write_ptr, read_ptr;
1042 unsigned long flags; 1042 unsigned long flags;
@@ -1054,21 +1054,26 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
1054 1054
1055 spin_lock_irqsave(&priv->sta_lock, flags); 1055 spin_lock_irqsave(&priv->sta_lock, flags);
1056 1056
1057 if (priv->stations[sta_id].tid[tid].agg.state ==
1058 IWL_EMPTYING_HW_QUEUE_ADDBA) {
1059 IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
1060 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1061 priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
1062 spin_unlock_irqrestore(&priv->sta_lock, flags);
1063 return 0;
1064 }
1065
1066 if (priv->stations[sta_id].tid[tid].agg.state != IWL_AGG_ON)
1067 IWL_WARN(priv, "Stopping AGG while state not ON or starting\n");
1068
1069 tid_data = &priv->stations[sta_id].tid[tid]; 1057 tid_data = &priv->stations[sta_id].tid[tid];
1070 ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4; 1058 ssn = (tid_data->seq_number & IEEE80211_SCTL_SEQ) >> 4;
1071 txq_id = tid_data->agg.txq_id; 1059 txq_id = tid_data->agg.txq_id;
1060
1061 switch (priv->stations[sta_id].tid[tid].agg.state) {
1062 case IWL_EMPTYING_HW_QUEUE_ADDBA:
1063 /*
1064 * This can happen if the peer stops aggregation
1065 * again before we've had a chance to drain the
1066 * queue we selected previously, i.e. before the
1067 * session was really started completely.
1068 */
1069 IWL_DEBUG_HT(priv, "AGG stop before setup done\n");
1070 goto turn_off;
1071 case IWL_AGG_ON:
1072 break;
1073 default:
1074 IWL_WARN(priv, "Stopping AGG while state not ON or starting\n");
1075 }
1076
1072 write_ptr = priv->txq[txq_id].q.write_ptr; 1077 write_ptr = priv->txq[txq_id].q.write_ptr;
1073 read_ptr = priv->txq[txq_id].q.read_ptr; 1078 read_ptr = priv->txq[txq_id].q.read_ptr;
1074 1079
@@ -1082,6 +1087,7 @@ int iwlagn_tx_agg_stop(struct iwl_priv *priv, struct ieee80211_vif *vif,
1082 } 1087 }
1083 1088
1084 IWL_DEBUG_HT(priv, "HW queue is empty\n"); 1089 IWL_DEBUG_HT(priv, "HW queue is empty\n");
1090 turn_off:
1085 priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF; 1091 priv->stations[sta_id].tid[tid].agg.state = IWL_AGG_OFF;
1086 1092
1087 /* do not restore/save irqs */ 1093 /* do not restore/save irqs */