aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211')
-rw-r--r--net/mac80211/agg-rx.c8
-rw-r--r--net/mac80211/debugfs_sta.c29
-rw-r--r--net/mac80211/rx.c17
-rw-r--r--net/mac80211/sta_info.h29
4 files changed, 45 insertions, 38 deletions
diff --git a/net/mac80211/agg-rx.c b/net/mac80211/agg-rx.c
index 720b7a84af59..f138b195d657 100644
--- a/net/mac80211/agg-rx.c
+++ b/net/mac80211/agg-rx.c
@@ -129,9 +129,7 @@ static void sta_rx_agg_reorder_timer_expired(unsigned long data)
129 timer_to_tid[0]); 129 timer_to_tid[0]);
130 130
131 rcu_read_lock(); 131 rcu_read_lock();
132 spin_lock(&sta->lock);
133 ieee80211_release_reorder_timeout(sta, *ptid); 132 ieee80211_release_reorder_timeout(sta, *ptid);
134 spin_unlock(&sta->lock);
135 rcu_read_unlock(); 133 rcu_read_unlock();
136} 134}
137 135
@@ -256,7 +254,7 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
256 } 254 }
257 255
258 /* prepare A-MPDU MLME for Rx aggregation */ 256 /* prepare A-MPDU MLME for Rx aggregation */
259 tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_ATOMIC); 257 tid_agg_rx = kmalloc(sizeof(struct tid_ampdu_rx), GFP_KERNEL);
260 if (!tid_agg_rx) { 258 if (!tid_agg_rx) {
261#ifdef CONFIG_MAC80211_HT_DEBUG 259#ifdef CONFIG_MAC80211_HT_DEBUG
262 if (net_ratelimit()) 260 if (net_ratelimit())
@@ -280,9 +278,9 @@ void ieee80211_process_addba_request(struct ieee80211_local *local,
280 278
281 /* prepare reordering buffer */ 279 /* prepare reordering buffer */
282 tid_agg_rx->reorder_buf = 280 tid_agg_rx->reorder_buf =
283 kcalloc(buf_size, sizeof(struct sk_buff *), GFP_ATOMIC); 281 kcalloc(buf_size, sizeof(struct sk_buff *), GFP_KERNEL);
284 tid_agg_rx->reorder_time = 282 tid_agg_rx->reorder_time =
285 kcalloc(buf_size, sizeof(unsigned long), GFP_ATOMIC); 283 kcalloc(buf_size, sizeof(unsigned long), GFP_KERNEL);
286 if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) { 284 if (!tid_agg_rx->reorder_buf || !tid_agg_rx->reorder_time) {
287#ifdef CONFIG_MAC80211_HT_DEBUG 285#ifdef CONFIG_MAC80211_HT_DEBUG
288 if (net_ratelimit()) 286 if (net_ratelimit())
diff --git a/net/mac80211/debugfs_sta.c b/net/mac80211/debugfs_sta.c
index f0fce37f4069..8bb5af85f469 100644
--- a/net/mac80211/debugfs_sta.c
+++ b/net/mac80211/debugfs_sta.c
@@ -112,34 +112,35 @@ static ssize_t sta_agg_status_read(struct file *file, char __user *userbuf,
112 char buf[71 + STA_TID_NUM * 40], *p = buf; 112 char buf[71 + STA_TID_NUM * 40], *p = buf;
113 int i; 113 int i;
114 struct sta_info *sta = file->private_data; 114 struct sta_info *sta = file->private_data;
115 struct tid_ampdu_rx *tid_rx;
116 struct tid_ampdu_tx *tid_tx;
117
118 rcu_read_lock();
115 119
116 spin_lock_bh(&sta->lock);
117 p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n", 120 p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n",
118 sta->ampdu_mlme.dialog_token_allocator + 1); 121 sta->ampdu_mlme.dialog_token_allocator + 1);
119 p += scnprintf(p, sizeof(buf) + buf - p, 122 p += scnprintf(p, sizeof(buf) + buf - p,
120 "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tpending\n"); 123 "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tpending\n");
124
121 for (i = 0; i < STA_TID_NUM; i++) { 125 for (i = 0; i < STA_TID_NUM; i++) {
126 tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]);
127 tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[i]);
128
122 p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i); 129 p += scnprintf(p, sizeof(buf) + buf - p, "%02d", i);
123 p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", 130 p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", !!tid_rx);
124 !!sta->ampdu_mlme.tid_rx[i]);
125 p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", 131 p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
126 sta->ampdu_mlme.tid_rx[i] ? 132 tid_rx ? tid_rx->dialog_token : 0);
127 sta->ampdu_mlme.tid_rx[i]->dialog_token : 0);
128 p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x", 133 p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.3x",
129 sta->ampdu_mlme.tid_rx[i] ? 134 tid_rx ? tid_rx->ssn : 0);
130 sta->ampdu_mlme.tid_rx[i]->ssn : 0);
131 135
132 p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", 136 p += scnprintf(p, sizeof(buf) + buf - p, "\t\t%x", !!tid_tx);
133 !!sta->ampdu_mlme.tid_tx[i]);
134 p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x", 137 p += scnprintf(p, sizeof(buf) + buf - p, "\t%#.2x",
135 sta->ampdu_mlme.tid_tx[i] ? 138 tid_tx ? tid_tx->dialog_token : 0);
136 sta->ampdu_mlme.tid_tx[i]->dialog_token : 0);
137 p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d", 139 p += scnprintf(p, sizeof(buf) + buf - p, "\t%03d",
138 sta->ampdu_mlme.tid_tx[i] ? 140 tid_tx ? skb_queue_len(&tid_tx->pending) : 0);
139 skb_queue_len(&sta->ampdu_mlme.tid_tx[i]->pending) : 0);
140 p += scnprintf(p, sizeof(buf) + buf - p, "\n"); 141 p += scnprintf(p, sizeof(buf) + buf - p, "\n");
141 } 142 }
142 spin_unlock_bh(&sta->lock); 143 rcu_read_unlock();
143 144
144 return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf); 145 return simple_read_from_buffer(userbuf, count, ppos, buf, p - buf);
145} 146}
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 */
2522void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid) 2531void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
2523{ 2532{
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index b562d9b6a702..05f11302443b 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -81,13 +81,14 @@ enum ieee80211_sta_info_flags {
81 * @stop_initiator: initiator of a session stop 81 * @stop_initiator: initiator of a session stop
82 * @tx_stop: TX DelBA frame when stopping 82 * @tx_stop: TX DelBA frame when stopping
83 * 83 *
84 * This structure is protected by RCU and the per-station 84 * This structure's lifetime is managed by RCU, assignments to
85 * spinlock. Assignments to the array holding it must hold 85 * the array holding it must hold the aggregation mutex.
86 * the spinlock, only the TX path can access it under RCU 86 *
87 * lock-free if, and only if, the state has the flag 87 * The TX path can access it under RCU lock-free if, and
88 * %HT_AGG_STATE_OPERATIONAL set. Otherwise, the TX path 88 * only if, the state has the flag %HT_AGG_STATE_OPERATIONAL
89 * must also acquire the spinlock and re-check the state, 89 * set. Otherwise, the TX path must also acquire the spinlock
90 * see comments in the tx code touching it. 90 * and re-check the state, see comments in the tx code
91 * touching it.
91 */ 92 */
92struct tid_ampdu_tx { 93struct tid_ampdu_tx {
93 struct rcu_head rcu_head; 94 struct rcu_head rcu_head;
@@ -115,15 +116,13 @@ struct tid_ampdu_tx {
115 * @rcu_head: RCU head used for freeing this struct 116 * @rcu_head: RCU head used for freeing this struct
116 * @reorder_lock: serializes access to reorder buffer, see below. 117 * @reorder_lock: serializes access to reorder buffer, see below.
117 * 118 *
118 * This structure is protected by RCU and the per-station 119 * This structure's lifetime is managed by RCU, assignments to
119 * spinlock. Assignments to the array holding it must hold 120 * the array holding it must hold the aggregation mutex.
120 * the spinlock.
121 * 121 *
122 * The @reorder_lock is used to protect the variables and 122 * The @reorder_lock is used to protect the members of this
123 * arrays such as @reorder_buf, @reorder_time, @head_seq_num, 123 * struct, except for @timeout, @buf_size and @dialog_token,
124 * @stored_mpdu_num and @reorder_time from being corrupted by 124 * which are constant across the lifetime of the struct (the
125 * concurrent access of the RX path and the expired frame 125 * dialog token being used only for debugging).
126 * release timer.
127 */ 126 */
128struct tid_ampdu_rx { 127struct tid_ampdu_rx {
129 struct rcu_head rcu_head; 128 struct rcu_head rcu_head;