aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2010-10-05 13:37:40 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-10-06 16:30:40 -0400
commit53f73c09d64f1fa7d7e6e8b6bb7468d42eddc92d (patch)
treea9284928f65ad33b3cbef9625871bb0c0116f875
parent845d708e62f08a45ff716fdb270c52585cad31d0 (diff)
mac80211: avoid transmitting delBA to old AP
When roaming while we have active BA session, we can end up transmitting delBA frames to the old AP while we're already on the new AP's channel, which can cause warnings. Simply avoid sending those frames, but still tear down the internal session state, since they are not really necessary anyway as we will implicitly disassociate when sending the association to the new AP. Signed-off-by: Johannes Berg <johannes.berg@intel.com> Acked-by: Luis R. Rodriguez <lrodriguez@atheros.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
-rw-r--r--net/mac80211/agg-rx.c8
-rw-r--r--net/mac80211/agg-tx.c14
-rw-r--r--net/mac80211/debugfs_sta.c3
-rw-r--r--net/mac80211/ht.c17
-rw-r--r--net/mac80211/ieee80211_i.h12
-rw-r--r--net/mac80211/iface.c3
-rw-r--r--net/mac80211/mlme.c18
-rw-r--r--net/mac80211/pm.c2
-rw-r--r--net/mac80211/sta_info.c2
-rw-r--r--net/mac80211/sta_info.h2
-rw-r--r--net/mac80211/util.c2
11 files changed, 48 insertions, 35 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 58eab9e8e4ee..720b7a84af59 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -56,7 +56,7 @@ static void ieee80211_free_tid_rx(struct rcu_head *h)
56} 56}
57 57
58void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 58void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
59 u16 initiator, u16 reason) 59 u16 initiator, u16 reason, bool tx)
60{ 60{
61 struct ieee80211_local *local = sta->local; 61 struct ieee80211_local *local = sta->local;
62 struct tid_ampdu_rx *tid_rx; 62 struct tid_ampdu_rx *tid_rx;
@@ -81,7 +81,7 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
81 "aggregation for tid %d\n", tid); 81 "aggregation for tid %d\n", tid);
82 82
83 /* check if this is a self generated aggregation halt */ 83 /* check if this is a self generated aggregation halt */
84 if (initiator == WLAN_BACK_RECIPIENT) 84 if (initiator == WLAN_BACK_RECIPIENT && tx)
85 ieee80211_send_delba(sta->sdata, sta->sta.addr, 85 ieee80211_send_delba(sta->sdata, sta->sta.addr,
86 tid, 0, reason); 86 tid, 0, reason);
87 87
@@ -92,10 +92,10 @@ void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
92} 92}
93 93
94void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 94void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
95 u16 initiator, u16 reason) 95 u16 initiator, u16 reason, bool tx)
96{ 96{
97 mutex_lock(&sta->ampdu_mlme.mtx); 97 mutex_lock(&sta->ampdu_mlme.mtx);
98 ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason); 98 ___ieee80211_stop_rx_ba_session(sta, tid, initiator, reason, tx);
99 mutex_unlock(&sta->ampdu_mlme.mtx); 99 mutex_unlock(&sta->ampdu_mlme.mtx);
100} 100}
101 101
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 8f23401832b7..d4679b265ba8 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -145,7 +145,8 @@ static void kfree_tid_tx(struct rcu_head *rcu_head)
145} 145}
146 146
147int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, 147int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
148 enum ieee80211_back_parties initiator) 148 enum ieee80211_back_parties initiator,
149 bool tx)
149{ 150{
150 struct ieee80211_local *local = sta->local; 151 struct ieee80211_local *local = sta->local;
151 struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; 152 struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid];
@@ -185,6 +186,7 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
185 clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); 186 clear_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
186 187
187 tid_tx->stop_initiator = initiator; 188 tid_tx->stop_initiator = initiator;
189 tid_tx->tx_stop = tx;
188 190
189 ret = drv_ampdu_action(local, sta->sdata, 191 ret = drv_ampdu_action(local, sta->sdata,
190 IEEE80211_AMPDU_TX_STOP, 192 IEEE80211_AMPDU_TX_STOP,
@@ -577,13 +579,14 @@ void ieee80211_start_tx_ba_cb_irqsafe(struct ieee80211_vif *vif,
577EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe); 579EXPORT_SYMBOL(ieee80211_start_tx_ba_cb_irqsafe);
578 580
579int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, 581int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
580 enum ieee80211_back_parties initiator) 582 enum ieee80211_back_parties initiator,
583 bool tx)
581{ 584{
582 int ret; 585 int ret;
583 586
584 mutex_lock(&sta->ampdu_mlme.mtx); 587 mutex_lock(&sta->ampdu_mlme.mtx);
585 588
586 ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator); 589 ret = ___ieee80211_stop_tx_ba_session(sta, tid, initiator, tx);
587 590
588 mutex_unlock(&sta->ampdu_mlme.mtx); 591 mutex_unlock(&sta->ampdu_mlme.mtx);
589 592
@@ -672,7 +675,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
672 goto unlock_sta; 675 goto unlock_sta;
673 } 676 }
674 677
675 if (tid_tx->stop_initiator == WLAN_BACK_INITIATOR) 678 if (tid_tx->stop_initiator == WLAN_BACK_INITIATOR && tid_tx->tx_stop)
676 ieee80211_send_delba(sta->sdata, ra, tid, 679 ieee80211_send_delba(sta->sdata, ra, tid,
677 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE); 680 WLAN_BACK_INITIATOR, WLAN_REASON_QSTA_NOT_USE);
678 681
@@ -772,7 +775,8 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
772 775
773 sta->ampdu_mlme.addba_req_num[tid] = 0; 776 sta->ampdu_mlme.addba_req_num[tid] = 0;
774 } else { 777 } else {
775 ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR); 778 ___ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_INITIATOR,
779 true);
776 } 780 }
777 781
778 out: 782 out:
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index 6b7ff9fb4604..50c40ea3cb4d 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -196,7 +196,8 @@ static ssize_t sta_agg_status_write(struct file *file, const char __user *userbu
196 else 196 else
197 ret = ieee80211_stop_tx_ba_session(&sta->sta, tid); 197 ret = ieee80211_stop_tx_ba_session(&sta->sta, tid);
198 } else { 198 } else {
199 __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT, 3); 199 __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
200 3, true);
200 ret = 0; 201 ret = 0;
201 } 202 }
202 203
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c
index 11f74f5f7b2f..4214bb6e12fc 100644
--- a/net/mac80211/ht.c
+++ b/net/mac80211/ht.c
@@ -101,16 +101,16 @@ void ieee80211_ht_cap_ie_to_sta_ht_cap(struct ieee80211_supported_band *sband,
101 ht_cap->mcs.rx_mask[32/8] |= 1; 101 ht_cap->mcs.rx_mask[32/8] |= 1;
102} 102}
103 103
104void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta) 104void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx)
105{ 105{
106 int i; 106 int i;
107 107
108 cancel_work_sync(&sta->ampdu_mlme.work); 108 cancel_work_sync(&sta->ampdu_mlme.work);
109 109
110 for (i = 0; i < STA_TID_NUM; i++) { 110 for (i = 0; i < STA_TID_NUM; i++) {
111 __ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR); 111 __ieee80211_stop_tx_ba_session(sta, i, WLAN_BACK_INITIATOR, tx);
112 __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT, 112 __ieee80211_stop_rx_ba_session(sta, i, WLAN_BACK_RECIPIENT,
113 WLAN_REASON_QSTA_LEAVE_QBSS); 113 WLAN_REASON_QSTA_LEAVE_QBSS, tx);
114 } 114 }
115} 115}
116 116
@@ -135,7 +135,7 @@ void ieee80211_ba_session_work(struct work_struct *work)
135 if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired)) 135 if (test_and_clear_bit(tid, sta->ampdu_mlme.tid_rx_timer_expired))
136 ___ieee80211_stop_rx_ba_session( 136 ___ieee80211_stop_rx_ba_session(
137 sta, tid, WLAN_BACK_RECIPIENT, 137 sta, tid, WLAN_BACK_RECIPIENT,
138 WLAN_REASON_QSTA_TIMEOUT); 138 WLAN_REASON_QSTA_TIMEOUT, true);
139 139
140 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 140 tid_tx = sta->ampdu_mlme.tid_tx[tid];
141 if (!tid_tx) 141 if (!tid_tx)
@@ -146,7 +146,8 @@ void ieee80211_ba_session_work(struct work_struct *work)
146 else if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP, 146 else if (test_and_clear_bit(HT_AGG_STATE_WANT_STOP,
147 &tid_tx->state)) 147 &tid_tx->state))
148 ___ieee80211_stop_tx_ba_session(sta, tid, 148 ___ieee80211_stop_tx_ba_session(sta, tid,
149 WLAN_BACK_INITIATOR); 149 WLAN_BACK_INITIATOR,
150 true);
150 } 151 }
151 mutex_unlock(&sta->ampdu_mlme.mtx); 152 mutex_unlock(&sta->ampdu_mlme.mtx);
152} 153}
@@ -214,9 +215,11 @@ void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
214#endif /* CONFIG_MAC80211_HT_DEBUG */ 215#endif /* CONFIG_MAC80211_HT_DEBUG */
215 216
216 if (initiator == WLAN_BACK_INITIATOR) 217 if (initiator == WLAN_BACK_INITIATOR)
217 __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0); 218 __ieee80211_stop_rx_ba_session(sta, tid, WLAN_BACK_INITIATOR, 0,
219 true);
218 else 220 else
219 __ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_RECIPIENT); 221 __ieee80211_stop_tx_ba_session(sta, tid, WLAN_BACK_RECIPIENT,
222 true);
220} 223}
221 224
222int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata, 225int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 08509e212841..76c2b50ec6f8 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1175,10 +1175,10 @@ int ieee80211_send_smps_action(struct ieee80211_sub_if_data *sdata,
1175void ieee80211_request_smps_work(struct work_struct *work); 1175void ieee80211_request_smps_work(struct work_struct *work);
1176 1176
1177void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 1177void ___ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
1178 u16 initiator, u16 reason); 1178 u16 initiator, u16 reason, bool stop);
1179void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid, 1179void __ieee80211_stop_rx_ba_session(struct sta_info *sta, u16 tid,
1180 u16 initiator, u16 reason); 1180 u16 initiator, u16 reason, bool stop);
1181void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta); 1181void ieee80211_sta_tear_down_BA_sessions(struct sta_info *sta, bool tx);
1182void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata, 1182void ieee80211_process_delba(struct ieee80211_sub_if_data *sdata,
1183 struct sta_info *sta, 1183 struct sta_info *sta,
1184 struct ieee80211_mgmt *mgmt, size_t len); 1184 struct ieee80211_mgmt *mgmt, size_t len);
@@ -1192,9 +1192,11 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
1192 size_t len); 1192 size_t len);
1193 1193
1194int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, 1194int __ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
1195 enum ieee80211_back_parties initiator); 1195 enum ieee80211_back_parties initiator,
1196 bool tx);
1196int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, 1197int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
1197 enum ieee80211_back_parties initiator); 1198 enum ieee80211_back_parties initiator,
1199 bool tx);
1198void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid); 1200void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid);
1199void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid); 1201void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid);
1200void ieee80211_ba_session_work(struct work_struct *work); 1202void ieee80211_ba_session_work(struct work_struct *work);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 438a2f51420e..e99d1b60557c 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -796,7 +796,8 @@ static void ieee80211_iface_work(struct work_struct *work)
796 796
797 __ieee80211_stop_rx_ba_session( 797 __ieee80211_stop_rx_ba_session(
798 sta, tid, WLAN_BACK_RECIPIENT, 798 sta, tid, WLAN_BACK_RECIPIENT,
799 WLAN_REASON_QSTA_REQUIRE_SETUP); 799 WLAN_REASON_QSTA_REQUIRE_SETUP,
800 true);
800 } 801 }
801 mutex_unlock(&local->sta_mtx); 802 mutex_unlock(&local->sta_mtx);
802 } else switch (sdata->vif.type) { 803 } else switch (sdata->vif.type) {
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index cd13aa82f835..5695c94c49aa 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -921,7 +921,7 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
921} 921}
922 922
923static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, 923static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
924 bool remove_sta) 924 bool remove_sta, bool tx)
925{ 925{
926 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd; 926 struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
927 struct ieee80211_local *local = sdata->local; 927 struct ieee80211_local *local = sdata->local;
@@ -960,7 +960,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
960 sta = sta_info_get(sdata, bssid); 960 sta = sta_info_get(sdata, bssid);
961 if (sta) { 961 if (sta) {
962 set_sta_flags(sta, WLAN_STA_BLOCK_BA); 962 set_sta_flags(sta, WLAN_STA_BLOCK_BA);
963 ieee80211_sta_tear_down_BA_sessions(sta); 963 ieee80211_sta_tear_down_BA_sessions(sta, tx);
964 } 964 }
965 mutex_unlock(&local->sta_mtx); 965 mutex_unlock(&local->sta_mtx);
966 966
@@ -1124,7 +1124,7 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
1124 1124
1125 printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid); 1125 printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid);
1126 1126
1127 ieee80211_set_disassoc(sdata, true); 1127 ieee80211_set_disassoc(sdata, true, true);
1128 mutex_unlock(&ifmgd->mtx); 1128 mutex_unlock(&ifmgd->mtx);
1129 1129
1130 mutex_lock(&local->mtx); 1130 mutex_lock(&local->mtx);
@@ -1197,7 +1197,7 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
1197 printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n", 1197 printk(KERN_DEBUG "%s: deauthenticated from %pM (Reason: %u)\n",
1198 sdata->name, bssid, reason_code); 1198 sdata->name, bssid, reason_code);
1199 1199
1200 ieee80211_set_disassoc(sdata, true); 1200 ieee80211_set_disassoc(sdata, true, false);
1201 mutex_lock(&sdata->local->mtx); 1201 mutex_lock(&sdata->local->mtx);
1202 ieee80211_recalc_idle(sdata->local); 1202 ieee80211_recalc_idle(sdata->local);
1203 mutex_unlock(&sdata->local->mtx); 1203 mutex_unlock(&sdata->local->mtx);
@@ -1229,7 +1229,7 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
1229 printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n", 1229 printk(KERN_DEBUG "%s: disassociated from %pM (Reason: %u)\n",
1230 sdata->name, mgmt->sa, reason_code); 1230 sdata->name, mgmt->sa, reason_code);
1231 1231
1232 ieee80211_set_disassoc(sdata, true); 1232 ieee80211_set_disassoc(sdata, true, false);
1233 mutex_lock(&sdata->local->mtx); 1233 mutex_lock(&sdata->local->mtx);
1234 ieee80211_recalc_idle(sdata->local); 1234 ieee80211_recalc_idle(sdata->local);
1235 mutex_unlock(&sdata->local->mtx); 1235 mutex_unlock(&sdata->local->mtx);
@@ -1880,7 +1880,7 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
1880 printk(KERN_DEBUG "No probe response from AP %pM" 1880 printk(KERN_DEBUG "No probe response from AP %pM"
1881 " after %dms, disconnecting.\n", 1881 " after %dms, disconnecting.\n",
1882 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ); 1882 bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
1883 ieee80211_set_disassoc(sdata, true); 1883 ieee80211_set_disassoc(sdata, true, true);
1884 mutex_unlock(&ifmgd->mtx); 1884 mutex_unlock(&ifmgd->mtx);
1885 mutex_lock(&local->mtx); 1885 mutex_lock(&local->mtx);
1886 ieee80211_recalc_idle(local); 1886 ieee80211_recalc_idle(local);
@@ -2204,7 +2204,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
2204 } 2204 }
2205 2205
2206 /* Trying to reassociate - clear previous association state */ 2206 /* Trying to reassociate - clear previous association state */
2207 ieee80211_set_disassoc(sdata, true); 2207 ieee80211_set_disassoc(sdata, true, false);
2208 } 2208 }
2209 mutex_unlock(&ifmgd->mtx); 2209 mutex_unlock(&ifmgd->mtx);
2210 2210
@@ -2318,7 +2318,7 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
2318 2318
2319 memcpy(bssid, req->bss->bssid, ETH_ALEN); 2319 memcpy(bssid, req->bss->bssid, ETH_ALEN);
2320 if (ifmgd->associated == req->bss) { 2320 if (ifmgd->associated == req->bss) {
2321 ieee80211_set_disassoc(sdata, false); 2321 ieee80211_set_disassoc(sdata, false, true);
2322 mutex_unlock(&ifmgd->mtx); 2322 mutex_unlock(&ifmgd->mtx);
2323 assoc_bss = true; 2323 assoc_bss = true;
2324 } else { 2324 } else {
@@ -2401,7 +2401,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
2401 sdata->name, req->bss->bssid, req->reason_code); 2401 sdata->name, req->bss->bssid, req->reason_code);
2402 2402
2403 memcpy(bssid, req->bss->bssid, ETH_ALEN); 2403 memcpy(bssid, req->bss->bssid, ETH_ALEN);
2404 ieee80211_set_disassoc(sdata, false); 2404 ieee80211_set_disassoc(sdata, false, true);
2405 2405
2406 mutex_unlock(&ifmgd->mtx); 2406 mutex_unlock(&ifmgd->mtx);
2407 2407
diff --git a/net/mac80211/pm.c b/net/mac80211/pm.c
index ce671dfd238c..e3e2bce3bb41 100644
--- a/net/mac80211/pm.c
+++ b/net/mac80211/pm.c
@@ -46,7 +46,7 @@ int __ieee80211_suspend(struct ieee80211_hw *hw)
46 list_for_each_entry(sta, &local->sta_list, list) { 46 list_for_each_entry(sta, &local->sta_list, list) {
47 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) { 47 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
48 set_sta_flags(sta, WLAN_STA_BLOCK_BA); 48 set_sta_flags(sta, WLAN_STA_BLOCK_BA);
49 ieee80211_sta_tear_down_BA_sessions(sta); 49 ieee80211_sta_tear_down_BA_sessions(sta, true);
50 } 50 }
51 51
52 if (sta->uploaded) { 52 if (sta->uploaded) {
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index ca2cba9cea87..aeaf2d6fccc8 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -633,7 +633,7 @@ static int __must_check __sta_info_destroy(struct sta_info *sta)
633 * will be sufficient. 633 * will be sufficient.
634 */ 634 */
635 set_sta_flags(sta, WLAN_STA_BLOCK_BA); 635 set_sta_flags(sta, WLAN_STA_BLOCK_BA);
636 ieee80211_sta_tear_down_BA_sessions(sta); 636 ieee80211_sta_tear_down_BA_sessions(sta, true);
637 637
638 spin_lock_irqsave(&local->sta_lock, flags); 638 spin_lock_irqsave(&local->sta_lock, flags);
639 ret = sta_info_hash_del(local, sta); 639 ret = sta_info_hash_del(local, sta);
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 810c5ce98316..cf21a2e8134f 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -79,6 +79,7 @@ enum ieee80211_sta_info_flags {
79 * @dialog_token: dialog token for aggregation session 79 * @dialog_token: dialog token for aggregation session
80 * @state: session state (see above) 80 * @state: session state (see above)
81 * @stop_initiator: initiator of a session stop 81 * @stop_initiator: initiator of a session stop
82 * @tx_stop: TX DelBA frame when stopping
82 * 83 *
83 * This structure is protected by RCU and the per-station 84 * This structure is protected by RCU and the per-station
84 * spinlock. Assignments to the array holding it must hold 85 * spinlock. Assignments to the array holding it must hold
@@ -95,6 +96,7 @@ struct tid_ampdu_tx {
95 unsigned long state; 96 unsigned long state;
96 u8 dialog_token; 97 u8 dialog_token;
97 u8 stop_initiator; 98 u8 stop_initiator;
99 bool tx_stop;
98}; 100};
99 101
100/** 102/**
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 4ee8f2b53cb7..0b6fc92bc0d7 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -1221,7 +1221,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1221 mutex_lock(&local->sta_mtx); 1221 mutex_lock(&local->sta_mtx);
1222 1222
1223 list_for_each_entry(sta, &local->sta_list, list) { 1223 list_for_each_entry(sta, &local->sta_list, list) {
1224 ieee80211_sta_tear_down_BA_sessions(sta); 1224 ieee80211_sta_tear_down_BA_sessions(sta, true);
1225 clear_sta_flags(sta, WLAN_STA_BLOCK_BA); 1225 clear_sta_flags(sta, WLAN_STA_BLOCK_BA);
1226 } 1226 }
1227 1227