aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c4
-rw-r--r--drivers/net/wireless/ath/carl9170/main.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c4
-rw-r--r--drivers/net/wireless/iwlegacy/4965-mac.c4
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/mac80211.c4
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c4
-rw-r--r--drivers/net/wireless/mwl8k.c4
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c4
-rw-r--r--drivers/net/wireless/rtlwifi/core.c4
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c4
-rw-r--r--include/net/mac80211.h22
-rw-r--r--net/mac80211/agg-tx.c40
13 files changed, 85 insertions, 21 deletions
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index 9c07a8fa5134..a8016d70088a 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -1628,7 +1628,9 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw,
1628 if (!ret) 1628 if (!ret)
1629 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); 1629 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1630 break; 1630 break;
1631 case IEEE80211_AMPDU_TX_STOP: 1631 case IEEE80211_AMPDU_TX_STOP_CONT:
1632 case IEEE80211_AMPDU_TX_STOP_FLUSH:
1633 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
1632 ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid); 1634 ath9k_htc_tx_aggr_oper(priv, vif, sta, action, tid);
1633 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 1635 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1634 break; 1636 break;
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index be30a9af1528..e1fa70596e61 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1610,7 +1610,9 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw,
1610 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); 1610 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1611 ath9k_ps_restore(sc); 1611 ath9k_ps_restore(sc);
1612 break; 1612 break;
1613 case IEEE80211_AMPDU_TX_STOP: 1613 case IEEE80211_AMPDU_TX_STOP_CONT:
1614 case IEEE80211_AMPDU_TX_STOP_FLUSH:
1615 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
1614 ath9k_ps_wakeup(sc); 1616 ath9k_ps_wakeup(sc);
1615 ath_tx_aggr_stop(sc, sta, tid); 1617 ath_tx_aggr_stop(sc, sta, tid);
1616 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 1618 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
diff --git a/drivers/net/wireless/ath/carl9170/main.c b/drivers/net/wireless/ath/carl9170/main.c
index 25a1e2f4f738..9d2051aeb782 100644
--- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -1394,7 +1394,9 @@ static int carl9170_op_ampdu_action(struct ieee80211_hw *hw,
1394 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); 1394 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1395 break; 1395 break;
1396 1396
1397 case IEEE80211_AMPDU_TX_STOP: 1397 case IEEE80211_AMPDU_TX_STOP_CONT:
1398 case IEEE80211_AMPDU_TX_STOP_FLUSH:
1399 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
1398 rcu_read_lock(); 1400 rcu_read_lock();
1399 tid_info = rcu_dereference(sta_info->agg[tid]); 1401 tid_info = rcu_dereference(sta_info->agg[tid]);
1400 if (tid_info) { 1402 if (tid_info) {
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 1fbd8ecbe2ea..f0fc8cd4d5df 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -668,7 +668,9 @@ brcms_ops_ampdu_action(struct ieee80211_hw *hw,
668 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); 668 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
669 break; 669 break;
670 670
671 case IEEE80211_AMPDU_TX_STOP: 671 case IEEE80211_AMPDU_TX_STOP_CONT:
672 case IEEE80211_AMPDU_TX_STOP_FLUSH:
673 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
672 spin_lock_bh(&wl->lock); 674 spin_lock_bh(&wl->lock);
673 brcms_c_ampdu_flush(wl->wlc, sta, tid); 675 brcms_c_ampdu_flush(wl->wlc, sta, tid);
674 spin_unlock_bh(&wl->lock); 676 spin_unlock_bh(&wl->lock);
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c
index c3fbf6717564..6a86ed45835d 100644
--- a/drivers/net/wireless/iwlegacy/4965-mac.c
+++ b/drivers/net/wireless/iwlegacy/4965-mac.c
@@ -5968,7 +5968,9 @@ il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
5968 D_HT("start Tx\n"); 5968 D_HT("start Tx\n");
5969 ret = il4965_tx_agg_start(il, vif, sta, tid, ssn); 5969 ret = il4965_tx_agg_start(il, vif, sta, tid, ssn);
5970 break; 5970 break;
5971 case IEEE80211_AMPDU_TX_STOP: 5971 case IEEE80211_AMPDU_TX_STOP_CONT:
5972 case IEEE80211_AMPDU_TX_STOP_FLUSH:
5973 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
5972 D_HT("stop Tx\n"); 5974 D_HT("stop Tx\n");
5973 ret = il4965_tx_agg_stop(il, vif, sta, tid); 5975 ret = il4965_tx_agg_stop(il, vif, sta, tid);
5974 if (test_bit(S_EXIT_PENDING, &il->status)) 5976 if (test_bit(S_EXIT_PENDING, &il->status))
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
index 3163e0f38c25..02fdcea76b21 100644
--- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c
@@ -679,7 +679,9 @@ static int iwlagn_mac_ampdu_action(struct ieee80211_hw *hw,
679 IWL_DEBUG_HT(priv, "start Tx\n"); 679 IWL_DEBUG_HT(priv, "start Tx\n");
680 ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn); 680 ret = iwlagn_tx_agg_start(priv, vif, sta, tid, ssn);
681 break; 681 break;
682 case IEEE80211_AMPDU_TX_STOP: 682 case IEEE80211_AMPDU_TX_STOP_CONT:
683 case IEEE80211_AMPDU_TX_STOP_FLUSH:
684 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
683 IWL_DEBUG_HT(priv, "stop Tx\n"); 685 IWL_DEBUG_HT(priv, "stop Tx\n");
684 ret = iwlagn_tx_agg_stop(priv, vif, sta, tid); 686 ret = iwlagn_tx_agg_stop(priv, vif, sta, tid);
685 if ((ret == 0) && (priv->agg_tids_count > 0)) { 687 if ((ret == 0) && (priv->agg_tids_count > 0)) {
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 145498f8411f..d248a4cc6656 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -1312,7 +1312,9 @@ static int mac80211_hwsim_ampdu_action(struct ieee80211_hw *hw,
1312 case IEEE80211_AMPDU_TX_START: 1312 case IEEE80211_AMPDU_TX_START:
1313 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); 1313 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1314 break; 1314 break;
1315 case IEEE80211_AMPDU_TX_STOP: 1315 case IEEE80211_AMPDU_TX_STOP_CONT:
1316 case IEEE80211_AMPDU_TX_STOP_FLUSH:
1317 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
1316 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 1318 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
1317 break; 1319 break;
1318 case IEEE80211_AMPDU_TX_OPERATIONAL: 1320 case IEEE80211_AMPDU_TX_OPERATIONAL:
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index f221b95b90b3..19b46fdf9f0f 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -5170,7 +5170,9 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
5170 } 5170 }
5171 ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); 5171 ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
5172 break; 5172 break;
5173 case IEEE80211_AMPDU_TX_STOP: 5173 case IEEE80211_AMPDU_TX_STOP_CONT:
5174 case IEEE80211_AMPDU_TX_STOP_FLUSH:
5175 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
5174 if (stream) { 5176 if (stream) {
5175 if (stream->state == AMPDU_STREAM_ACTIVE) { 5177 if (stream->state == AMPDU_STREAM_ACTIVE) {
5176 spin_unlock(&priv->stream_lock); 5178 spin_unlock(&priv->stream_lock);
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index 197b4466a5d2..12f93e42e160 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -5484,7 +5484,9 @@ int rt2800_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
5484 case IEEE80211_AMPDU_TX_START: 5484 case IEEE80211_AMPDU_TX_START:
5485 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid); 5485 ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
5486 break; 5486 break;
5487 case IEEE80211_AMPDU_TX_STOP: 5487 case IEEE80211_AMPDU_TX_STOP_CONT:
5488 case IEEE80211_AMPDU_TX_STOP_FLUSH:
5489 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
5488 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid); 5490 ieee80211_stop_tx_ba_cb_irqsafe(vif, sta->addr, tid);
5489 break; 5491 break;
5490 case IEEE80211_AMPDU_TX_OPERATIONAL: 5492 case IEEE80211_AMPDU_TX_OPERATIONAL:
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c
index be33aa14c8af..d3ce9fbef00e 100644
--- a/drivers/net/wireless/rtlwifi/core.c
+++ b/drivers/net/wireless/rtlwifi/core.c
@@ -879,7 +879,9 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw,
879 "IEEE80211_AMPDU_TX_START: TID:%d\n", tid); 879 "IEEE80211_AMPDU_TX_START: TID:%d\n", tid);
880 return rtl_tx_agg_start(hw, sta, tid, ssn); 880 return rtl_tx_agg_start(hw, sta, tid, ssn);
881 break; 881 break;
882 case IEEE80211_AMPDU_TX_STOP: 882 case IEEE80211_AMPDU_TX_STOP_CONT:
883 case IEEE80211_AMPDU_TX_STOP_FLUSH:
884 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
883 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE, 885 RT_TRACE(rtlpriv, COMP_MAC80211, DBG_TRACE,
884 "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid); 886 "IEEE80211_AMPDU_TX_STOP: TID:%d\n", tid);
885 return rtl_tx_agg_stop(hw, sta, tid); 887 return rtl_tx_agg_stop(hw, sta, tid);
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index ea9d8e011bc9..d7de06359ae1 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -4575,7 +4575,9 @@ static int wl1271_op_ampdu_action(struct ieee80211_hw *hw,
4575 * Falling break here on purpose for all TX APDU commands. 4575 * Falling break here on purpose for all TX APDU commands.
4576 */ 4576 */
4577 case IEEE80211_AMPDU_TX_START: 4577 case IEEE80211_AMPDU_TX_START:
4578 case IEEE80211_AMPDU_TX_STOP: 4578 case IEEE80211_AMPDU_TX_STOP_CONT:
4579 case IEEE80211_AMPDU_TX_STOP_FLUSH:
4580 case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
4579 case IEEE80211_AMPDU_TX_OPERATIONAL: 4581 case IEEE80211_AMPDU_TX_OPERATIONAL:
4580 ret = -EINVAL; 4582 ret = -EINVAL;
4581 break; 4583 break;
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 0978b0faa880..a464f4fb36a0 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2033,17 +2033,29 @@ enum ieee80211_filter_flags {
2033 * calling ieee80211_start_tx_ba_cb_irqsafe, because the peer 2033 * calling ieee80211_start_tx_ba_cb_irqsafe, because the peer
2034 * might receive the addBA frame and send a delBA right away! 2034 * might receive the addBA frame and send a delBA right away!
2035 * 2035 *
2036 * @IEEE80211_AMPDU_RX_START: start Rx aggregation 2036 * @IEEE80211_AMPDU_RX_START: start RX aggregation
2037 * @IEEE80211_AMPDU_RX_STOP: stop Rx aggregation 2037 * @IEEE80211_AMPDU_RX_STOP: stop RX aggregation
2038 * @IEEE80211_AMPDU_TX_START: start Tx aggregation 2038 * @IEEE80211_AMPDU_TX_START: start TX aggregation
2039 * @IEEE80211_AMPDU_TX_STOP: stop Tx aggregation
2040 * @IEEE80211_AMPDU_TX_OPERATIONAL: TX aggregation has become operational 2039 * @IEEE80211_AMPDU_TX_OPERATIONAL: TX aggregation has become operational
2040 * @IEEE80211_AMPDU_TX_STOP_CONT: stop TX aggregation but continue transmitting
2041 * queued packets, now unaggregated. After all packets are transmitted the
2042 * driver has to call ieee80211_stop_tx_ba_cb_irqsafe().
2043 * @IEEE80211_AMPDU_TX_STOP_FLUSH: stop TX aggregation and flush all packets,
2044 * called when the station is removed. There's no need or reason to call
2045 * ieee80211_stop_tx_ba_cb_irqsafe() in this case as mac80211 assumes the
2046 * session is gone and removes the station.
2047 * @IEEE80211_AMPDU_TX_STOP_FLUSH_CONT: called when TX aggregation is stopped
2048 * but the driver hasn't called ieee80211_stop_tx_ba_cb_irqsafe() yet and
2049 * now the connection is dropped and the station will be removed. Drivers
2050 * should clean up and drop remaining packets when this is called.
2041 */ 2051 */
2042enum ieee80211_ampdu_mlme_action { 2052enum ieee80211_ampdu_mlme_action {
2043 IEEE80211_AMPDU_RX_START, 2053 IEEE80211_AMPDU_RX_START,
2044 IEEE80211_AMPDU_RX_STOP, 2054 IEEE80211_AMPDU_RX_STOP,
2045 IEEE80211_AMPDU_TX_START, 2055 IEEE80211_AMPDU_TX_START,
2046 IEEE80211_AMPDU_TX_STOP, 2056 IEEE80211_AMPDU_TX_STOP_CONT,
2057 IEEE80211_AMPDU_TX_STOP_FLUSH,
2058 IEEE80211_AMPDU_TX_STOP_FLUSH_CONT,
2047 IEEE80211_AMPDU_TX_OPERATIONAL, 2059 IEEE80211_AMPDU_TX_OPERATIONAL,
2048}; 2060};
2049 2061
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index dda8d7df4b54..2f0ccbc5f13e 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -257,10 +257,25 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
257{ 257{
258 struct ieee80211_local *local = sta->local; 258 struct ieee80211_local *local = sta->local;
259 struct tid_ampdu_tx *tid_tx; 259 struct tid_ampdu_tx *tid_tx;
260 enum ieee80211_ampdu_mlme_action action;
260 int ret; 261 int ret;
261 262
262 lockdep_assert_held(&sta->ampdu_mlme.mtx); 263 lockdep_assert_held(&sta->ampdu_mlme.mtx);
263 264
265 switch (reason) {
266 case AGG_STOP_DECLINED:
267 case AGG_STOP_LOCAL_REQUEST:
268 case AGG_STOP_PEER_REQUEST:
269 action = IEEE80211_AMPDU_TX_STOP_CONT;
270 break;
271 case AGG_STOP_DESTROY_STA:
272 action = IEEE80211_AMPDU_TX_STOP_FLUSH;
273 break;
274 default:
275 WARN_ON_ONCE(1);
276 return -EINVAL;
277 }
278
264 spin_lock_bh(&sta->lock); 279 spin_lock_bh(&sta->lock);
265 280
266 tid_tx = rcu_dereference_protected_tid_tx(sta, tid); 281 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
@@ -269,10 +284,19 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
269 return -ENOENT; 284 return -ENOENT;
270 } 285 }
271 286
272 /* if we're already stopping ignore any new requests to stop */ 287 /*
288 * if we're already stopping ignore any new requests to stop
289 * unless we're destroying it in which case notify the driver
290 */
273 if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { 291 if (test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
274 spin_unlock_bh(&sta->lock); 292 spin_unlock_bh(&sta->lock);
275 return -EALREADY; 293 if (reason != AGG_STOP_DESTROY_STA)
294 return -EALREADY;
295 ret = drv_ampdu_action(local, sta->sdata,
296 IEEE80211_AMPDU_TX_STOP_FLUSH_CONT,
297 &sta->sta, tid, NULL, 0);
298 WARN_ON_ONCE(ret);
299 goto remove_tid_tx;
276 } 300 }
277 301
278 if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { 302 if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
@@ -319,8 +343,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
319 WLAN_BACK_INITIATOR; 343 WLAN_BACK_INITIATOR;
320 tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST; 344 tid_tx->tx_stop = reason == AGG_STOP_LOCAL_REQUEST;
321 345
322 ret = drv_ampdu_action(local, sta->sdata, 346 ret = drv_ampdu_action(local, sta->sdata, action,
323 IEEE80211_AMPDU_TX_STOP,
324 &sta->sta, tid, NULL, 0); 347 &sta->sta, tid, NULL, 0);
325 348
326 /* HW shall not deny going back to legacy */ 349 /* HW shall not deny going back to legacy */
@@ -331,7 +354,14 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
331 */ 354 */
332 } 355 }
333 356
334 return ret; 357 if (reason == AGG_STOP_DESTROY_STA) {
358 remove_tid_tx:
359 spin_lock_bh(&sta->lock);
360 ieee80211_remove_tid_tx(sta, tid);
361 spin_unlock_bh(&sta->lock);
362 }
363
364 return 0;
335} 365}
336 366
337/* 367/*