aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/rx.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/rx.c')
-rw-r--r--net/mac80211/rx.c47
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;