These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / net / mac80211 / rx.c
index f6f8d98..0e9e264 100644 (file)
 #include "wme.h"
 #include "rate.h"
 
+static inline void ieee80211_rx_stats(struct net_device *dev, u32 len)
+{
+       struct pcpu_sw_netstats *tstats = this_cpu_ptr(dev->tstats);
+
+       u64_stats_update_begin(&tstats->syncp);
+       tstats->rx_packets++;
+       tstats->rx_bytes += len;
+       u64_stats_update_end(&tstats->syncp);
+}
+
+static u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
+                              enum nl80211_iftype type)
+{
+       __le16 fc = hdr->frame_control;
+
+       if (ieee80211_is_data(fc)) {
+               if (len < 24) /* drop incorrect hdr len (data) */
+                       return NULL;
+
+               if (ieee80211_has_a4(fc))
+                       return NULL;
+               if (ieee80211_has_tods(fc))
+                       return hdr->addr1;
+               if (ieee80211_has_fromds(fc))
+                       return hdr->addr2;
+
+               return hdr->addr3;
+       }
+
+       if (ieee80211_is_mgmt(fc)) {
+               if (len < 24) /* drop incorrect hdr len (mgmt) */
+                       return NULL;
+               return hdr->addr3;
+       }
+
+       if (ieee80211_is_ctl(fc)) {
+               if (ieee80211_is_pspoll(fc))
+                       return hdr->addr1;
+
+               if (ieee80211_is_back_req(fc)) {
+                       switch (type) {
+                       case NL80211_IFTYPE_STATION:
+                               return hdr->addr2;
+                       case NL80211_IFTYPE_AP:
+                       case NL80211_IFTYPE_AP_VLAN:
+                               return hdr->addr1;
+                       default:
+                               break; /* fall through to the return */
+                       }
+               }
+       }
+
+       return NULL;
+}
+
 /*
  * monitor mode reception
  *
@@ -42,7 +97,7 @@ static struct sk_buff *remove_monitor_info(struct ieee80211_local *local,
                                           struct sk_buff *skb,
                                           unsigned int rtap_vendor_space)
 {
-       if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS) {
+       if (ieee80211_hw_check(&local->hw, RX_INCLUDES_FCS)) {
                if (likely(skb->len > FCS_LEN))
                        __pskb_trim(skb, skb->len - FCS_LEN);
                else {
@@ -67,8 +122,7 @@ static inline bool should_drop_frame(struct sk_buff *skb, int present_fcs_len,
        hdr = (void *)(skb->data + rtap_vendor_space);
 
        if (status->flag & (RX_FLAG_FAILED_FCS_CRC |
-                           RX_FLAG_FAILED_PLCP_CRC |
-                           RX_FLAG_AMPDU_IS_ZEROLEN))
+                           RX_FLAG_FAILED_PLCP_CRC))
                return true;
 
        if (unlikely(skb->len < 16 + present_fcs_len + rtap_vendor_space))
@@ -100,7 +154,7 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
                len = ALIGN(len, 8);
                len += 8;
        }
-       if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
+       if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
                len += 1;
 
        /* antenna field, if we don't have per-chain info */
@@ -175,7 +229,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        }
 
        mpdulen = skb->len;
-       if (!(has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)))
+       if (!(has_fcs && ieee80211_hw_check(&local->hw, RX_INCLUDES_FCS)))
                mpdulen += FCS_LEN;
 
        rthdr = (struct ieee80211_radiotap_header *)skb_push(skb, rtap_len);
@@ -229,7 +283,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        }
 
        /* IEEE80211_RADIOTAP_FLAGS */
-       if (has_fcs && (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS))
+       if (has_fcs && ieee80211_hw_check(&local->hw, RX_INCLUDES_FCS))
                *pos |= IEEE80211_RADIOTAP_F_FCS;
        if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
                *pos |= IEEE80211_RADIOTAP_F_BADFCS;
@@ -279,7 +333,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        pos += 2;
 
        /* IEEE80211_RADIOTAP_DBM_ANTSIGNAL */
-       if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM &&
+       if (ieee80211_hw_check(&local->hw, SIGNAL_DBM) &&
            !(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
                *pos = status->signal;
                rthdr->it_present |=
@@ -336,10 +390,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
                        cpu_to_le32(1 << IEEE80211_RADIOTAP_AMPDU_STATUS);
                put_unaligned_le32(status->ampdu_reference, pos);
                pos += 4;
-               if (status->flag & RX_FLAG_AMPDU_REPORT_ZEROLEN)
-                       flags |= IEEE80211_RADIOTAP_AMPDU_REPORT_ZEROLEN;
-               if (status->flag & RX_FLAG_AMPDU_IS_ZEROLEN)
-                       flags |= IEEE80211_RADIOTAP_AMPDU_IS_ZEROLEN;
                if (status->flag & RX_FLAG_AMPDU_LAST_KNOWN)
                        flags |= IEEE80211_RADIOTAP_AMPDU_LAST_KNOWN;
                if (status->flag & RX_FLAG_AMPDU_IS_LAST)
@@ -448,7 +498,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
         * the SKB because it has a bad FCS/PLCP checksum.
         */
 
-       if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
+       if (ieee80211_hw_check(&local->hw, RX_INCLUDES_FCS))
                present_fcs_len = FCS_LEN;
 
        /* ensure hdr->frame_control and vendor radiotap data are in skb head */
@@ -529,8 +579,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
                }
 
                prev_dev = sdata->dev;
-               sdata->dev->stats.rx_packets++;
-               sdata->dev->stats.rx_bytes += skb->len;
+               ieee80211_rx_stats(sdata->dev, skb->len);
        }
 
        if (prev_dev) {
@@ -981,7 +1030,6 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
        struct sk_buff *skb = rx->skb;
        struct ieee80211_local *local = rx->local;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
-       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct sta_info *sta = rx->sta;
        struct tid_ampdu_rx *tid_agg_rx;
        u16 sc;
@@ -1016,10 +1064,6 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
            ack_policy != IEEE80211_QOS_CTL_ACK_POLICY_NORMAL)
                goto dont_reorder;
 
-       /* not actually part of this BA session */
-       if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
-               goto dont_reorder;
-
        /* new, potentially un-ordered, ampdu frame - process it */
 
        /* reset session timer */
@@ -1069,18 +1113,16 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx)
            is_multicast_ether_addr(hdr->addr1))
                return RX_CONTINUE;
 
-       if (rx->sta) {
-               if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
-                            rx->sta->last_seq_ctrl[rx->seqno_idx] ==
-                            hdr->seq_ctrl)) {
-                       if (status->rx_flags & IEEE80211_RX_RA_MATCH) {
-                               rx->local->dot11FrameDuplicateCount++;
-                               rx->sta->num_duplicates++;
-                       }
-                       return RX_DROP_UNUSABLE;
-               } else if (!(status->flag & RX_FLAG_AMSDU_MORE)) {
-                       rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl;
-               }
+       if (!rx->sta)
+               return RX_CONTINUE;
+
+       if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
+                    rx->sta->last_seq_ctrl[rx->seqno_idx] == hdr->seq_ctrl)) {
+               I802_DEBUG_INC(rx->local->dot11FrameDuplicateCount);
+               rx->sta->rx_stats.num_duplicates++;
+               return RX_DROP_UNUSABLE;
+       } else if (!(status->flag & RX_FLAG_AMSDU_MORE)) {
+               rx->sta->last_seq_ctrl[rx->seqno_idx] = hdr->seq_ctrl;
        }
 
        return RX_CONTINUE;
@@ -1091,11 +1133,6 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
 
-       if (unlikely(rx->skb->len < 16)) {
-               I802_DEBUG_INC(rx->local->rx_handlers_drop_short);
-               return RX_DROP_MONITOR;
-       }
-
        /* Drop disallowed frame classes based on STA auth/assoc state;
         * IEEE 802.11, Chap 5.5.
         *
@@ -1195,11 +1232,13 @@ static void sta_ps_start(struct sta_info *sta)
 
        atomic_inc(&ps->num_sta_ps);
        set_sta_flag(sta, WLAN_STA_PS_STA);
-       if (!(local->hw.flags & IEEE80211_HW_AP_LINK_PS))
+       if (!ieee80211_hw_check(&local->hw, AP_LINK_PS))
                drv_sta_notify(local, sdata, STA_NOTIFY_SLEEP, &sta->sta);
        ps_dbg(sdata, "STA %pM aid %d enters power save mode\n",
               sta->sta.addr, sta->sta.aid);
 
+       ieee80211_clear_fast_xmit(sta);
+
        if (!sta->sta.txq[0])
                return;
 
@@ -1236,22 +1275,22 @@ static void sta_ps_end(struct sta_info *sta)
        ieee80211_sta_ps_deliver_wakeup(sta);
 }
 
-int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start)
+int ieee80211_sta_ps_transition(struct ieee80211_sta *pubsta, bool start)
 {
-       struct sta_info *sta_inf = container_of(sta, struct sta_info, sta);
+       struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
        bool in_ps;
 
-       WARN_ON(!(sta_inf->local->hw.flags & IEEE80211_HW_AP_LINK_PS));
+       WARN_ON(!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS));
 
        /* Don't let the same PS state be set twice */
-       in_ps = test_sta_flag(sta_inf, WLAN_STA_PS_STA);
+       in_ps = test_sta_flag(sta, WLAN_STA_PS_STA);
        if ((start && in_ps) || (!start && !in_ps))
                return -EINVAL;
 
        if (start)
-               sta_ps_start(sta_inf);
+               sta_ps_start(sta);
        else
-               sta_ps_end(sta_inf);
+               sta_ps_end(sta);
 
        return 0;
 }
@@ -1265,7 +1304,7 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
        int tid, ac;
 
-       if (!rx->sta || !(status->rx_flags & IEEE80211_RX_RA_MATCH))
+       if (!rx->sta)
                return RX_CONTINUE;
 
        if (sdata->vif.type != NL80211_IFTYPE_AP &&
@@ -1277,7 +1316,7 @@ ieee80211_rx_h_uapsd_and_pspoll(struct ieee80211_rx_data *rx)
         * uAPSD and PS-Poll frames (the latter shouldn't even come up from
         * it to mac80211 since they're handled.)
         */
-       if (sdata->local->hw.flags & IEEE80211_HW_AP_LINK_PS)
+       if (ieee80211_hw_check(&sdata->local->hw, AP_LINK_PS))
                return RX_CONTINUE;
 
        /*
@@ -1357,58 +1396,56 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
                                                NL80211_IFTYPE_ADHOC);
                if (ether_addr_equal(bssid, rx->sdata->u.ibss.bssid) &&
                    test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
-                       sta->last_rx = jiffies;
+                       sta->rx_stats.last_rx = jiffies;
                        if (ieee80211_is_data(hdr->frame_control) &&
                            !is_multicast_ether_addr(hdr->addr1)) {
-                               sta->last_rx_rate_idx = status->rate_idx;
-                               sta->last_rx_rate_flag = status->flag;
-                               sta->last_rx_rate_vht_flag = status->vht_flag;
-                               sta->last_rx_rate_vht_nss = status->vht_nss;
+                               sta->rx_stats.last_rate_idx =
+                                       status->rate_idx;
+                               sta->rx_stats.last_rate_flag =
+                                       status->flag;
+                               sta->rx_stats.last_rate_vht_flag =
+                                       status->vht_flag;
+                               sta->rx_stats.last_rate_vht_nss =
+                                       status->vht_nss;
                        }
                }
        } else if (rx->sdata->vif.type == NL80211_IFTYPE_OCB) {
-               u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
-                                               NL80211_IFTYPE_OCB);
-               /* OCB uses wild-card BSSID */
-               if (is_broadcast_ether_addr(bssid))
-                       sta->last_rx = jiffies;
+               sta->rx_stats.last_rx = jiffies;
        } else if (!is_multicast_ether_addr(hdr->addr1)) {
                /*
                 * Mesh beacons will update last_rx when if they are found to
                 * match the current local configuration when processed.
                 */
-               sta->last_rx = jiffies;
+               sta->rx_stats.last_rx = jiffies;
                if (ieee80211_is_data(hdr->frame_control)) {
-                       sta->last_rx_rate_idx = status->rate_idx;
-                       sta->last_rx_rate_flag = status->flag;
-                       sta->last_rx_rate_vht_flag = status->vht_flag;
-                       sta->last_rx_rate_vht_nss = status->vht_nss;
+                       sta->rx_stats.last_rate_idx = status->rate_idx;
+                       sta->rx_stats.last_rate_flag = status->flag;
+                       sta->rx_stats.last_rate_vht_flag = status->vht_flag;
+                       sta->rx_stats.last_rate_vht_nss = status->vht_nss;
                }
        }
 
-       if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
-               return RX_CONTINUE;
-
        if (rx->sdata->vif.type == NL80211_IFTYPE_STATION)
                ieee80211_sta_rx_notify(rx->sdata, hdr);
 
-       sta->rx_fragments++;
-       sta->rx_bytes += rx->skb->len;
+       sta->rx_stats.fragments++;
+       sta->rx_stats.bytes += rx->skb->len;
        if (!(status->flag & RX_FLAG_NO_SIGNAL_VAL)) {
-               sta->last_signal = status->signal;
-               ewma_add(&sta->avg_signal, -status->signal);
+               sta->rx_stats.last_signal = status->signal;
+               ewma_signal_add(&sta->rx_stats.avg_signal, -status->signal);
        }
 
        if (status->chains) {
-               sta->chains = status->chains;
+               sta->rx_stats.chains = status->chains;
                for (i = 0; i < ARRAY_SIZE(status->chain_signal); i++) {
                        int signal = status->chain_signal[i];
 
                        if (!(status->chains & BIT(i)))
                                continue;
 
-                       sta->chain_signal_last[i] = signal;
-                       ewma_add(&sta->chain_signal_avg[i], -signal);
+                       sta->rx_stats.chain_signal_last[i] = signal;
+                       ewma_signal_add(&sta->rx_stats.chain_signal_avg[i],
+                                       -signal);
                }
        }
 
@@ -1416,7 +1453,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
         * Change STA power saving mode only at the end of a frame
         * exchange sequence.
         */
-       if (!(sta->local->hw.flags & IEEE80211_HW_AP_LINK_PS) &&
+       if (!ieee80211_hw_check(&sta->local->hw, AP_LINK_PS) &&
            !ieee80211_has_morefrags(hdr->frame_control) &&
            !(status->rx_flags & IEEE80211_RX_DEFERRED_RELEASE) &&
            (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
@@ -1468,7 +1505,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
                 * Update counter and free packet here to avoid
                 * counting this as a dropped packed.
                 */
-               sta->rx_packets++;
+               sta->rx_stats.packets++;
                dev_kfree_skb(rx->skb);
                return RX_QUEUED;
        }
@@ -1517,13 +1554,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
         * possible.
         */
 
-       /*
-        * No point in finding a key and decrypting if the frame is neither
-        * addressed to us nor a multicast frame.
-        */
-       if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
-               return RX_CONTINUE;
-
        /* start without a key */
        rx->key = NULL;
        fc = hdr->frame_control;
@@ -1657,7 +1687,6 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
                if (unlikely(rx->key->flags & KEY_FLAG_TAINTED))
                        return RX_DROP_MONITOR;
 
-               rx->key->tx_rx_count++;
                /* TODO: add threshold stuff again */
        } else {
                return RX_DROP_MONITOR;
@@ -1725,7 +1754,7 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
        entry->seq = seq;
        entry->rx_queue = rx_queue;
        entry->last_frag = frag;
-       entry->ccmp = 0;
+       entry->check_sequential_pn = false;
        entry->extra_len = 0;
 
        return entry;
@@ -1795,7 +1824,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
        frag = sc & IEEE80211_SCTL_FRAG;
 
        if (is_multicast_ether_addr(hdr->addr1)) {
-               rx->local->dot11MulticastReceivedFrameCount++;
+               I802_DEBUG_INC(rx->local->dot11MulticastReceivedFrameCount);
                goto out_no_led;
        }
 
@@ -1821,15 +1850,27 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
                                                 rx->seqno_idx, &(rx->skb));
                if (rx->key &&
                    (rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP ||
-                    rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256) &&
+                    rx->key->conf.cipher == WLAN_CIPHER_SUITE_CCMP_256 ||
+                    rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP ||
+                    rx->key->conf.cipher == WLAN_CIPHER_SUITE_GCMP_256) &&
                    ieee80211_has_protected(fc)) {
                        int queue = rx->security_idx;
-                       /* Store CCMP PN so that we can verify that the next
-                        * fragment has a sequential PN value. */
-                       entry->ccmp = 1;
+
+                       /* Store CCMP/GCMP PN so that we can verify that the
+                        * next fragment has a sequential PN value.
+                        */
+                       entry->check_sequential_pn = true;
                        memcpy(entry->last_pn,
                               rx->key->u.ccmp.rx_pn[queue],
                               IEEE80211_CCMP_PN_LEN);
+                       BUILD_BUG_ON(offsetof(struct ieee80211_key,
+                                             u.ccmp.rx_pn) !=
+                                    offsetof(struct ieee80211_key,
+                                             u.gcmp.rx_pn));
+                       BUILD_BUG_ON(sizeof(rx->key->u.ccmp.rx_pn[queue]) !=
+                                    sizeof(rx->key->u.gcmp.rx_pn[queue]));
+                       BUILD_BUG_ON(IEEE80211_CCMP_PN_LEN !=
+                                    IEEE80211_GCMP_PN_LEN);
                }
                return RX_QUEUED;
        }
@@ -1844,15 +1885,21 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
                return RX_DROP_MONITOR;
        }
 
-       /* Verify that MPDUs within one MSDU have sequential PN values.
-        * (IEEE 802.11i, 8.3.3.4.5) */
-       if (entry->ccmp) {
+       /* "The receiver shall discard MSDUs and MMPDUs whose constituent
+        *  MPDU PN values are not incrementing in steps of 1."
+        * see IEEE P802.11-REVmc/D5.0, 12.5.3.4.4, item d (for CCMP)
+        * and IEEE P802.11-REVmc/D5.0, 12.5.5.4.4, item d (for GCMP)
+        */
+       if (entry->check_sequential_pn) {
                int i;
                u8 pn[IEEE80211_CCMP_PN_LEN], *rpn;
                int queue;
+
                if (!rx->key ||
                    (rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP &&
-                    rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256))
+                    rx->key->conf.cipher != WLAN_CIPHER_SUITE_CCMP_256 &&
+                    rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP &&
+                    rx->key->conf.cipher != WLAN_CIPHER_SUITE_GCMP_256))
                        return RX_DROP_UNUSABLE;
                memcpy(pn, entry->last_pn, IEEE80211_CCMP_PN_LEN);
                for (i = IEEE80211_CCMP_PN_LEN - 1; i >= 0; i--) {
@@ -1878,7 +1925,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 
        rx->skb = __skb_dequeue(&entry->skb_list);
        if (skb_tailroom(rx->skb) < entry->extra_len) {
-               I802_DEBUG_INC(rx->local->rx_expand_skb_head2);
+               I802_DEBUG_INC(rx->local->rx_expand_skb_head_defrag);
                if (unlikely(pskb_expand_head(rx->skb, 0, entry->extra_len,
                                              GFP_ATOMIC))) {
                        I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
@@ -1893,13 +1940,12 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 
        /* Complete frame has been reassembled - process it now */
        status = IEEE80211_SKB_RXCB(rx->skb);
-       status->rx_flags |= IEEE80211_RX_FRAGMENTED;
 
  out:
        ieee80211_led_rx(rx->local);
  out_no_led:
        if (rx->sta)
-               rx->sta->rx_packets++;
+               rx->sta->rx_stats.packets++;
        return RX_CONTINUE;
 }
 
@@ -2054,18 +2100,15 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
        struct sk_buff *skb, *xmit_skb;
        struct ethhdr *ehdr = (struct ethhdr *) rx->skb->data;
        struct sta_info *dsta;
-       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
-
-       dev->stats.rx_packets++;
-       dev->stats.rx_bytes += rx->skb->len;
 
        skb = rx->skb;
        xmit_skb = NULL;
 
+       ieee80211_rx_stats(dev, skb->len);
+
        if ((sdata->vif.type == NL80211_IFTYPE_AP ||
             sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
            !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
-           (status->rx_flags & IEEE80211_RX_RA_MATCH) &&
            (sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->u.vlan.sta)) {
                if (is_multicast_ether_addr(ehdr->h_dest)) {
                        /*
@@ -2121,9 +2164,8 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
                /* deliver to local stack */
                skb->protocol = eth_type_trans(skb, dev);
                memset(skb->cb, 0, sizeof(skb->cb));
-               if (!(rx->flags & IEEE80211_RX_REORDER_TIMER) &&
-                   rx->local->napi)
-                       napi_gro_receive(rx->local->napi, skb);
+               if (rx->napi)
+                       napi_gro_receive(rx->napi, skb);
                else
                        netif_receive_skb(skb);
        }
@@ -2207,7 +2249,6 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        struct sk_buff *skb = rx->skb, *fwd_skb;
        struct ieee80211_local *local = rx->local;
        struct ieee80211_sub_if_data *sdata = rx->sdata;
-       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
        u16 q, hdrlen;
 
@@ -2238,8 +2279,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
            mesh_rmc_check(rx->sdata, hdr->addr3, mesh_hdr))
                return RX_DROP_MONITOR;
 
-       if (!ieee80211_is_data(hdr->frame_control) ||
-           !(status->rx_flags & IEEE80211_RX_RA_MATCH))
+       if (!ieee80211_is_data(hdr->frame_control))
                return RX_CONTINUE;
 
        if (!mesh_hdr->ttl)
@@ -2330,11 +2370,9 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, fwded_frames);
        ieee80211_add_pending_skb(local, fwd_skb);
  out:
-       if (is_multicast_ether_addr(hdr->addr1) ||
-           sdata->dev->flags & IFF_PROMISC)
+       if (is_multicast_ether_addr(hdr->addr1))
                return RX_CONTINUE;
-       else
-               return RX_DROP_MONITOR;
+       return RX_DROP_MONITOR;
 }
 #endif
 
@@ -2361,7 +2399,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
                 * for non-QoS-data frames. Here we know it's a data
                 * frame, so count MSDUs.
                 */
-               rx->sta->rx_msdu[rx->seqno_idx]++;
+               rx->sta->rx_stats.msdu[rx->seqno_idx]++;
        }
 
        /*
@@ -2395,11 +2433,10 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
                    tf->category == WLAN_CATEGORY_TDLS &&
                    (tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_REQUEST ||
                     tf->action_code == WLAN_TDLS_CHANNEL_SWITCH_RESPONSE)) {
-                       rx->skb->pkt_type = IEEE80211_SDATA_QUEUE_TDLS_CHSW;
-                       skb_queue_tail(&sdata->skb_queue, rx->skb);
-                       ieee80211_queue_work(&rx->local->hw, &sdata->work);
+                       skb_queue_tail(&local->skb_queue_tdls_chsw, rx->skb);
+                       schedule_work(&local->tdls_chsw_work);
                        if (rx->sta)
-                               rx->sta->rx_packets++;
+                               rx->sta->rx_stats.packets++;
 
                        return RX_QUEUED;
                }
@@ -2445,6 +2482,9 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
                struct {
                        __le16 control, start_seq_num;
                } __packed bar_data;
+               struct ieee80211_event event = {
+                       .type = BAR_RX_EVENT,
+               };
 
                if (!rx->sta)
                        return RX_DROP_MONITOR;
@@ -2460,6 +2500,9 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
                        return RX_DROP_MONITOR;
 
                start_seq_num = le16_to_cpu(bar_data.start_seq_num) >> 4;
+               event.u.ba.tid = tid;
+               event.u.ba.ssn = start_seq_num;
+               event.u.ba.sta = &rx->sta->sta;
 
                /* reset session timer */
                if (tid_agg_rx->timeout)
@@ -2472,6 +2515,8 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
                                                 start_seq_num, frames);
                spin_unlock(&tid_agg_rx->reorder_lock);
 
+               drv_event_callback(rx->local, rx->sdata, &event);
+
                kfree_skb(skb);
                return RX_QUEUED;
        }
@@ -2552,7 +2597,7 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
            !(rx->flags & IEEE80211_RX_BEACON_REPORTED)) {
                int sig = 0;
 
-               if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
+               if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM))
                        sig = status->signal;
 
                cfg80211_report_obss_beacon(rx->local->hw.wiphy,
@@ -2561,9 +2606,6 @@ ieee80211_rx_h_mgmt_check(struct ieee80211_rx_data *rx)
                rx->flags |= IEEE80211_RX_BEACON_REPORTED;
        }
 
-       if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
-               return RX_DROP_MONITOR;
-
        if (ieee80211_drop_unencrypted_mgmt(rx))
                return RX_DROP_UNUSABLE;
 
@@ -2591,9 +2633,6 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
            mgmt->u.action.category != WLAN_CATEGORY_SPECTRUM_MGMT)
                return RX_DROP_UNUSABLE;
 
-       if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
-               return RX_DROP_UNUSABLE;
-
        switch (mgmt->u.action.category) {
        case WLAN_CATEGORY_HT:
                /* reject HT action frames from stations not supporting HT */
@@ -2715,8 +2754,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                        opmode = mgmt->u.action.u.vht_opmode_notif.operating_mode;
 
                        ieee80211_vht_handle_opmode(rx->sdata, rx->sta,
-                                                   opmode, status->band,
-                                                   false);
+                                                   opmode, status->band);
                        goto handled;
                }
                default:
@@ -2859,7 +2897,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
 
  handled:
        if (rx->sta)
-               rx->sta->rx_packets++;
+               rx->sta->rx_stats.packets++;
        dev_kfree_skb(rx->skb);
        return RX_QUEUED;
 
@@ -2868,7 +2906,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
        skb_queue_tail(&sdata->skb_queue, rx->skb);
        ieee80211_queue_work(&local->hw, &sdata->work);
        if (rx->sta)
-               rx->sta->rx_packets++;
+               rx->sta->rx_stats.packets++;
        return RX_QUEUED;
 }
 
@@ -2889,13 +2927,13 @@ ieee80211_rx_h_userspace_mgmt(struct ieee80211_rx_data *rx)
         * it transmitted were processed or returned.
         */
 
-       if (rx->local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
+       if (ieee80211_hw_check(&rx->local->hw, SIGNAL_DBM))
                sig = status->signal;
 
        if (cfg80211_rx_mgmt(&rx->sdata->wdev, status->freq, sig,
                             rx->skb->data, rx->skb->len, 0)) {
                if (rx->sta)
-                       rx->sta->rx_packets++;
+                       rx->sta->rx_stats.packets++;
                dev_kfree_skb(rx->skb);
                return RX_QUEUED;
        }
@@ -2954,7 +2992,7 @@ ieee80211_rx_h_action_return(struct ieee80211_rx_data *rx)
                        info->flags = IEEE80211_TX_CTL_TX_OFFCHAN |
                                      IEEE80211_TX_INTFL_OFFCHAN_TX_OK |
                                      IEEE80211_TX_CTL_NO_CCK_RATE;
-                       if (local->hw.flags & IEEE80211_HW_QUEUE_CONTROL)
+                       if (ieee80211_hw_check(&local->hw, QUEUE_CONTROL))
                                info->hw_queue =
                                        local->hw.offchannel_tx_hw_queue;
                }
@@ -3014,12 +3052,11 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
        skb_queue_tail(&sdata->skb_queue, rx->skb);
        ieee80211_queue_work(&rx->local->hw, &sdata->work);
        if (rx->sta)
-               rx->sta->rx_packets++;
+               rx->sta->rx_stats.packets++;
 
        return RX_QUEUED;
 }
 
-/* TODO: use IEEE80211_RX_FRAGMENTED */
 static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
                                        struct ieee80211_rate *rate)
 {
@@ -3077,8 +3114,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
                }
 
                prev_dev = sdata->dev;
-               sdata->dev->stats.rx_packets++;
-               sdata->dev->stats.rx_bytes += skb->len;
+               ieee80211_rx_stats(sdata->dev, skb->len);
        }
 
        if (prev_dev) {
@@ -3098,7 +3134,7 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx,
        case RX_DROP_MONITOR:
                I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop);
                if (rx->sta)
-                       rx->sta->rx_dropped++;
+                       rx->sta->rx_stats.dropped++;
                /* fall through */
        case RX_CONTINUE: {
                struct ieee80211_rate *rate = NULL;
@@ -3118,7 +3154,7 @@ static void ieee80211_rx_handlers_result(struct ieee80211_rx_data *rx,
        case RX_DROP_UNUSABLE:
                I802_DEBUG_INC(rx->sdata->local->rx_handlers_drop);
                if (rx->sta)
-                       rx->sta->rx_dropped++;
+                       rx->sta->rx_stats.dropped++;
                dev_kfree_skb(rx->skb);
                break;
        case RX_QUEUED:
@@ -3232,7 +3268,7 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
                /* This is OK -- must be QoS data frame */
                .security_idx = tid,
                .seqno_idx = tid,
-               .flags = IEEE80211_RX_REORDER_TIMER,
+               .napi = NULL, /* must be NULL to not have races */
        };
        struct tid_ampdu_rx *tid_agg_rx;
 
@@ -3246,16 +3282,25 @@ void ieee80211_release_reorder_timeout(struct sta_info *sta, int tid)
        ieee80211_sta_reorder_release(sta->sdata, tid_agg_rx, &frames);
        spin_unlock(&tid_agg_rx->reorder_lock);
 
+       if (!skb_queue_empty(&frames)) {
+               struct ieee80211_event event = {
+                       .type = BA_FRAME_TIMEOUT,
+                       .u.ba.tid = tid,
+                       .u.ba.sta = &sta->sta,
+               };
+               drv_event_callback(rx.local, rx.sdata, &event);
+       }
+
        ieee80211_rx_handlers(&rx, &frames);
 }
 
 /* main receive path */
 
-static bool prepare_for_handlers(struct ieee80211_rx_data *rx,
-                                struct ieee80211_hdr *hdr)
+static bool ieee80211_accept_frame(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_sub_if_data *sdata = rx->sdata;
        struct sk_buff *skb = rx->skb;
+       struct ieee80211_hdr *hdr = (void *)skb->data;
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
        u8 *bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
        int multicast = is_multicast_ether_addr(hdr->addr1);
@@ -3264,30 +3309,23 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx,
        case NL80211_IFTYPE_STATION:
                if (!bssid && !sdata->u.mgd.use_4addr)
                        return false;
-               if (!multicast &&
-                   !ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
-                       if (!(sdata->dev->flags & IFF_PROMISC) ||
-                           sdata->u.mgd.use_4addr)
-                               return false;
-                       status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
-               }
-               break;
+               if (multicast)
+                       return true;
+               return ether_addr_equal(sdata->vif.addr, hdr->addr1);
        case NL80211_IFTYPE_ADHOC:
                if (!bssid)
                        return false;
                if (ether_addr_equal(sdata->vif.addr, hdr->addr2) ||
                    ether_addr_equal(sdata->u.ibss.bssid, hdr->addr2))
                        return false;
-               if (ieee80211_is_beacon(hdr->frame_control)) {
+               if (ieee80211_is_beacon(hdr->frame_control))
                        return true;
-               } else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {
+               if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid))
                        return false;
-               } else if (!multicast &&
-                          !ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
-                       if (!(sdata->dev->flags & IFF_PROMISC))
-                               return false;
-                       status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
-               } else if (!rx->sta) {
+               if (!multicast &&
+                   !ether_addr_equal(sdata->vif.addr, hdr->addr1))
+                       return false;
+               if (!rx->sta) {
                        int rate_idx;
                        if (status->flag & (RX_FLAG_HT | RX_FLAG_VHT))
                                rate_idx = 0; /* TODO: HT/VHT rates */
@@ -3296,25 +3334,18 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx,
                        ieee80211_ibss_rx_no_sta(sdata, bssid, hdr->addr2,
                                                 BIT(rate_idx));
                }
-               break;
+               return true;
        case NL80211_IFTYPE_OCB:
                if (!bssid)
                        return false;
-               if (ieee80211_is_beacon(hdr->frame_control)) {
+               if (!ieee80211_is_data_present(hdr->frame_control))
                        return false;
-               } else if (!is_broadcast_ether_addr(bssid)) {
-                       ocb_dbg(sdata, "BSSID mismatch in OCB mode!\n");
+               if (!is_broadcast_ether_addr(bssid))
                        return false;
-               } else if (!multicast &&
-                          !ether_addr_equal(sdata->dev->dev_addr,
-                                            hdr->addr1)) {
-                       /* if we are in promisc mode we also accept
-                        * packets not destined for us
-                        */
-                       if (!(sdata->dev->flags & IFF_PROMISC))
-                               return false;
-                       rx->flags &= ~IEEE80211_RX_RA_MATCH;
-               } else if (!rx->sta) {
+               if (!multicast &&
+                   !ether_addr_equal(sdata->dev->dev_addr, hdr->addr1))
+                       return false;
+               if (!rx->sta) {
                        int rate_idx;
                        if (status->flag & RX_FLAG_HT)
                                rate_idx = 0; /* TODO: HT rates */
@@ -3323,22 +3354,17 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx,
                        ieee80211_ocb_rx_no_sta(sdata, bssid, hdr->addr2,
                                                BIT(rate_idx));
                }
-               break;
+               return true;
        case NL80211_IFTYPE_MESH_POINT:
-               if (!multicast &&
-                   !ether_addr_equal(sdata->vif.addr, hdr->addr1)) {
-                       if (!(sdata->dev->flags & IFF_PROMISC))
-                               return false;
-
-                       status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
-               }
-               break;
+               if (multicast)
+                       return true;
+               return ether_addr_equal(sdata->vif.addr, hdr->addr1);
        case NL80211_IFTYPE_AP_VLAN:
        case NL80211_IFTYPE_AP:
-               if (!bssid) {
-                       if (!ether_addr_equal(sdata->vif.addr, hdr->addr1))
-                               return false;
-               } else if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) {
+               if (!bssid)
+                       return ether_addr_equal(sdata->vif.addr, hdr->addr1);
+
+               if (!ieee80211_bssid_match(bssid, sdata->vif.addr)) {
                        /*
                         * Accept public action frames even when the
                         * BSSID doesn't match, this is used for P2P
@@ -3350,42 +3376,35 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx,
                                return false;
                        if (ieee80211_is_public_action(hdr, skb->len))
                                return true;
-                       if (!ieee80211_is_beacon(hdr->frame_control))
-                               return false;
-                       status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
-               } else if (!ieee80211_has_tods(hdr->frame_control)) {
+                       return ieee80211_is_beacon(hdr->frame_control);
+               }
+
+               if (!ieee80211_has_tods(hdr->frame_control)) {
                        /* ignore data frames to TDLS-peers */
                        if (ieee80211_is_data(hdr->frame_control))
                                return false;
                        /* ignore action frames to TDLS-peers */
                        if (ieee80211_is_action(hdr->frame_control) &&
+                           !is_broadcast_ether_addr(bssid) &&
                            !ether_addr_equal(bssid, hdr->addr1))
                                return false;
                }
-               break;
+               return true;
        case NL80211_IFTYPE_WDS:
                if (bssid || !ieee80211_is_data(hdr->frame_control))
                        return false;
-               if (!ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2))
-                       return false;
-               break;
+               return ether_addr_equal(sdata->u.wds.remote_addr, hdr->addr2);
        case NL80211_IFTYPE_P2P_DEVICE:
-               if (!ieee80211_is_public_action(hdr, skb->len) &&
-                   !ieee80211_is_probe_req(hdr->frame_control) &&
-                   !ieee80211_is_probe_resp(hdr->frame_control) &&
-                   !ieee80211_is_beacon(hdr->frame_control))
-                       return false;
-               if (!ether_addr_equal(sdata->vif.addr, hdr->addr1) &&
-                   !multicast)
-                       status->rx_flags &= ~IEEE80211_RX_RA_MATCH;
-               break;
+               return ieee80211_is_public_action(hdr, skb->len) ||
+                      ieee80211_is_probe_req(hdr->frame_control) ||
+                      ieee80211_is_probe_resp(hdr->frame_control) ||
+                      ieee80211_is_beacon(hdr->frame_control);
        default:
-               /* should never get here */
-               WARN_ON_ONCE(1);
                break;
        }
 
-       return true;
+       WARN_ON_ONCE(1);
+       return false;
 }
 
 /*
@@ -3399,13 +3418,10 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
 {
        struct ieee80211_local *local = rx->local;
        struct ieee80211_sub_if_data *sdata = rx->sdata;
-       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-       struct ieee80211_hdr *hdr = (void *)skb->data;
 
        rx->skb = skb;
-       status->rx_flags |= IEEE80211_RX_RA_MATCH;
 
-       if (!prepare_for_handlers(rx, hdr))
+       if (!ieee80211_accept_frame(rx))
                return false;
 
        if (!consume) {
@@ -3430,7 +3446,8 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
  * be called with rcu_read_lock protection.
  */
 static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
-                                        struct sk_buff *skb)
+                                        struct sk_buff *skb,
+                                        struct napi_struct *napi)
 {
        struct ieee80211_local *local = hw_to_local(hw);
        struct ieee80211_sub_if_data *sdata;
@@ -3446,9 +3463,10 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        memset(&rx, 0, sizeof(rx));
        rx.skb = skb;
        rx.local = local;
+       rx.napi = napi;
 
        if (ieee80211_is_data(fc) || ieee80211_is_mgmt(fc))
-               local->dot11ReceivedFragmentCount++;
+               I802_DEBUG_INC(local->dot11ReceivedFragmentCount);
 
        if (ieee80211_is_mgmt(fc)) {
                /* drop frame if too short for header */
@@ -3547,7 +3565,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
  * This is the receive path handler. It is called by a low level driver when an
  * 802.11 MPDU is received from the hardware.
  */
-void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
+void ieee80211_rx_napi(struct ieee80211_hw *hw, struct sk_buff *skb,
+                      struct napi_struct *napi)
 {
        struct ieee80211_local *local = hw_to_local(hw);
        struct ieee80211_rate *rate = NULL;
@@ -3646,7 +3665,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
        ieee80211_tpt_led_trig_rx(local,
                        ((struct ieee80211_hdr *)skb->data)->frame_control,
                        skb->len);
-       __ieee80211_rx_handle_packet(hw, skb);
+       __ieee80211_rx_handle_packet(hw, skb, napi);
 
        rcu_read_unlock();
 
@@ -3654,7 +3673,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
  drop:
        kfree_skb(skb);
 }
-EXPORT_SYMBOL(ieee80211_rx);
+EXPORT_SYMBOL(ieee80211_rx_napi);
 
 /* This is a version of the rx handler that can be called from hard irq
  * context. Post the skb on the queue and schedule the tasklet */