]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - net/mac80211/rx.c
Merge tag 'armsoc-drivers' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc
[linux.git] / net / mac80211 / rx.c
index 96611d5dfadb0ce37effd4adcce80454bb69f285..3bd3b57697970f8ad2c756d1ab69a360b465ff38 100644 (file)
@@ -115,7 +115,8 @@ static inline bool should_drop_frame(struct sk_buff *skb, int present_fcs_len,
 
        if (status->flag & (RX_FLAG_FAILED_FCS_CRC |
                            RX_FLAG_FAILED_PLCP_CRC |
-                           RX_FLAG_ONLY_MONITOR))
+                           RX_FLAG_ONLY_MONITOR |
+                           RX_FLAG_NO_PSDU))
                return true;
 
        if (unlikely(skb->len < 16 + present_fcs_len + rtap_space))
@@ -189,6 +190,15 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
                BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_he_mu) != 12);
        }
 
+       if (status->flag & RX_FLAG_NO_PSDU)
+               len += 1;
+
+       if (status->flag & RX_FLAG_RADIOTAP_LSIG) {
+               len = ALIGN(len, 2);
+               len += 4;
+               BUILD_BUG_ON(sizeof(struct ieee80211_radiotap_lsig) != 4);
+       }
+
        if (status->chains) {
                /* antenna and antenna signal fields */
                len += 2 * hweight8(status->chains);
@@ -279,6 +289,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        struct ieee80211_vendor_radiotap rtap = {};
        struct ieee80211_radiotap_he he = {};
        struct ieee80211_radiotap_he_mu he_mu = {};
+       struct ieee80211_radiotap_lsig lsig = {};
 
        if (status->flag & RX_FLAG_RADIOTAP_HE) {
                he = *(struct ieee80211_radiotap_he *)skb->data;
@@ -291,6 +302,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
                skb_pull(skb, sizeof(he_mu));
        }
 
+       if (status->flag & RX_FLAG_RADIOTAP_LSIG) {
+               lsig = *(struct ieee80211_radiotap_lsig *)skb->data;
+               skb_pull(skb, sizeof(lsig));
+       }
+
        if (status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA) {
                rtap = *(struct ieee80211_vendor_radiotap *)skb->data;
                /* rtap.len and rtap.pad are undone immediately */
@@ -549,7 +565,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
 
        if (status->encoding == RX_ENC_HE &&
            status->flag & RX_FLAG_RADIOTAP_HE) {
-#define HE_PREP(f, val)        cpu_to_le16(FIELD_PREP(IEEE80211_RADIOTAP_HE_##f, val))
+#define HE_PREP(f, val)        le16_encode_bits(val, IEEE80211_RADIOTAP_HE_##f)
 
                if (status->enc_flags & RX_ENC_FLAG_STBC_MASK) {
                        he.data6 |= HE_PREP(DATA6_NSTS,
@@ -630,6 +646,21 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
                pos += sizeof(he_mu);
        }
 
+       if (status->flag & RX_FLAG_NO_PSDU) {
+               rthdr->it_present |=
+                       cpu_to_le32(1 << IEEE80211_RADIOTAP_ZERO_LEN_PSDU);
+               *pos++ = status->zero_length_psdu_type;
+       }
+
+       if (status->flag & RX_FLAG_RADIOTAP_LSIG) {
+               /* ensure 2 byte alignment */
+               while ((pos - (u8 *)rthdr) & 1)
+                       pos++;
+               rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_LSIG);
+               memcpy(pos, &lsig, sizeof(lsig));
+               pos += sizeof(lsig);
+       }
+
        for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) {
                *pos++ = status->chain_signal[chain];
                *pos++ = chain;
@@ -1505,7 +1536,7 @@ static void sta_ps_start(struct sta_info *sta)
        if (!sta->sta.txq[0])
                return;
 
-       for (tid = 0; tid < ARRAY_SIZE(sta->sta.txq); tid++) {
+       for (tid = 0; tid < IEEE80211_NUM_TIDS; tid++) {
                if (txq_has_queue(sta->sta.txq[tid]))
                        set_bit(tid, &sta->txq_buffered_tids);
                else
@@ -2046,6 +2077,7 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
        idx = sdata->fragment_next;
        for (i = 0; i < IEEE80211_FRAGMENT_MAX; i++) {
                struct ieee80211_hdr *f_hdr;
+               struct sk_buff *f_skb;
 
                idx--;
                if (idx < 0)
@@ -2057,7 +2089,8 @@ ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
                    entry->last_frag + 1 != frag)
                        continue;
 
-               f_hdr = (struct ieee80211_hdr *)entry->skb_list.next->data;
+               f_skb = __skb_peek(&entry->skb_list);
+               f_hdr = (struct ieee80211_hdr *) f_skb->data;
 
                /*
                 * Check ftype and addresses are equal, else check next fragment
@@ -2314,7 +2347,7 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control)
 
                if (!sdata->u.mgd.use_4addr)
                        return -1;
-               else
+               else if (!ether_addr_equal(hdr->addr1, sdata->vif.addr))
                        check_port_control = true;
        }
 
@@ -2425,8 +2458,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
                        if (!xmit_skb)
                                net_info_ratelimited("%s: failed to clone multicast frame\n",
                                                    dev->name);
-               } else if (!is_multicast_ether_addr(ehdr->h_dest)) {
-                       dsta = sta_info_get(sdata, skb->data);
+               } else if (!is_multicast_ether_addr(ehdr->h_dest) &&
+                          !ether_addr_equal(ehdr->h_dest, ehdr->h_source)) {
+                       dsta = sta_info_get(sdata, ehdr->h_dest);
                        if (dsta) {
                                /*
                                 * The destination station is associated to
@@ -4207,11 +4241,10 @@ static bool ieee80211_invoke_fast_rx(struct ieee80211_rx_data *rx,
 
        if (fast_rx->internal_forward) {
                struct sk_buff *xmit_skb = NULL;
-               bool multicast = is_multicast_ether_addr(skb->data);
-
-               if (multicast) {
+               if (is_multicast_ether_addr(addrs.da)) {
                        xmit_skb = skb_copy(skb, GFP_ATOMIC);
-               } else if (sta_info_get(rx->sdata, skb->data)) {
+               } else if (!ether_addr_equal(addrs.da, addrs.sa) &&
+                          sta_info_get(rx->sdata, addrs.da)) {
                        xmit_skb = skb;
                        skb = NULL;
                }