diff options
author | Johannes Berg <johannes.berg@intel.com> | 2010-11-29 05:09:16 -0500 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-11-29 15:30:30 -0500 |
commit | dd318575ff0aae91ac4cbcc5b60c184e59267212 (patch) | |
tree | 140a0104b99b8edef7b961b4de9182e092782cf9 /net/mac80211/rx.c | |
parent | 8b7f8532d15631776ce8bec2bbbc58f6aad738d1 (diff) |
mac80211: fix RX aggregation locking
The RX aggregation locking documentation was
wrong, which led Christian to also code the
timer timeout handling for it somewhat wrongly.
Fix the documentation, the two places that
need to hold the reorder lock across accesses
to the structure, and the debugfs code that
should just use RCU.
Also, remove acquiring the sta->lock across
reorder timeouts since it isn't necessary, and
change a few places to GFP_KERNEL because the
code path here doesn't need atomic allocations
as I noticed when reviewing all this.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Acked-by: Christian Lamparter <chunkeey@googlemail.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 17 |
1 files changed, 13 insertions, 4 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index d2fcd22ab06d..fdeabb19943c 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -538,6 +538,8 @@ static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw, | |||
538 | { | 538 | { |
539 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; | 539 | struct sk_buff *skb = tid_agg_rx->reorder_buf[index]; |
540 | 540 | ||
541 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | ||
542 | |||
541 | if (!skb) | 543 | if (!skb) |
542 | goto no_frame; | 544 | goto no_frame; |
543 | 545 | ||
@@ -557,6 +559,8 @@ static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, | |||
557 | { | 559 | { |
558 | int index; | 560 | int index; |
559 | 561 | ||
562 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | ||
563 | |||
560 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { | 564 | while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { |
561 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 565 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % |
562 | tid_agg_rx->buf_size; | 566 | tid_agg_rx->buf_size; |
@@ -581,6 +585,8 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw, | |||
581 | { | 585 | { |
582 | int index, j; | 586 | int index, j; |
583 | 587 | ||
588 | lockdep_assert_held(&tid_agg_rx->reorder_lock); | ||
589 | |||
584 | /* release the buffer until next missing frame */ | 590 | /* release the buffer until next missing frame */ |
585 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | 591 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % |
586 | tid_agg_rx->buf_size; | 592 | tid_agg_rx->buf_size; |
@@ -683,10 +689,11 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
683 | int index; | 689 | int index; |
684 | bool ret = true; | 690 | bool ret = true; |
685 | 691 | ||
692 | spin_lock(&tid_agg_rx->reorder_lock); | ||
693 | |||
686 | buf_size = tid_agg_rx->buf_size; | 694 | buf_size = tid_agg_rx->buf_size; |
687 | head_seq_num = tid_agg_rx->head_seq_num; | 695 | head_seq_num = tid_agg_rx->head_seq_num; |
688 | 696 | ||
689 | spin_lock(&tid_agg_rx->reorder_lock); | ||
690 | /* frame with out of date sequence number */ | 697 | /* frame with out of date sequence number */ |
691 | if (seq_less(mpdu_seq_num, head_seq_num)) { | 698 | if (seq_less(mpdu_seq_num, head_seq_num)) { |
692 | dev_kfree_skb(skb); | 699 | dev_kfree_skb(skb); |
@@ -1921,9 +1928,12 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames) | |||
1921 | mod_timer(&tid_agg_rx->session_timer, | 1928 | mod_timer(&tid_agg_rx->session_timer, |
1922 | TU_TO_EXP_TIME(tid_agg_rx->timeout)); | 1929 | TU_TO_EXP_TIME(tid_agg_rx->timeout)); |
1923 | 1930 | ||
1931 | spin_lock(&tid_agg_rx->reorder_lock); | ||
1924 | /* release stored frames up to start of BAR */ | 1932 | /* release stored frames up to start of BAR */ |
1925 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, | 1933 | ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num, |
1926 | frames); | 1934 | frames); |
1935 | spin_unlock(&tid_agg_rx->reorder_lock); | ||
1936 | |||
1927 | kfree_skb(skb); | 1937 | kfree_skb(skb); |
1928 | return RX_QUEUED; | 1938 | return RX_QUEUED; |
1929 | } | 1939 | } |
@@ -2515,9 +2525,8 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_rx_data *rx) | |||
2515 | } | 2525 | } |
2516 | 2526 | ||
2517 | /* | 2527 | /* |
2518 | * This function makes calls into the RX path. Therefore the | 2528 | * This function makes calls into the RX path, therefore |
2519 | * caller must hold the sta_info->lock and everything has to | 2529 | * it has to be invoked under RCU read lock. |
2520 | * be under rcu_read_lock protection as well. | ||
2521 | */ | 2530 | */ |
2522 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) | 2531 | void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) |
2523 | { | 2532 | { |