diff options
Diffstat (limited to 'net/mac80211/agg-tx.c')
-rw-r--r-- | net/mac80211/agg-tx.c | 59 |
1 files changed, 38 insertions, 21 deletions
diff --git a/net/mac80211/agg-tx.c b/net/mac80211/agg-tx.c index 53defafb9aae..c8be8eff70da 100644 --- a/net/mac80211/agg-tx.c +++ b/net/mac80211/agg-tx.c | |||
@@ -136,24 +136,35 @@ 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 | ||
139 | void 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 | |||
139 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, | 147 | int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid, |
140 | enum ieee80211_back_parties initiator, | 148 | enum ieee80211_back_parties initiator, |
141 | bool tx) | 149 | bool tx) |
142 | { | 150 | { |
143 | struct ieee80211_local *local = sta->local; | 151 | struct ieee80211_local *local = sta->local; |
144 | struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 152 | struct tid_ampdu_tx *tid_tx; |
145 | int ret; | 153 | int ret; |
146 | 154 | ||
147 | lockdep_assert_held(&sta->ampdu_mlme.mtx); | 155 | lockdep_assert_held(&sta->ampdu_mlme.mtx); |
148 | 156 | ||
149 | if (!tid_tx) | ||
150 | return -ENOENT; | ||
151 | |||
152 | spin_lock_bh(&sta->lock); | 157 | spin_lock_bh(&sta->lock); |
153 | 158 | ||
159 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | ||
160 | if (!tid_tx) { | ||
161 | spin_unlock_bh(&sta->lock); | ||
162 | return -ENOENT; | ||
163 | } | ||
164 | |||
154 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { | 165 | if (test_bit(HT_AGG_STATE_WANT_START, &tid_tx->state)) { |
155 | /* not even started yet! */ | 166 | /* not even started yet! */ |
156 | rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); | 167 | ieee80211_assign_tid_tx(sta, tid, NULL); |
157 | spin_unlock_bh(&sta->lock); | 168 | spin_unlock_bh(&sta->lock); |
158 | kfree_rcu(tid_tx, rcu_head); | 169 | kfree_rcu(tid_tx, rcu_head); |
159 | return 0; | 170 | return 0; |
@@ -275,13 +286,13 @@ ieee80211_wake_queue_agg(struct ieee80211_local *local, int tid) | |||
275 | 286 | ||
276 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | 287 | void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) |
277 | { | 288 | { |
278 | struct tid_ampdu_tx *tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 289 | struct tid_ampdu_tx *tid_tx; |
279 | struct ieee80211_local *local = sta->local; | 290 | struct ieee80211_local *local = sta->local; |
280 | struct ieee80211_sub_if_data *sdata = sta->sdata; | 291 | struct ieee80211_sub_if_data *sdata = sta->sdata; |
281 | u16 start_seq_num; | 292 | u16 start_seq_num; |
282 | int ret; | 293 | int ret; |
283 | 294 | ||
284 | lockdep_assert_held(&sta->ampdu_mlme.mtx); | 295 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
285 | 296 | ||
286 | /* | 297 | /* |
287 | * While we're asking the driver about the aggregation, | 298 | * While we're asking the driver about the aggregation, |
@@ -310,7 +321,7 @@ void ieee80211_tx_ba_session_handle_start(struct sta_info *sta, int tid) | |||
310 | " tid %d\n", tid); | 321 | " tid %d\n", tid); |
311 | #endif | 322 | #endif |
312 | spin_lock_bh(&sta->lock); | 323 | spin_lock_bh(&sta->lock); |
313 | rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); | 324 | ieee80211_assign_tid_tx(sta, tid, NULL); |
314 | spin_unlock_bh(&sta->lock); | 325 | spin_unlock_bh(&sta->lock); |
315 | 326 | ||
316 | ieee80211_wake_queue_agg(local, tid); | 327 | ieee80211_wake_queue_agg(local, tid); |
@@ -388,9 +399,9 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
388 | goto err_unlock_sta; | 399 | goto err_unlock_sta; |
389 | } | 400 | } |
390 | 401 | ||
391 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 402 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
392 | /* check if the TID is not in aggregation flow already */ | 403 | /* check if the TID is not in aggregation flow already */ |
393 | if (tid_tx) { | 404 | if (tid_tx || sta->ampdu_mlme.tid_start_tx[tid]) { |
394 | #ifdef CONFIG_MAC80211_HT_DEBUG | 405 | #ifdef CONFIG_MAC80211_HT_DEBUG |
395 | printk(KERN_DEBUG "BA request denied - session is not " | 406 | printk(KERN_DEBUG "BA request denied - session is not " |
396 | "idle on tid %u\n", tid); | 407 | "idle on tid %u\n", tid); |
@@ -425,8 +436,11 @@ int ieee80211_start_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid, | |||
425 | sta->ampdu_mlme.dialog_token_allocator++; | 436 | sta->ampdu_mlme.dialog_token_allocator++; |
426 | tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator; | 437 | tid_tx->dialog_token = sta->ampdu_mlme.dialog_token_allocator; |
427 | 438 | ||
428 | /* finally, assign it to the array */ | 439 | /* |
429 | rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], tid_tx); | 440 | * Finally, assign it to the start array; the work item will |
441 | * collect it and move it to the normal array. | ||
442 | */ | ||
443 | sta->ampdu_mlme.tid_start_tx[tid] = tid_tx; | ||
430 | 444 | ||
431 | ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); | 445 | ieee80211_queue_work(&local->hw, &sta->ampdu_mlme.work); |
432 | 446 | ||
@@ -472,16 +486,19 @@ ieee80211_agg_splice_finish(struct ieee80211_local *local, u16 tid) | |||
472 | static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | 486 | static void ieee80211_agg_tx_operational(struct ieee80211_local *local, |
473 | struct sta_info *sta, u16 tid) | 487 | struct sta_info *sta, u16 tid) |
474 | { | 488 | { |
489 | struct tid_ampdu_tx *tid_tx; | ||
490 | |||
475 | lockdep_assert_held(&sta->ampdu_mlme.mtx); | 491 | lockdep_assert_held(&sta->ampdu_mlme.mtx); |
476 | 492 | ||
493 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); | ||
494 | |||
477 | #ifdef CONFIG_MAC80211_HT_DEBUG | 495 | #ifdef CONFIG_MAC80211_HT_DEBUG |
478 | printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); | 496 | printk(KERN_DEBUG "Aggregation is on for tid %d\n", tid); |
479 | #endif | 497 | #endif |
480 | 498 | ||
481 | drv_ampdu_action(local, sta->sdata, | 499 | drv_ampdu_action(local, sta->sdata, |
482 | IEEE80211_AMPDU_TX_OPERATIONAL, | 500 | IEEE80211_AMPDU_TX_OPERATIONAL, |
483 | &sta->sta, tid, NULL, | 501 | &sta->sta, tid, NULL, tid_tx->buf_size); |
484 | sta->ampdu_mlme.tid_tx[tid]->buf_size); | ||
485 | 502 | ||
486 | /* | 503 | /* |
487 | * synchronize with TX path, while splicing the TX path | 504 | * synchronize with TX path, while splicing the TX path |
@@ -489,13 +506,13 @@ static void ieee80211_agg_tx_operational(struct ieee80211_local *local, | |||
489 | */ | 506 | */ |
490 | spin_lock_bh(&sta->lock); | 507 | spin_lock_bh(&sta->lock); |
491 | 508 | ||
492 | ieee80211_agg_splice_packets(local, sta->ampdu_mlme.tid_tx[tid], tid); | 509 | ieee80211_agg_splice_packets(local, tid_tx, tid); |
493 | /* | 510 | /* |
494 | * Now mark as operational. This will be visible | 511 | * Now mark as operational. This will be visible |
495 | * in the TX path, and lets it go lock-free in | 512 | * in the TX path, and lets it go lock-free in |
496 | * the common case. | 513 | * the common case. |
497 | */ | 514 | */ |
498 | set_bit(HT_AGG_STATE_OPERATIONAL, &sta->ampdu_mlme.tid_tx[tid]->state); | 515 | set_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state); |
499 | ieee80211_agg_splice_finish(local, tid); | 516 | ieee80211_agg_splice_finish(local, tid); |
500 | 517 | ||
501 | spin_unlock_bh(&sta->lock); | 518 | spin_unlock_bh(&sta->lock); |
@@ -529,7 +546,7 @@ void ieee80211_start_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u16 tid) | |||
529 | } | 546 | } |
530 | 547 | ||
531 | mutex_lock(&sta->ampdu_mlme.mtx); | 548 | mutex_lock(&sta->ampdu_mlme.mtx); |
532 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 549 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
533 | 550 | ||
534 | if (WARN_ON(!tid_tx)) { | 551 | if (WARN_ON(!tid_tx)) { |
535 | #ifdef CONFIG_MAC80211_HT_DEBUG | 552 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -607,7 +624,7 @@ int ieee80211_stop_tx_ba_session(struct ieee80211_sta *pubsta, u16 tid) | |||
607 | return -EINVAL; | 624 | return -EINVAL; |
608 | 625 | ||
609 | spin_lock_bh(&sta->lock); | 626 | spin_lock_bh(&sta->lock); |
610 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 627 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
611 | 628 | ||
612 | if (!tid_tx) { | 629 | if (!tid_tx) { |
613 | ret = -ENOENT; | 630 | ret = -ENOENT; |
@@ -663,7 +680,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
663 | 680 | ||
664 | mutex_lock(&sta->ampdu_mlme.mtx); | 681 | mutex_lock(&sta->ampdu_mlme.mtx); |
665 | spin_lock_bh(&sta->lock); | 682 | spin_lock_bh(&sta->lock); |
666 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 683 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
667 | 684 | ||
668 | if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { | 685 | if (!tid_tx || !test_bit(HT_AGG_STATE_STOPPING, &tid_tx->state)) { |
669 | #ifdef CONFIG_MAC80211_HT_DEBUG | 686 | #ifdef CONFIG_MAC80211_HT_DEBUG |
@@ -689,7 +706,7 @@ void ieee80211_stop_tx_ba_cb(struct ieee80211_vif *vif, u8 *ra, u8 tid) | |||
689 | ieee80211_agg_splice_packets(local, tid_tx, tid); | 706 | ieee80211_agg_splice_packets(local, tid_tx, tid); |
690 | 707 | ||
691 | /* future packets must not find the tid_tx struct any more */ | 708 | /* future packets must not find the tid_tx struct any more */ |
692 | rcu_assign_pointer(sta->ampdu_mlme.tid_tx[tid], NULL); | 709 | ieee80211_assign_tid_tx(sta, tid, NULL); |
693 | 710 | ||
694 | ieee80211_agg_splice_finish(local, tid); | 711 | ieee80211_agg_splice_finish(local, tid); |
695 | 712 | ||
@@ -744,7 +761,7 @@ void ieee80211_process_addba_resp(struct ieee80211_local *local, | |||
744 | 761 | ||
745 | mutex_lock(&sta->ampdu_mlme.mtx); | 762 | mutex_lock(&sta->ampdu_mlme.mtx); |
746 | 763 | ||
747 | tid_tx = sta->ampdu_mlme.tid_tx[tid]; | 764 | tid_tx = rcu_dereference_protected_tid_tx(sta, tid); |
748 | if (!tid_tx) | 765 | if (!tid_tx) |
749 | goto out; | 766 | goto out; |
750 | 767 | ||