Commit a02ae758e8780d737b6d0135d6292bb3043e7eea
Committed by
John W. Linville
1 parent
af2ced6a32
Exists in
master
and in
7 other branches
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>
Showing 1 changed file with 81 additions and 81 deletions Side-by-side Diff
net/mac80211/rx.c
... | ... | @@ -27,11 +27,10 @@ |
27 | 27 | #include "tkip.h" |
28 | 28 | #include "wme.h" |
29 | 29 | |
30 | -static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |
31 | - struct tid_ampdu_rx *tid_agg_rx, | |
32 | - struct sk_buff *skb, | |
33 | - u16 mpdu_seq_num, | |
34 | - int bar_req); | |
30 | +static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw, | |
31 | + struct tid_ampdu_rx *tid_agg_rx, | |
32 | + u16 head_seq_num); | |
33 | + | |
35 | 34 | /* |
36 | 35 | * monitor mode reception |
37 | 36 | * |
38 | 37 | |
... | ... | @@ -1592,11 +1591,11 @@ |
1592 | 1591 | |
1593 | 1592 | if (ieee80211_is_back_req(bar->frame_control)) { |
1594 | 1593 | if (!rx->sta) |
1595 | - return RX_CONTINUE; | |
1594 | + return RX_DROP_MONITOR; | |
1596 | 1595 | tid = le16_to_cpu(bar->control) >> 12; |
1597 | 1596 | if (rx->sta->ampdu_mlme.tid_state_rx[tid] |
1598 | 1597 | != HT_AGG_STATE_OPERATIONAL) |
1599 | - return RX_CONTINUE; | |
1598 | + return RX_DROP_MONITOR; | |
1600 | 1599 | tid_agg_rx = rx->sta->ampdu_mlme.tid_rx[tid]; |
1601 | 1600 | |
1602 | 1601 | start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4; |
... | ... | @@ -1606,13 +1605,10 @@ |
1606 | 1605 | mod_timer(&tid_agg_rx->session_timer, |
1607 | 1606 | TU_TO_EXP_TIME(tid_agg_rx->timeout)); |
1608 | 1607 | |
1609 | - /* manage reordering buffer according to requested */ | |
1610 | - /* sequence number */ | |
1611 | - rcu_read_lock(); | |
1612 | - ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, NULL, | |
1613 | - start_seq_num, 1); | |
1614 | - rcu_read_unlock(); | |
1615 | - return RX_DROP_UNUSABLE; | |
1608 | + /* release stored frames up to start of BAR */ | |
1609 | + ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num); | |
1610 | + kfree_skb(skb); | |
1611 | + return RX_QUEUED; | |
1616 | 1612 | } |
1617 | 1613 | |
1618 | 1614 | return RX_CONTINUE; |
1619 | 1615 | |
... | ... | @@ -2223,7 +2219,19 @@ |
2223 | 2219 | tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); |
2224 | 2220 | } |
2225 | 2221 | |
2222 | +static 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; | |
2226 | 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 | +} | |
2234 | + | |
2227 | 2235 | /* |
2228 | 2236 | * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If |
2229 | 2237 | * the skb was added to the buffer longer than this time ago, the earlier |
2230 | 2238 | |
2231 | 2239 | |
... | ... | @@ -2234,15 +2242,17 @@ |
2234 | 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 | |
2238 | - * the proper rcu_read_lock protection for its flow. | |
2245 | + * As this function belongs to the RX path it must be under | |
2246 | + * rcu_read_lock protection. It returns false if the frame | |
2247 | + * can be processed immediately, true if it was consumed. | |
2239 | 2248 | */ |
2240 | -static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |
2241 | - struct tid_ampdu_rx *tid_agg_rx, | |
2242 | - struct sk_buff *skb, | |
2243 | - u16 mpdu_seq_num, | |
2244 | - int bar_req) | |
2249 | +static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |
2250 | + struct tid_ampdu_rx *tid_agg_rx, | |
2251 | + struct sk_buff *skb) | |
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 | 2256 | u16 head_seq_num, buf_size; |
2247 | 2257 | int index; |
2248 | 2258 | |
2249 | 2259 | |
2250 | 2260 | |
2251 | 2261 | |
2252 | 2262 | |
2253 | 2263 | |
2254 | 2264 | |
... | ... | @@ -2252,47 +2262,37 @@ |
2252 | 2262 | /* frame with out of date sequence number */ |
2253 | 2263 | if (seq_less(mpdu_seq_num, head_seq_num)) { |
2254 | 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 | |
2259 | - * block Ack Request arrived - release stored frames */ | |
2260 | - if ((!seq_less(mpdu_seq_num, head_seq_num + buf_size)) || (bar_req)) { | |
2261 | - /* new head to the ordering buffer */ | |
2262 | - if (bar_req) | |
2263 | - head_seq_num = mpdu_seq_num; | |
2264 | - else | |
2265 | - head_seq_num = | |
2266 | - seq_inc(seq_sub(mpdu_seq_num, buf_size)); | |
2268 | + /* | |
2269 | + * If frame the sequence number exceeds our buffering window | |
2270 | + * size release some previous frames to make room for this one. | |
2271 | + */ | |
2272 | + if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) { | |
2273 | + head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size)); | |
2267 | 2274 | /* release stored frames up to new head to stack */ |
2268 | - while (seq_less(tid_agg_rx->head_seq_num, 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; | |
2275 | + ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num); | |
2277 | 2276 | } |
2278 | 2277 | |
2279 | - /* now the new frame is always in the range of the reordering */ | |
2280 | - /* buffer window */ | |
2281 | - index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) | |
2282 | - % tid_agg_rx->buf_size; | |
2278 | + /* Now the new frame is always in the range of the reordering buffer */ | |
2279 | + | |
2280 | + index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size; | |
2281 | + | |
2283 | 2282 | /* check if we already stored this frame */ |
2284 | 2283 | if (tid_agg_rx->reorder_buf[index]) { |
2285 | 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 */ | |
2290 | - /* release it immediately */ | |
2288 | + /* | |
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 | 2292 | if (mpdu_seq_num == tid_agg_rx->head_seq_num && |
2292 | - tid_agg_rx->stored_mpdu_num == 0) { | |
2293 | - tid_agg_rx->head_seq_num = | |
2294 | - seq_inc(tid_agg_rx->head_seq_num); | |
2295 | - return 0; | |
2293 | + tid_agg_rx->stored_mpdu_num == 0) { | |
2294 | + tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); | |
2295 | + return false; | |
2296 | 2296 | } |
2297 | 2297 | |
2298 | 2298 | /* put the frame in the reordering buffer */ |
... | ... | @@ -2300,8 +2300,8 @@ |
2300 | 2300 | tid_agg_rx->reorder_time[index] = jiffies; |
2301 | 2301 | tid_agg_rx->stored_mpdu_num++; |
2302 | 2302 | /* release the buffer until next missing frame */ |
2303 | - index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) | |
2304 | - % tid_agg_rx->buf_size; | |
2303 | + index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | |
2304 | + tid_agg_rx->buf_size; | |
2305 | 2305 | if (!tid_agg_rx->reorder_buf[index] && |
2306 | 2306 | tid_agg_rx->stored_mpdu_num > 1) { |
2307 | 2307 | /* |
2308 | 2308 | |
... | ... | @@ -2312,12 +2312,12 @@ |
2312 | 2312 | int skipped = 1; |
2313 | 2313 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; |
2314 | 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 | 2316 | skipped++; |
2317 | 2317 | continue; |
2318 | 2318 | } |
2319 | 2319 | if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + |
2320 | - HZ / 10)) | |
2320 | + HT_RX_REORDER_BUF_TIMEOUT)) | |
2321 | 2321 | break; |
2322 | 2322 | |
2323 | 2323 | #ifdef CONFIG_MAC80211_HT_DEBUG |
2324 | 2324 | |
2325 | 2325 | |
2326 | 2326 | |
2327 | 2327 | |
2328 | 2328 | |
2329 | 2329 | |
2330 | 2330 | |
2331 | 2331 | |
2332 | 2332 | |
2333 | 2333 | |
... | ... | @@ -2333,51 +2333,56 @@ |
2333 | 2333 | * Increment the head seq# also for the skipped slots. |
2334 | 2334 | */ |
2335 | 2335 | tid_agg_rx->head_seq_num = |
2336 | - (tid_agg_rx->head_seq_num + skipped) & | |
2337 | - SEQ_MASK; | |
2336 | + (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK; | |
2338 | 2337 | skipped = 0; |
2339 | 2338 | } |
2340 | 2339 | } else while (tid_agg_rx->reorder_buf[index]) { |
2341 | 2340 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index); |
2342 | - index = seq_sub(tid_agg_rx->head_seq_num, | |
2343 | - tid_agg_rx->ssn) % tid_agg_rx->buf_size; | |
2341 | + index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % | |
2342 | + tid_agg_rx->buf_size; | |
2344 | 2343 | } |
2345 | - return 1; | |
2344 | + | |
2345 | + return true; | |
2346 | 2346 | } |
2347 | 2347 | |
2348 | -static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |
2349 | - struct sk_buff *skb) | |
2348 | +/* | |
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 | + */ | |
2352 | +static bool ieee80211_rx_reorder_ampdu(struct ieee80211_local *local, | |
2353 | + struct sk_buff *skb) | |
2350 | 2354 | { |
2351 | 2355 | struct ieee80211_hw *hw = &local->hw; |
2352 | 2356 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; |
2353 | 2357 | struct sta_info *sta; |
2354 | 2358 | struct tid_ampdu_rx *tid_agg_rx; |
2355 | 2359 | u16 sc; |
2356 | - u16 mpdu_seq_num; | |
2357 | - u8 ret = 0; | |
2358 | 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 | 2370 | sta = sta_info_get(local, hdr->addr2); |
2361 | 2371 | if (!sta) |
2362 | - return ret; | |
2372 | + return false; | |
2363 | 2373 | |
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 | - | |
2369 | 2374 | tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK; |
2370 | 2375 | |
2371 | 2376 | if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL) |
2372 | - goto end_reorder; | |
2377 | + return false; | |
2373 | 2378 | |
2374 | 2379 | tid_agg_rx = sta->ampdu_mlme.tid_rx[tid]; |
2375 | 2380 | |
2376 | 2381 | /* qos null data frames are excluded */ |
2377 | 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 | 2387 | /* reset session timer */ |
2383 | 2388 | if (tid_agg_rx->timeout) |
2384 | 2389 | |
... | ... | @@ -2389,16 +2394,11 @@ |
2389 | 2394 | if (sc & IEEE80211_SCTL_FRAG) { |
2390 | 2395 | ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr, |
2391 | 2396 | tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP); |
2392 | - ret = 1; | |
2393 | - goto end_reorder; | |
2397 | + dev_kfree_skb(skb); | |
2398 | + return true; | |
2394 | 2399 | } |
2395 | 2400 | |
2396 | - /* according to mpdu sequence number deal with reordering buffer */ | |
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; | |
2401 | + return ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb); | |
2402 | 2402 | } |
2403 | 2403 | |
2404 | 2404 | /* |