diff options
| -rw-r--r-- | net/mac80211/agg-tx.c | 86 |
1 files changed, 41 insertions, 45 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 331472ce038c..d448f7a3dbc0 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
| @@ -302,6 +302,38 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) | |||
| 302 | __release(agg_queue); | 302 | __release(agg_queue); |
| 303 | } | 303 | } |
| 304 | 304 | ||
| 305 | /* | ||
| 306 | * splice packets from the STA's pending to the local pending, | ||
| 307 | * requires a call to ieee80211_agg_splice_finish later | ||
| 308 | */ | ||
| 309 | static void __acquires(agg_queue) | ||
| 310 | ieee80211_agg_splice_packets(struct ieee80211_local *local, | ||
| 311 | struct tid_ampdu_tx *tid_tx, u16 tid) | ||
| 312 | { | ||
| 313 | int queue = ieee80211_ac_from_tid(tid); | ||
| 314 | unsigned long flags; | ||
| 315 | |||
| 316 | ieee80211_stop_queue_agg(local, tid); | ||
| 317 | |||
| 318 | if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" | ||
| 319 | " from the pending queue\n", tid)) | ||
| 320 | return; | ||
| 321 | |||
| 322 | if (!skb_queue_empty(&tid_tx->pending)) { | ||
| 323 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
| 324 | /* copy over remaining packets */ | ||
| 325 | skb_queue_splice_tail_init(&tid_tx->pending, | ||
| 326 | &local->pending[queue]); | ||
| 327 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
| 328 | } | ||
| 329 | } | ||
| 330 | |||
| 331 | static void __releases(agg_queue) | ||
| 332 | ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) | ||
| 333 | { | ||
| 334 | ieee80211_wake_queue_agg(local, tid); | ||
| 335 | } | ||
| 336 | |||
| 305 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | 337 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) |
| 306 | { | 338 | { |
| 307 | struct tid_ampdu_tx *tid_tx; | 339 | struct tid_ampdu_tx *tid_tx; |
| @@ -313,19 +345,17 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
| 313 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | 345 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
| 314 | 346 | ||
| 315 | /* | 347 | /* |
| 316 | * While we're asking the driver about the aggregation, | 348 | * Start queuing up packets for this aggregation session. |
| 317 | * stop the AC queue so that we don't have to worry | 349 | * We're going to release them once the driver is OK with |
| 318 | * about frames that came in while we were doing that, | 350 | * that. |
| 319 | * which would require us to put them to the AC pending | ||
| 320 | * afterwards which just makes the code more complex. | ||
| 321 | */ | 351 | */ |
| 322 | ieee80211_stop_queue_agg(local, tid); | ||
| 323 | |||
| 324 | clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); | 352 | clear_bit(HT_AGG_STATE_WANT_START, &tid_tx->state); |
| 325 | 353 | ||
| 326 | /* | 354 | /* |
| 327 | * make sure no packets are being processed to get | 355 | * Make sure no packets are being processed. This ensures that |
| 328 | * valid starting sequence number | 356 | * we have a valid starting sequence number and that in-flight |
| 357 | * packets have been flushed out and no packets for this TID | ||
| 358 | * will go into the driver during the ampdu_action call. | ||
| 329 | */ | 359 | */ |
| 330 | synchronize_net(); | 360 | synchronize_net(); |
| 331 | 361 | ||
| @@ -339,17 +369,15 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
| 339 | " tid %d\n", tid); | 369 | " tid %d\n", tid); |
| 340 | #endif | 370 | #endif |
| 341 | spin_lock_bh(&sta->lock); | 371 | spin_lock_bh(&sta->lock); |
| 372 | ieee80211_agg_splice_packets(local, tid_tx, tid); | ||
| 342 | ieee80211_assign_tid_tx(sta, tid, NULL); | 373 | ieee80211_assign_tid_tx(sta, tid, NULL); |
| 374 | ieee80211_agg_splice_finish(local, tid); | ||
| 343 | spin_unlock_bh(&sta->lock); | 375 | spin_unlock_bh(&sta->lock); |
| 344 | 376 | ||
| 345 | ieee80211_wake_queue_agg(local, tid); | ||
| 346 | kfree_rcu(tid_tx, rcu_head); | 377 | kfree_rcu(tid_tx, rcu_head); |
| 347 | return; | 378 | return; |
| 348 | } | 379 | } |
| 349 | 380 | ||
| 350 | /* we can take packets again now */ | ||
| 351 | ieee80211_wake_queue_agg(local, tid); | ||
| 352 | |||
| 353 | /* activate the timer for the recipient's addBA response */ | 381 | /* activate the timer for the recipient's addBA response */ |
| 354 | mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); | 382 | mod_timer(&tid_tx->addba_resp_timer, jiffies + ADDBA_RESP_INTERVAL); |
| 355 | #ifdef CONFIG_MAC80211_HT_DEBUG | 383 | #ifdef CONFIG_MAC80211_HT_DEBUG |
| @@ -465,38 +493,6 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
| 465 | } | 493 | } |
| 466 | EXPORT_SYMBOL(ieee80211_start_tx_ba_session); | 494 | EXPORT_SYMBOL(ieee80211_start_tx_ba_session); |
| 467 | 495 | ||
| 468 | /* | ||
| 469 | * splice packets from the STA's pending to the local pending, | ||
| 470 | * requires a call to ieee80211_agg_splice_finish later | ||
| 471 | */ | ||
| 472 | static void __acquires(agg_queue) | ||
| 473 | ieee80211_agg_splice_packets(struct ieee80211_local *local, | ||
| 474 | struct tid_ampdu_tx *tid_tx, u16 tid) | ||
| 475 | { | ||
| 476 | int queue = ieee80211_ac_from_tid(tid); | ||
| 477 | unsigned long flags; | ||
| 478 | |||
| 479 | ieee80211_stop_queue_agg(local, tid); | ||
| 480 | |||
| 481 | if (WARN(!tid_tx, "TID %d gone but expected when splicing aggregates" | ||
| 482 | " from the pending queue\n", tid)) | ||
| 483 | return; | ||
| 484 | |||
| 485 | if (!skb_queue_empty(&tid_tx->pending)) { | ||
| 486 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
| 487 | /* copy over remaining packets */ | ||
| 488 | skb_queue_splice_tail_init(&tid_tx->pending, | ||
| 489 | &local->pending[queue]); | ||
| 490 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
| 491 | } | ||
| 492 | } | ||
| 493 | |||
| 494 | static void __releases(agg_queue) | ||
| 495 | ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) | ||
| 496 | { | ||
| 497 | ieee80211_wake_queue_agg(local, tid); | ||
| 498 | } | ||
| 499 | |||
| 500 | static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | 496 | static void ieee80211_agg_tx_operational(struct ieee80211_local *local, |
| 501 | struct sta_info *sta, u16 tid) | 497 | struct sta_info *sta, u16 tid) |
| 502 | { | 498 | { |
