aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
authorJohannes Berg <johannes@sipsolutions.net>2009-11-16 06:00:40 -0500
committerJohn W. Linville <linville@tuxdriver.com>2009-11-18 17:09:17 -0500
commita02ae758e8780d737b6d0135d6292bb3043e7eea (patch)
treed7a1acb57944f51ddd299a8373b3e9f0174bffe8 /net/mac80211/rx.c
parentaf2ced6a32dafb71d21b726c06df57fc574093d7 (diff)
mac80211: cleanup reorder buffer handling
The reorder buffer handling is written in a quite peculiar style (especially comments) and also has a quirk where it invokes the entire reorder code in ieee80211_sta_manage_reorder_buf() for just a handful of lines in it with a special argument. Split out ieee80211_release_reorder_frames which can then be invoked from BAR handling and other reordering code, clean up code and comments and remove function arguments that are now unused from ieee80211_sta_manage_reorder_buf(). Signed-off-by: Johannes Berg <johannes@sipsolutions.net> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c162
1 files changed, 81 insertions, 81 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index 68d9e9c86595..37e9891605b4 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -27,11 +27,10 @@
27#include "tkip.h" 27#include "tkip.h"
28#include "wme.h" 28#include "wme.h"
29 29
30static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, 30static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
31 struct tid_ampdu_rx *tid_agg_rx, 31 struct tid_ampdu_rx *tid_agg_rx,
32 struct sk_buff *skb, 32 u16 head_seq_num);
33 u16 mpdu_seq_num, 33
34 int bar_req);
35/* 34/*
36 * monitor mode reception 35 * monitor mode reception
37 * 36 *
@@ -1592,11 +1591,11 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
1592 1591
1593 if (ieee80211_is_back_req(bar->frame_control)) { 1592 if (ieee80211_is_back_req(bar->frame_control)) {
1594 if (!rx->sta) 1593 if (!rx->sta)
1595 return RX_CONTINUE; 1594 return RX_DROP_MONITOR;
1596 tid = le16_to_cpu(bar->control) >> 12; 1595 tid = le16_to_cpu(bar->control) >> 12;
1597 if (rx->sta->ampdu_mlme.tid_state_rx[tid] 1596 if (rx->sta->ampdu_mlme.tid_state_rx[tid]
1598 != HT_AGG_STATE_OPERATIONAL) 1597 != HT_AGG_STATE_OPERATIONAL)
1599 return RX_CONTINUE; 1598 return RX_DROP_MONITOR;
1600 tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; 1599 tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid];
1601 1600
1602 start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; 1601 start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4;
@@ -1606,13 +1605,10 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
1606 mod_timer(&tid_agg_rx->session_timer, 1605 mod_timer(&tid_agg_rx->session_timer,
1607 TU_TO_EXP_TIME(tid_agg_rx->timeout)); 1606 TU_TO_EXP_TIME(tid_agg_rx->timeout));
1608 1607
1609 /* manage reordering buffer according to requested */ 1608 /* release stored frames up to start of BAR */
1610 /* sequence number */ 1609 ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num);
1611 rcu_read_lock(); 1610 kfree_skb(skb);
1612 ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL, 1611 return RX_QUEUED;
1613 start_seq_num, 1);
1614 rcu_read_unlock();
1615 return RX_DROP_UNUSABLE;
1616 } 1612 }
1617 1613
1618 return RX_CONTINUE; 1614 return RX_CONTINUE;
@@ -2223,6 +2219,18 @@ no_frame:
2223 tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); 2219 tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
2224} 2220}
2225 2221
2222static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
2223 struct tid_ampdu_rx *tid_agg_rx,
2224 u16 head_seq_num)
2225{
2226 int index;
2227
2228 while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) {
2229 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
2230 tid_agg_rx->buf_size;
2231 ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
2232 }
2233}
2226 2234
2227/* 2235/*
2228 * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If 2236 * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If
@@ -2234,15 +2242,17 @@ no_frame:
2234#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) 2242#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10)
2235 2243
2236/* 2244/*
2237 * As it function blongs to Rx path it must be called with 2245 * As this function belongs to the RX path it must be under
2238 * the proper rcu_read_lock protection for its flow. 2246 * rcu_read_lock protection. It returns false if the frame
2247 * can be processed immediately, true if it was consumed.
2239 */ 2248 */
2240static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, 2249static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
2241 struct tid_ampdu_rx *tid_agg_rx, 2250 struct tid_ampdu_rx *tid_agg_rx,
2242 struct sk_buff *skb, 2251 struct sk_buff *skb)
2243 u16 mpdu_seq_num,
2244 int bar_req)
2245{ 2252{
2253 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2254 u16 sc = le16_to_cpu(hdr->seq_ctrl);
2255 u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
2246 u16 head_seq_num, buf_size; 2256 u16 head_seq_num, buf_size;
2247 int index; 2257 int index;
2248 2258
@@ -2252,47 +2262,37 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
2252 /* frame with out of date sequence number */ 2262 /* frame with out of date sequence number */
2253 if (seq_less(mpdu_seq_num, head_seq_num)) { 2263 if (seq_less(mpdu_seq_num, head_seq_num)) {
2254 dev_kfree_skb(skb); 2264 dev_kfree_skb(skb);
2255 return 1; 2265 return true;
2256 } 2266 }
2257 2267
2258 /* if frame sequence number exceeds our buffering window size or 2268 /*
2259 * block Ack Request arrived - release stored frames */ 2269 * If frame the sequence number exceeds our buffering window
2260 if ((!seq_less(mpdu_seq_num, head_seq_num + buf_size)) || (bar_req)) { 2270 * size release some previous frames to make room for this one.
2261 /* new head to the ordering buffer */ 2271 */
2262 if (bar_req) 2272 if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) {
2263 head_seq_num = mpdu_seq_num; 2273 head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size));
2264 else
2265 head_seq_num =
2266 seq_inc(seq_sub(mpdu_seq_num, buf_size));
2267 /* release stored frames up to new head to stack */ 2274 /* release stored frames up to new head to stack */
2268 while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) { 2275 ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num);
2269 index = seq_sub(tid_agg_rx->head_seq_num,
2270 tid_agg_rx->ssn)
2271 % tid_agg_rx->buf_size;
2272 ieee80211_release_reorder_frame(hw, tid_agg_rx,
2273 index);
2274 }
2275 if (bar_req)
2276 return 1;
2277 } 2276 }
2278 2277
2279 /* now the new frame is always in the range of the reordering */ 2278 /* Now the new frame is always in the range of the reordering buffer */
2280 /* buffer window */ 2279
2281 index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) 2280 index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size;
2282 % tid_agg_rx->buf_size; 2281
2283 /* check if we already stored this frame */ 2282 /* check if we already stored this frame */
2284 if (tid_agg_rx->reorder_buf[index]) { 2283 if (tid_agg_rx->reorder_buf[index]) {
2285 dev_kfree_skb(skb); 2284 dev_kfree_skb(skb);
2286 return 1; 2285 return true;
2287 } 2286 }
2288 2287
2289 /* if arrived mpdu is in the right order and nothing else stored */ 2288 /*
2290 /* release it immediately */ 2289 * If the current MPDU is in the right order and nothing else
2290 * is stored we can process it directly, no need to buffer it.
2291 */
2291 if (mpdu_seq_num == tid_agg_rx->head_seq_num && 2292 if (mpdu_seq_num == tid_agg_rx->head_seq_num &&
2292 tid_agg_rx->stored_mpdu_num == 0) { 2293 tid_agg_rx->stored_mpdu_num == 0) {
2293 tid_agg_rx->head_seq_num = 2294 tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
2294 seq_inc(tid_agg_rx->head_seq_num); 2295 return false;
2295 return 0;
2296 } 2296 }
2297 2297
2298 /* put the frame in the reordering buffer */ 2298 /* put the frame in the reordering buffer */
@@ -2300,8 +2300,8 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
2300 tid_agg_rx->reorder_time[index] = jiffies; 2300 tid_agg_rx->reorder_time[index] = jiffies;
2301 tid_agg_rx->stored_mpdu_num++; 2301 tid_agg_rx->stored_mpdu_num++;
2302 /* release the buffer until next missing frame */ 2302 /* release the buffer until next missing frame */
2303 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) 2303 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
2304 % tid_agg_rx->buf_size; 2304 tid_agg_rx->buf_size;
2305 if (!tid_agg_rx->reorder_buf[index] && 2305 if (!tid_agg_rx->reorder_buf[index] &&
2306 tid_agg_rx->stored_mpdu_num > 1) { 2306 tid_agg_rx->stored_mpdu_num > 1) {
2307 /* 2307 /*
@@ -2312,12 +2312,12 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
2312 int skipped = 1; 2312 int skipped = 1;
2313 for (j = (index + 1) % tid_agg_rx->buf_size; j != index; 2313 for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
2314 j = (j + 1) % tid_agg_rx->buf_size) { 2314 j = (j + 1) % tid_agg_rx->buf_size) {
2315 if (tid_agg_rx->reorder_buf[j] == NULL) { 2315 if (!tid_agg_rx->reorder_buf[j]) {
2316 skipped++; 2316 skipped++;
2317 continue; 2317 continue;
2318 } 2318 }
2319 if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + 2319 if (!time_after(jiffies, tid_agg_rx->reorder_time[j] +
2320 HZ / 10)) 2320 HT_RX_REORDER_BUF_TIMEOUT))
2321 break; 2321 break;
2322 2322
2323#ifdef CONFIG_MAC80211_HT_DEBUG 2323#ifdef CONFIG_MAC80211_HT_DEBUG
@@ -2333,51 +2333,56 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
2333 * Increment the head seq# also for the skipped slots. 2333 * Increment the head seq# also for the skipped slots.
2334 */ 2334 */
2335 tid_agg_rx->head_seq_num = 2335 tid_agg_rx->head_seq_num =
2336 (tid_agg_rx->head_seq_num + skipped) & 2336 (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK;
2337 SEQ_MASK;
2338 skipped = 0; 2337 skipped = 0;
2339 } 2338 }
2340 } else while (tid_agg_rx->reorder_buf[index]) { 2339 } else while (tid_agg_rx->reorder_buf[index]) {
2341 ieee80211_release_reorder_frame(hw, tid_agg_rx, index); 2340 ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
2342 index = seq_sub(tid_agg_rx->head_seq_num, 2341 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
2343 tid_agg_rx->ssn) % tid_agg_rx->buf_size; 2342 tid_agg_rx->buf_size;
2344 } 2343 }
2345 return 1; 2344
2345 return true;
2346} 2346}
2347 2347
2348static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, 2348/*
2349 struct sk_buff *skb) 2349 * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns
2350 * true if the MPDU was buffered, false if it should be processed.
2351 */
2352static bool ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
2353 struct sk_buff *skb)
2350{ 2354{
2351 struct ieee80211_hw *hw = &local->hw; 2355 struct ieee80211_hw *hw = &local->hw;
2352 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; 2356 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2353 struct sta_info *sta; 2357 struct sta_info *sta;
2354 struct tid_ampdu_rx *tid_agg_rx; 2358 struct tid_ampdu_rx *tid_agg_rx;
2355 u16 sc; 2359 u16 sc;
2356 u16 mpdu_seq_num;
2357 u8 ret = 0;
2358 int tid; 2360 int tid;
2359 2361
2362 if (!ieee80211_is_data_qos(hdr->frame_control))
2363 return false;
2364
2365 /*
2366 * filter the QoS data rx stream according to
2367 * STA/TID and check if this STA/TID is on aggregation
2368 */
2369
2360 sta = sta_info_get(local, hdr->addr2); 2370 sta = sta_info_get(local, hdr->addr2);
2361 if (!sta) 2371 if (!sta)
2362 return ret; 2372 return false;
2363
2364 /* filter the QoS data rx stream according to
2365 * STA/TID and check if this STA/TID is on aggregation */
2366 if (!ieee80211_is_data_qos(hdr->frame_control))
2367 goto end_reorder;
2368 2373
2369 tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; 2374 tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
2370 2375
2371 if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) 2376 if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
2372 goto end_reorder; 2377 return false;
2373 2378
2374 tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; 2379 tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
2375 2380
2376 /* qos null data frames are excluded */ 2381 /* qos null data frames are excluded */
2377 if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC))) 2382 if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
2378 goto end_reorder; 2383 return false;
2379 2384
2380 /* new un-ordered ampdu frame - process it */ 2385 /* new, potentially un-ordered, ampdu frame - process it */
2381 2386
2382 /* reset session timer */ 2387 /* reset session timer */
2383 if (tid_agg_rx->timeout) 2388 if (tid_agg_rx->timeout)
@@ -2389,16 +2394,11 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
2389 if (sc & IEEE80211_SCTL_FRAG) { 2394 if (sc & IEEE80211_SCTL_FRAG) {
2390 ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, 2395 ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr,
2391 tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); 2396 tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
2392 ret = 1; 2397 dev_kfree_skb(skb);
2393 goto end_reorder; 2398 return true;
2394 } 2399 }
2395 2400
2396 /* according to mpdu sequence number deal with reordering buffer */ 2401 return ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb);
2397 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
2398 ret = ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb,
2399 mpdu_seq_num, 0);
2400 end_reorder:
2401 return ret;
2402} 2402}
2403 2403
2404/* 2404/*