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.c70
1 files changed, 63 insertions, 7 deletions
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index d5b91b6eb120..f24a0a1cff1a 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -572,6 +572,8 @@ static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
572 * frames that have not yet been received are assumed to be lost and the skb 572 * frames that have not yet been received are assumed to be lost and the skb
573 * can be released for processing. This may also release other skb's from the 573 * can be released for processing. This may also release other skb's from the
574 * reorder buffer if there are no additional gaps between the frames. 574 * reorder buffer if there are no additional gaps between the frames.
575 *
576 * Callers must hold tid_agg_rx->reorder_lock.
575 */ 577 */
576#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10) 578#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10)
577 579
@@ -579,7 +581,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
579 struct tid_ampdu_rx *tid_agg_rx, 581 struct tid_ampdu_rx *tid_agg_rx,
580 struct sk_buff_head *frames) 582 struct sk_buff_head *frames)
581{ 583{
582 int index; 584 int index, j;
583 585
584 /* release the buffer until next missing frame */ 586 /* release the buffer until next missing frame */
585 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % 587 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
@@ -590,7 +592,6 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
590 * No buffers ready to be released, but check whether any 592 * No buffers ready to be released, but check whether any
591 * frames in the reorder buffer have timed out. 593 * frames in the reorder buffer have timed out.
592 */ 594 */
593 int j;
594 int skipped = 1; 595 int skipped = 1;
595 for (j = (index + 1) % tid_agg_rx->buf_size; j != index; 596 for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
596 j = (j + 1) % tid_agg_rx->buf_size) { 597 j = (j + 1) % tid_agg_rx->buf_size) {
@@ -600,7 +601,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
600 } 601 }
601 if (!time_after(jiffies, tid_agg_rx->reorder_time[j] + 602 if (!time_after(jiffies, tid_agg_rx->reorder_time[j] +
602 HT_RX_REORDER_BUF_TIMEOUT)) 603 HT_RX_REORDER_BUF_TIMEOUT))
603 break; 604 goto set_release_timer;
604 605
605#ifdef CONFIG_MAC80211_HT_DEBUG 606#ifdef CONFIG_MAC80211_HT_DEBUG
606 if (net_ratelimit()) 607 if (net_ratelimit())
@@ -624,6 +625,25 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
624 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) % 625 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
625 tid_agg_rx->buf_size; 626 tid_agg_rx->buf_size;
626 } 627 }
628
629 if (tid_agg_rx->stored_mpdu_num) {
630 j = index = seq_sub(tid_agg_rx->head_seq_num,
631 tid_agg_rx->ssn) % tid_agg_rx->buf_size;
632
633 for (; j != (index - 1) % tid_agg_rx->buf_size;
634 j = (j + 1) % tid_agg_rx->buf_size) {
635 if (tid_agg_rx->reorder_buf[j])
636 break;
637 }
638
639 set_release_timer:
640
641 mod_timer(&tid_agg_rx->reorder_timer,
642 tid_agg_rx->reorder_time[j] +
643 HT_RX_REORDER_BUF_TIMEOUT);
644 } else {
645 del_timer(&tid_agg_rx->reorder_timer);
646 }
627} 647}
628 648
629/* 649/*
@@ -641,14 +661,16 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
641 u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4; 661 u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
642 u16 head_seq_num, buf_size; 662 u16 head_seq_num, buf_size;
643 int index; 663 int index;
664 bool ret = true;
644 665
645 buf_size = tid_agg_rx->buf_size; 666 buf_size = tid_agg_rx->buf_size;
646 head_seq_num = tid_agg_rx->head_seq_num; 667 head_seq_num = tid_agg_rx->head_seq_num;
647 668
669 spin_lock(&tid_agg_rx->reorder_lock);
648 /* frame with out of date sequence number */ 670 /* frame with out of date sequence number */
649 if (seq_less(mpdu_seq_num, head_seq_num)) { 671 if (seq_less(mpdu_seq_num, head_seq_num)) {
650 dev_kfree_skb(skb); 672 dev_kfree_skb(skb);
651 return true; 673 goto out;
652 } 674 }
653 675
654 /* 676 /*
@@ -669,7 +691,7 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
669 /* check if we already stored this frame */ 691 /* check if we already stored this frame */
670 if (tid_agg_rx->reorder_buf[index]) { 692 if (tid_agg_rx->reorder_buf[index]) {
671 dev_kfree_skb(skb); 693 dev_kfree_skb(skb);
672 return true; 694 goto out;
673 } 695 }
674 696
675 /* 697 /*
@@ -679,7 +701,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
679 if (mpdu_seq_num == tid_agg_rx->head_seq_num && 701 if (mpdu_seq_num == tid_agg_rx->head_seq_num &&
680 tid_agg_rx->stored_mpdu_num == 0) { 702 tid_agg_rx->stored_mpdu_num == 0) {
681 tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num); 703 tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
682 return false; 704 ret = false;
705 goto out;
683 } 706 }
684 707
685 /* put the frame in the reordering buffer */ 708 /* put the frame in the reordering buffer */
@@ -688,7 +711,9 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
688 tid_agg_rx->stored_mpdu_num++; 711 tid_agg_rx->stored_mpdu_num++;
689 ieee80211_sta_reorder_release(hw, tid_agg_rx, frames); 712 ieee80211_sta_reorder_release(hw, tid_agg_rx, frames);
690 713
691 return true; 714 out:
715 spin_unlock(&tid_agg_rx->reorder_lock);
716 return ret;
692} 717}
693 718
694/* 719/*
@@ -2387,6 +2412,37 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
2387#undef CALL_RXH 2412#undef CALL_RXH
2388} 2413}
2389 2414
2415/*
2416 * This function makes calls into the RX path. Therefore the
2417 * caller must hold the sta_info->lock and everything has to
2418 * be under rcu_read_lock protection as well.
2419 */
2420void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
2421{
2422 struct sk_buff_head frames;
2423 struct ieee80211_rx_data rx = { };
2424
2425 __skb_queue_head_init(&frames);
2426
2427 /* construct rx struct */
2428 rx.sta = sta;
2429 rx.sdata = sta->sdata;
2430 rx.local = sta->local;
2431 rx.queue = tid;
2432 rx.flags |= IEEE80211_RX_RA_MATCH;
2433
2434 if (unlikely(test_bit(SCAN_HW_SCANNING, &sta->local->scanning) ||
2435 test_bit(SCAN_OFF_CHANNEL, &sta->local->scanning)))
2436 rx.flags |= IEEE80211_RX_IN_SCAN;
2437
2438 spin_lock(&sta->ampdu_mlme.tid_rx[tid]->reorder_lock);
2439 ieee80211_sta_reorder_release(&sta->local->hw,
2440 sta->ampdu_mlme.tid_rx[tid], &frames);
2441 spin_unlock(&sta->ampdu_mlme.tid_rx[tid]->reorder_lock);
2442
2443 ieee80211_rx_handlers(&rx, &frames);
2444}
2445
2390/* main receive path */ 2446/* main receive path */
2391 2447
2392static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, 2448static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,