aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/agg-tx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/agg-tx.c')
-rw-r--r--net/mac80211/agg-tx.c59
1 files changed, 38 insertions, 21 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c
index 63d852cb4ca2..cd5125f77cc5 100644
--- a/net/mac80211/agg-tx.c
+++ b/net/mac80211/agg-tx.c
@@ -136,6 +136,14 @@ void ieee80211_send_bar(struct ieee80211_sub_if_data *sdata, u8 *ra, u16 tid, u1
136 ieee80211_tx_skb(sdata, skb); 136 ieee80211_tx_skb(sdata, skb);
137} 137}
138 138
139void ieee80211_assign_tid_tx(struct sta_info *sta, int tid,
140 struct tid_ampdu_tx *tid_tx)
141{
142 lockdep_assert_held(&sta->ampdu_mlme.mtx);
143 lockdep_assert_held(&sta->lock);
144 rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx);
145}
146
139static void kfree_tid_tx(struct rcu_head *rcu_head) 147static void kfree_tid_tx(struct rcu_head *rcu_head)
140{ 148{
141 struct tid_ampdu_tx *tid_tx = 149 struct tid_ampdu_tx *tid_tx =
@@ -149,19 +157,22 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
149 bool tx) 157 bool tx)
150{ 158{
151 struct ieee80211_local *local = sta->local; 159 struct ieee80211_local *local = sta->local;
152 struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; 160 struct tid_ampdu_tx *tid_tx;
153 int ret; 161 int ret;
154 162
155 lockdep_assert_held(&sta->ampdu_mlme.mtx); 163 lockdep_assert_held(&sta->ampdu_mlme.mtx);
156 164
157 if (!tid_tx)
158 return -ENOENT;
159
160 spin_lock_bh(&sta->lock); 165 spin_lock_bh(&sta->lock);
161 166
167 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
168 if (!tid_tx) {
169 spin_unlock_bh(&sta->lock);
170 return -ENOENT;
171 }
172
162 if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { 173 if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) {
163 /* not even started yet! */ 174 /* not even started yet! */
164 rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); 175 ieee80211_assign_tid_tx(sta, tid, NULL);
165 spin_unlock_bh(&sta->lock); 176 spin_unlock_bh(&sta->lock);
166 call_rcu(&tid_tx->rcu_head, kfree_tid_tx); 177 call_rcu(&tid_tx->rcu_head, kfree_tid_tx);
167 return 0; 178 return 0;
@@ -283,13 +294,13 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid)
283 294
284void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) 295void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
285{ 296{
286 struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; 297 struct tid_ampdu_tx *tid_tx;
287 struct ieee80211_local *local = sta->local; 298 struct ieee80211_local *local = sta->local;
288 struct ieee80211_sub_if_data *sdata = sta->sdata; 299 struct ieee80211_sub_if_data *sdata = sta->sdata;
289 u16 start_seq_num; 300 u16 start_seq_num;
290 int ret; 301 int ret;
291 302
292 lockdep_assert_held(&sta->ampdu_mlme.mtx); 303 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
293 304
294 /* 305 /*
295 * While we're asking the driver about the aggregation, 306 * While we're asking the driver about the aggregation,
@@ -318,7 +329,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid)
318 " tid %d\n", tid); 329 " tid %d\n", tid);
319#endif 330#endif
320 spin_lock_bh(&sta->lock); 331 spin_lock_bh(&sta->lock);
321 rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); 332 ieee80211_assign_tid_tx(sta, tid, NULL);
322 spin_unlock_bh(&sta->lock); 333 spin_unlock_bh(&sta->lock);
323 334
324 ieee80211_wake_queue_agg(local, tid); 335 ieee80211_wake_queue_agg(local, tid);
@@ -396,9 +407,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
396 goto err_unlock_sta; 407 goto err_unlock_sta;
397 } 408 }
398 409
399 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 410 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
400 /* check if the TID is not in aggregation flow already */ 411 /* check if the TID is not in aggregation flow already */
401 if (tid_tx) { 412 if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) {
402#ifdef CONFIG_MAC80211_HT_DEBUG 413#ifdef CONFIG_MAC80211_HT_DEBUG
403 printk(KERN_DEBUG "BA request denied - session is not " 414 printk(KERN_DEBUG "BA request denied - session is not "
404 "idle on tid %u\n", tid); 415 "idle on tid %u\n", tid);
@@ -433,8 +444,11 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid,
433 sta->ampdu_mlme.dialog_token_allocator++; 444 sta->ampdu_mlme.dialog_token_allocator++;
434 tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator; 445 tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator;
435 446
436 /* finally, assign it to the array */ 447 /*
437 rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx); 448 * Finally, assign it to the start array; the work item will
449 * collect it and move it to the normal array.
450 */
451 sta->ampdu_mlme.tid_start_tx[tid] = tid_tx;
438 452
439 ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); 453 ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work);
440 454
@@ -480,16 +494,19 @@ ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid)
480static void ieee80211_agg_tx_operational(struct ieee80211_local *local, 494static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
481 struct sta_info *sta, u16 tid) 495 struct sta_info *sta, u16 tid)
482{ 496{
497 struct tid_ampdu_tx *tid_tx;
498
483 lockdep_assert_held(&sta->ampdu_mlme.mtx); 499 lockdep_assert_held(&sta->ampdu_mlme.mtx);
484 500
501 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
502
485#ifdef CONFIG_MAC80211_HT_DEBUG 503#ifdef CONFIG_MAC80211_HT_DEBUG
486 printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); 504 printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid);
487#endif 505#endif
488 506
489 drv_ampdu_action(local, sta->sdata, 507 drv_ampdu_action(local, sta->sdata,
490 IEEE80211_AMPDU_TX_OPERATIONAL, 508 IEEE80211_AMPDU_TX_OPERATIONAL,
491 &sta->sta, tid, NULL, 509 &sta->sta, tid, NULL, tid_tx->buf_size);
492 sta->ampdu_mlme.tid_tx[tid]->buf_size);
493 510
494 /* 511 /*
495 * synchronize with TX path, while splicing the TX path 512 * synchronize with TX path, while splicing the TX path
@@ -497,13 +514,13 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local,
497 */ 514 */
498 spin_lock_bh(&sta->lock); 515 spin_lock_bh(&sta->lock);
499 516
500 ieee80211_agg_splice_packets(local, sta->ampdu_mlme.tid_tx[tid], tid); 517 ieee80211_agg_splice_packets(local, tid_tx, tid);
501 /* 518 /*
502 * Now mark as operational. This will be visible 519 * Now mark as operational. This will be visible
503 * in the TX path, and lets it go lock-free in 520 * in the TX path, and lets it go lock-free in
504 * the common case. 521 * the common case.
505 */ 522 */
506 set_bit(HT_AGG_STATE_OPERATIONAL, &sta->ampdu_mlme.tid_tx[tid]->state); 523 set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state);
507 ieee80211_agg_splice_finish(local, tid); 524 ieee80211_agg_splice_finish(local, tid);
508 525
509 spin_unlock_bh(&sta->lock); 526 spin_unlock_bh(&sta->lock);
@@ -537,7 +554,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid)
537 } 554 }
538 555
539 mutex_lock(&sta->ampdu_mlme.mtx); 556 mutex_lock(&sta->ampdu_mlme.mtx);
540 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 557 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
541 558
542 if (WARN_ON(!tid_tx)) { 559 if (WARN_ON(!tid_tx)) {
543#ifdef CONFIG_MAC80211_HT_DEBUG 560#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -615,7 +632,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid)
615 return -EINVAL; 632 return -EINVAL;
616 633
617 spin_lock_bh(&sta->lock); 634 spin_lock_bh(&sta->lock);
618 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 635 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
619 636
620 if (!tid_tx) { 637 if (!tid_tx) {
621 ret = -ENOENT; 638 ret = -ENOENT;
@@ -671,7 +688,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
671 688
672 mutex_lock(&sta->ampdu_mlme.mtx); 689 mutex_lock(&sta->ampdu_mlme.mtx);
673 spin_lock_bh(&sta->lock); 690 spin_lock_bh(&sta->lock);
674 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 691 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
675 692
676 if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { 693 if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) {
677#ifdef CONFIG_MAC80211_HT_DEBUG 694#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -697,7 +714,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid)
697 ieee80211_agg_splice_packets(local, tid_tx, tid); 714 ieee80211_agg_splice_packets(local, tid_tx, tid);
698 715
699 /* future packets must not find the tid_tx struct any more */ 716 /* future packets must not find the tid_tx struct any more */
700 rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); 717 ieee80211_assign_tid_tx(sta, tid, NULL);
701 718
702 ieee80211_agg_splice_finish(local, tid); 719 ieee80211_agg_splice_finish(local, tid);
703 720
@@ -752,7 +769,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local,
752 769
753 mutex_lock(&sta->ampdu_mlme.mtx); 770 mutex_lock(&sta->ampdu_mlme.mtx);
754 771
755 tid_tx = sta->ampdu_mlme.tid_tx[tid]; 772 tid_tx = rcu_dereference_protected_tid_tx(sta, tid);
756 if (!tid_tx) 773 if (!tid_tx)
757 goto out; 774 goto out;
758 775