aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/carl9170/rx.c
diff options
context:
space:
mode:
authorChristian Lamparter <chunkeey@googlemail.com>2010-10-09 19:15:07 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-10-11 15:04:23 -0400
commit8f236d1bef659ca69c912536a69b3031e5ba3269 (patch)
tree84698876160061a099bd9709f6bc660b1e1d0ffd /drivers/net/wireless/ath/carl9170/rx.c
parent9f59f3c694c184c69e0be7d0fd0829bcb61b0429 (diff)
carl9170: A-MPDU frame type filter
In the past, carl9170 has been plagued by mysterious ghosts. e.g.: wlan4: deauthenticated from 02:04:d8:3c:ac:c1 (Reason: 0) Apparently, the AP sent us a bogus deauthentication notification. But upon closer inspection the "management frame" turned out to be a corrupted scrap of an unsuccessful A-MPDU. Signed-off-by: Christian Lamparter <chunkeey@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/carl9170/rx.c')
-rw-r--r--drivers/net/wireless/ath/carl9170/rx.c42
1 files changed, 41 insertions, 1 deletions
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c
index 256dd42bb4a..939a0e96ed1 100644
--- a/drivers/net/wireless/ath/carl9170/rx.c
+++ b/drivers/net/wireless/ath/carl9170/rx.c
@@ -576,6 +576,41 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len)
576 } 576 }
577} 577}
578 578
579static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms)
580{
581 __le16 fc;
582
583 if ((ms & AR9170_RX_STATUS_MPDU) == AR9170_RX_STATUS_MPDU_SINGLE) {
584 /*
585 * This frame is not part of an aMPDU.
586 * Therefore it is not subjected to any
587 * of the following content restrictions.
588 */
589 return true;
590 }
591
592 /*
593 * "802.11n - 7.4a.3 A-MPDU contents" describes in which contexts
594 * certain frame types can be part of an aMPDU.
595 *
596 * In order to keep the processing cost down, I opted for a
597 * stateless filter solely based on the frame control field.
598 */
599
600 fc = ((struct ieee80211_hdr *)buf)->frame_control;
601 if (ieee80211_is_data_qos(fc) && ieee80211_is_data_present(fc))
602 return true;
603
604 if (ieee80211_is_ack(fc) || ieee80211_is_back(fc) ||
605 ieee80211_is_back_req(fc))
606 return true;
607
608 if (ieee80211_is_action(fc))
609 return true;
610
611 return false;
612}
613
579/* 614/*
580 * If the frame alignment is right (or the kernel has 615 * If the frame alignment is right (or the kernel has
581 * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there 616 * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there
@@ -594,6 +629,7 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
594 struct ieee80211_rx_status status; 629 struct ieee80211_rx_status status;
595 struct sk_buff *skb; 630 struct sk_buff *skb;
596 int mpdu_len; 631 int mpdu_len;
632 u8 mac_status;
597 633
598 if (!IS_STARTED(ar)) 634 if (!IS_STARTED(ar))
599 return; 635 return;
@@ -604,7 +640,8 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
604 mpdu_len = len - sizeof(*mac); 640 mpdu_len = len - sizeof(*mac);
605 641
606 mac = (void *)(buf + mpdu_len); 642 mac = (void *)(buf + mpdu_len);
607 switch (mac->status & AR9170_RX_STATUS_MPDU) { 643 mac_status = mac->status;
644 switch (mac_status & AR9170_RX_STATUS_MPDU) {
608 case AR9170_RX_STATUS_MPDU_FIRST: 645 case AR9170_RX_STATUS_MPDU_FIRST:
609 /* Aggregated MPDUs start with an PLCP header */ 646 /* Aggregated MPDUs start with an PLCP header */
610 if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) { 647 if (likely(mpdu_len >= sizeof(struct ar9170_rx_head))) {
@@ -693,6 +730,9 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len)
693 if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status))) 730 if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status)))
694 goto drop; 731 goto drop;
695 732
733 if (!carl9170_ampdu_check(ar, buf, mac_status))
734 goto drop;
735
696 if (phy) 736 if (phy)
697 carl9170_rx_phy_status(ar, phy, &status); 737 carl9170_rx_phy_status(ar, phy, &status);
698 738