diff options
Diffstat (limited to 'drivers/net/wireless/ath/carl9170/rx.c')
| -rw-r--r-- | drivers/net/wireless/ath/carl9170/rx.c | 69 |
1 files changed, 43 insertions, 26 deletions
diff --git a/drivers/net/wireless/ath/carl9170/rx.c b/drivers/net/wireless/ath/carl9170/rx.c index a0b72307854..924135b8e57 100644 --- a/drivers/net/wireless/ath/carl9170/rx.c +++ b/drivers/net/wireless/ath/carl9170/rx.c @@ -37,7 +37,6 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include <linux/init.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/etherdevice.h> @@ -164,9 +163,6 @@ void carl9170_handle_command_response(struct ar9170 *ar, void *buf, u32 len) struct carl9170_rsp *cmd = buf; struct ieee80211_vif *vif; - if (carl9170_check_sequence(ar, cmd->hdr.seq)) - return; - if ((cmd->hdr.cmd & CARL9170_RSP_FLAG) != CARL9170_RSP_FLAG) { if (!(cmd->hdr.cmd & CARL9170_CMD_ASYNC_FLAG)) carl9170_cmd_callback(ar, len, buf); @@ -523,6 +519,7 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) { struct ieee80211_hdr *hdr = data; struct ieee80211_tim_ie *tim_ie; + struct ath_common *common = &ar->common; u8 *tim; u8 tim_len; bool cam; @@ -530,17 +527,13 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) if (likely(!(ar->hw->conf.flags & IEEE80211_CONF_PS))) return; - /* check if this really is a beacon */ - if (!ieee80211_is_beacon(hdr->frame_control)) - return; - /* min. beacon length + FCS_LEN */ if (len <= 40 + FCS_LEN) return; + /* check if this really is a beacon */ /* and only beacons from the associated BSSID, please */ - if (!ether_addr_equal(hdr->addr3, ar->common.curbssid) || - !ar->common.curaid) + if (!ath_is_mybeacon(common, hdr) || !common->curaid) return; ar->ps.last_beacon = jiffies; @@ -579,7 +572,7 @@ static void carl9170_ps_beacon(struct ar9170 *ar, void *data, unsigned int len) static void carl9170_ba_check(struct ar9170 *ar, void *data, unsigned int len) { - struct ieee80211_bar *bar = (void *) data; + struct ieee80211_bar *bar = data; struct carl9170_bar_list_entry *entry; unsigned int queue; @@ -605,8 +598,8 @@ static void carl9170_ba_check(struct ar9170 *ar, void *data, unsigned int len) if (bar->start_seq_num == entry_bar->start_seq_num && TID_CHECK(bar->control, entry_bar->control) && - compare_ether_addr(bar->ra, entry_bar->ta) == 0 && - compare_ether_addr(bar->ta, entry_bar->ra) == 0) { + ether_addr_equal_64bits(bar->ra, entry_bar->ta) && + ether_addr_equal_64bits(bar->ta, entry_bar->ra)) { struct ieee80211_tx_info *tx_info; tx_info = IEEE80211_SKB_CB(entry_skb); @@ -663,6 +656,35 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms, return false; } +static int carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len, + struct ieee80211_rx_status *status) +{ + struct sk_buff *skb; + + /* (driver) frame trap handler + * + * Because power-saving mode handing has to be implemented by + * the driver/firmware. We have to check each incoming beacon + * from the associated AP, if there's new data for us (either + * broadcast/multicast or unicast) we have to react quickly. + * + * So, if you have you want to add additional frame trap + * handlers, this would be the perfect place! + */ + + carl9170_ps_beacon(ar, buf, len); + + carl9170_ba_check(ar, buf, len); + + skb = carl9170_rx_copy_data(buf, len); + if (!skb) + return -ENOMEM; + + memcpy(IEEE80211_SKB_RXCB(skb), status, sizeof(*status)); + ieee80211_rx(ar->hw, skb); + return 0; +} + /* * If the frame alignment is right (or the kernel has * CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS), and there @@ -672,14 +694,12 @@ static bool carl9170_ampdu_check(struct ar9170 *ar, u8 *buf, u8 ms, * mode, and we need to observe the proper ordering, * this is non-trivial. */ - -static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) +static void carl9170_rx_untie_data(struct ar9170 *ar, u8 *buf, int len) { struct ar9170_rx_head *head; struct ar9170_rx_macstatus *mac; struct ar9170_rx_phystatus *phy = NULL; struct ieee80211_rx_status status; - struct sk_buff *skb; int mpdu_len; u8 mac_status; @@ -790,19 +810,13 @@ static void carl9170_handle_mpdu(struct ar9170 *ar, u8 *buf, int len) if (phy) carl9170_rx_phy_status(ar, phy, &status); + else + status.flag |= RX_FLAG_NO_SIGNAL_VAL; - carl9170_ps_beacon(ar, buf, mpdu_len); - - carl9170_ba_check(ar, buf, mpdu_len); - - skb = carl9170_rx_copy_data(buf, mpdu_len); - if (!skb) + if (carl9170_handle_mpdu(ar, buf, mpdu_len, &status)) goto drop; - memcpy(IEEE80211_SKB_RXCB(skb), &status, sizeof(status)); - ieee80211_rx(ar->hw, skb); return; - drop: ar->rx_dropped++; } @@ -820,6 +834,9 @@ static void carl9170_rx_untie_cmds(struct ar9170 *ar, const u8 *respbuf, if (unlikely(i > resplen)) break; + if (carl9170_check_sequence(ar, cmd->hdr.seq)) + break; + carl9170_handle_command_response(ar, cmd, cmd->hdr.len + 4); } @@ -851,7 +868,7 @@ static void __carl9170_rx(struct ar9170 *ar, u8 *buf, unsigned int len) if (i == 12) carl9170_rx_untie_cmds(ar, buf, len); else - carl9170_handle_mpdu(ar, buf, len); + carl9170_rx_untie_data(ar, buf, len); } static void carl9170_rx_stream(struct ar9170 *ar, void *buf, unsigned int len) |
