From a841c50472bac9035c1ae33d5b50f1e063a7bd82 Mon Sep 17 00:00:00 2001 From: Christian Lamparter Date: Sun, 10 Oct 2010 01:15:07 +0200 Subject: [PATCH] --- yaml --- r: 215307 b: refs/heads/master c: 8f236d1bef659ca69c912536a69b3031e5ba3269 h: refs/heads/master i: 215305: 7e4b4c9aa8b709d91572ffb2eddecd24aee52e4f 215303: b34043f7514b02b5c9bb454c455a779c8b97b804 v: v3 --- [refs] | 2 +- trunk/drivers/net/wireless/ath/carl9170/rx.c | 42 +++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/[refs] b/[refs] index 8bf574addc2a..4dc669a3166b 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 9f59f3c694c184c69e0be7d0fd0829bcb61b0429 +refs/heads/master: 8f236d1bef659ca69c912536a69b3031e5ba3269 diff --git a/trunk/drivers/net/wireless/ath/carl9170/rx.c b/trunk/drivers/net/wireless/ath/carl9170/rx.c index 256dd42bb4ab..939a0e96ed1f 100644 --- a/trunk/drivers/net/wireless/ath/carl9170/rx.c +++ b/trunk/drivers/net/wireless/ath/carl9170/rx.c @@ -576,6 +576,41 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) } } +static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms) +{ + __le16 fc; + + if ((ms & AR9170_RX_STATUS_MPDU) == AR9170_RX_STATUS_MPDU_SINGLE) { + /* + * This frame is not part of an aMPDU. + * Therefore it is not subjected to any + * of the following content restrictions. + */ + return true; + } + + /* + * "802.11n - 7.4a.3 A-MPDU contents" describes in which contexts + * certain frame types can be part of an aMPDU. + * + * In order to keep the processing cost down, I opted for a + * stateless filter solely based on the frame control field. + */ + + fc = ((struct ieee80211_hdr *)buf)->frame_control; + if (ieee80211_is_data_qos(fc) && ieee80211_is_data_present(fc)) + return true; + + if (ieee80211_is_ack(fc) || ieee80211_is_back(fc) || + ieee80211_is_back_req(fc)) + return true; + + if (ieee80211_is_action(fc)) + return true; + + return false; +} + /* * If the frame alignment is right (or the kernel has * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there @@ -594,6 +629,7 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) struct ieee80211_rx_status status; struct sk_buff *skb; int mpdu_len; + u8 mac_status; if (!IS_STARTED(ar)) return; @@ -604,7 +640,8 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) mpdu_len = len - sizeof(*mac); mac = (void *)(buf + mpdu_len); - switch (mac->status & AR9170_RX_STATUS_MPDU) { + mac_status = mac->status; + switch (mac_status & AR9170_RX_STATUS_MPDU) { case AR9170_RX_STATUS_MPDU_FIRST: /* Aggregated MPDUs start with an PLCP header */ 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) if (unlikely(carl9170_rx_mac_status(ar, head, mac, &status))) goto drop; + if (!carl9170_ampdu_check(ar, buf, mac_status)) + goto drop; + if (phy) carl9170_rx_phy_status(ar, phy, &status);