diff options
-rw-r--r-- | drivers/net/wireless/ath/ath9k/htc_drv_main.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/carl9170/main.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlegacy/4965-mac.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/dvm/mac80211.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/mac80211_hwsim.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/mwl8k.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/rt2x00/rt2800lib.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/rtlwifi/core.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ti/wlcore/main.c | 4 | ||||
-rw-r--r-- | include/net/mac80211.h | 22 | ||||
-rw-r--r-- | net/mac80211/agg-tx.c | 40 |
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 | */ |
2042 | enum ieee80211_ampdu_mlme_action { | 2052 | enum 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 | /* |