aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/agg-tx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes.berg@intel.com>2012-07-18 07:51:25 -0400
committerJohannes Berg <johannes.berg@intel.com>2013-01-03 07:01:42 -0500
commit18b559d5db47c86b10c14590aa2d26c0243c39e4 (patch)
tree15db56605202e2b43628b0f441ca6275bf9b2d50 /net/mac80211/agg-tx.c
parent30bf5f1f433c7612857ed13c50525945c483dfe0 (diff)
mac80211: split TX aggregation stop action
When TX aggregation is stopped, there are a few different cases: - connection with the peer was dropped - session stop was requested locally - session stop was requested by the peer - connection was dropped while a session is stopping The behaviour in these cases should be different, if the connection is dropped then the driver should drop all frames, otherwise the frames may continue to be transmitted, aggregated in the case of a locally requested session stop or unaggregated in the case of the peer requesting session stop. Split these different cases so that the driver can act accordingly; however, treat local and remote stop the same way and ask the driver to not send frames as aggregated packets any more. In the case of connection drop, the stop callback the driver is otherwise supposed to call is no longer required. Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Diffstat (limited to 'net/mac80211/agg-tx.c')
-rw-r--r--net/mac80211/agg-tx.c40
1 files changed, 35 insertions, 5 deletions
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/*