diff options
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r-- | net/mac80211/rx.c | 47 |
1 files changed, 46 insertions, 1 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 9f2a29d1890b..24d41705ac0b 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -2313,6 +2313,15 @@ no_frame: | |||
2313 | 2313 | ||
2314 | 2314 | ||
2315 | /* | 2315 | /* |
2316 | * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If | ||
2317 | * the skb was added to the buffer longer than this time ago, the earlier | ||
2318 | * frames that have not yet been received are assumed to be lost and the skb | ||
2319 | * can be released for processing. This may also release other skb's from the | ||
2320 | * reorder buffer if there are no additional gaps between the frames. | ||
2321 | */ | ||
2322 | #define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) | ||
2323 | |||
2324 | /* | ||
2316 | * As it function blongs to Rx path it must be called with | 2325 | * As it function blongs to Rx path it must be called with |
2317 | * the proper rcu_read_lock protection for its flow. | 2326 | * the proper rcu_read_lock protection for its flow. |
2318 | */ | 2327 | */ |
@@ -2377,13 +2386,49 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2377 | 2386 | ||
2378 | /* put the frame in the reordering buffer */ | 2387 | /* put the frame in the reordering buffer */ |
2379 | tid_agg_rx->reorder_buf[index] = skb; | 2388 | tid_agg_rx->reorder_buf[index] = skb; |
2389 | tid_agg_rx->reorder_time[index] = jiffies; | ||
2380 | memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus, | 2390 | memcpy(tid_agg_rx->reorder_buf[index]->cb, rxstatus, |
2381 | sizeof(*rxstatus)); | 2391 | sizeof(*rxstatus)); |
2382 | tid_agg_rx->stored_mpdu_num++; | 2392 | tid_agg_rx->stored_mpdu_num++; |
2383 | /* release the buffer until next missing frame */ | 2393 | /* release the buffer until next missing frame */ |
2384 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) | 2394 | index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) |
2385 | % tid_agg_rx->buf_size; | 2395 | % tid_agg_rx->buf_size; |
2386 | while (tid_agg_rx->reorder_buf[index]) { | 2396 | if (!tid_agg_rx->reorder_buf[index] && |
2397 | tid_agg_rx->stored_mpdu_num > 1) { | ||
2398 | /* | ||
2399 | * No buffers ready to be released, but check whether any | ||
2400 | * frames in the reorder buffer have timed out. | ||
2401 | */ | ||
2402 | int j; | ||
2403 | int skipped = 1; | ||
2404 | for (j = (index + 1) % tid_agg_rx->buf_size; j != index; | ||
2405 | j = (j + 1) % tid_agg_rx->buf_size) { | ||
2406 | if (tid_agg_rx->reorder_buf[j] == NULL) { | ||
2407 | skipped++; | ||
2408 | continue; | ||
2409 | } | ||
2410 | if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + | ||
2411 | HZ / 10)) | ||
2412 | break; | ||
2413 | |||
2414 | #ifdef CONFIG_MAC80211_HT_DEBUG | ||
2415 | if (net_ratelimit()) | ||
2416 | printk(KERN_DEBUG "%s: release an RX reorder " | ||
2417 | "frame due to timeout on earlier " | ||
2418 | "frames\n", | ||
2419 | wiphy_name(hw->wiphy)); | ||
2420 | #endif | ||
2421 | ieee80211_release_reorder_frame(hw, tid_agg_rx, j); | ||
2422 | |||
2423 | /* | ||
2424 | * Increment the head seq# also for the skipped slots. | ||
2425 | */ | ||
2426 | tid_agg_rx->head_seq_num = | ||
2427 | (tid_agg_rx->head_seq_num + skipped) & | ||
2428 | SEQ_MASK; | ||
2429 | skipped = 0; | ||
2430 | } | ||
2431 | } else while (tid_agg_rx->reorder_buf[index]) { | ||
2387 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index); | 2432 | ieee80211_release_reorder_frame(hw, tid_agg_rx, index); |
2388 | index = seq_sub(tid_agg_rx->head_seq_num, | 2433 | index = seq_sub(tid_agg_rx->head_seq_num, |
2389 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; | 2434 | tid_agg_rx->ssn) % tid_agg_rx->buf_size; |