diff options
author | John W. Linville <linville@tuxdriver.com> | 2012-07-12 13:44:50 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2012-07-12 13:44:50 -0400 |
commit | 38a00840638b4932152bca48098dbfa069d942a2 (patch) | |
tree | dd12897854f6df8aac237d5fd46551c74be8153a /drivers/net/wireless/ath/carl9170/rx.c | |
parent | 391e5c22f5f4e55817f8ba18a08ea717ed2d4a1f (diff) | |
parent | 2f8684ce7a47c91da7e0ccba2686277c103d02b6 (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next into for-davem
Diffstat (limited to 'drivers/net/wireless/ath/carl9170/rx.c')
-rw-r--r-- | drivers/net/wireless/ath/carl9170/rx.c | 49 |
1 files changed, 49 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index 7a8e90eaad83..6f6a34155667 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c | |||
@@ -576,6 +576,53 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) | |||
576 | } | 576 | } |
577 | } | 577 | } |
578 | 578 | ||
579 | static void carl9170_ba_check(struct ar9170 *ar, void *data, unsigned int len) | ||
580 | { | ||
581 | struct ieee80211_bar *bar = (void *) data; | ||
582 | struct carl9170_bar_list_entry *entry; | ||
583 | unsigned int queue; | ||
584 | |||
585 | if (likely(!ieee80211_is_back(bar->frame_control))) | ||
586 | return; | ||
587 | |||
588 | if (len <= sizeof(*bar) + FCS_LEN) | ||
589 | return; | ||
590 | |||
591 | queue = TID_TO_WME_AC(((le16_to_cpu(bar->control) & | ||
592 | IEEE80211_BAR_CTRL_TID_INFO_MASK) >> | ||
593 | IEEE80211_BAR_CTRL_TID_INFO_SHIFT) & 7); | ||
594 | |||
595 | rcu_read_lock(); | ||
596 | list_for_each_entry_rcu(entry, &ar->bar_list[queue], list) { | ||
597 | struct sk_buff *entry_skb = entry->skb; | ||
598 | struct _carl9170_tx_superframe *super = (void *)entry_skb->data; | ||
599 | struct ieee80211_bar *entry_bar = (void *)super->frame_data; | ||
600 | |||
601 | #define TID_CHECK(a, b) ( \ | ||
602 | ((a) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK)) == \ | ||
603 | ((b) & cpu_to_le16(IEEE80211_BAR_CTRL_TID_INFO_MASK))) \ | ||
604 | |||
605 | if (bar->start_seq_num == entry_bar->start_seq_num && | ||
606 | TID_CHECK(bar->control, entry_bar->control) && | ||
607 | compare_ether_addr(bar->ra, entry_bar->ta) == 0 && | ||
608 | compare_ether_addr(bar->ta, entry_bar->ra) == 0) { | ||
609 | struct ieee80211_tx_info *tx_info; | ||
610 | |||
611 | tx_info = IEEE80211_SKB_CB(entry_skb); | ||
612 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | ||
613 | |||
614 | spin_lock_bh(&ar->bar_list_lock[queue]); | ||
615 | list_del_rcu(&entry->list); | ||
616 | spin_unlock_bh(&ar->bar_list_lock[queue]); | ||
617 | kfree_rcu(entry, head); | ||
618 | break; | ||
619 | } | ||
620 | } | ||
621 | rcu_read_unlock(); | ||
622 | |||
623 | #undef TID_CHECK | ||
624 | } | ||
625 | |||
579 | static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms) | 626 | static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms) |
580 | { | 627 | { |
581 | __le16 fc; | 628 | __le16 fc; |
@@ -738,6 +785,8 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) | |||
738 | 785 | ||
739 | carl9170_ps_beacon(ar, buf, mpdu_len); | 786 | carl9170_ps_beacon(ar, buf, mpdu_len); |
740 | 787 | ||
788 | carl9170_ba_check(ar, buf, mpdu_len); | ||
789 | |||
741 | skb = carl9170_rx_copy_data(buf, mpdu_len); | 790 | skb = carl9170_rx_copy_data(buf, mpdu_len); |
742 | if (!skb) | 791 | if (!skb) |
743 | goto drop; | 792 | goto drop; |