Merge tag 'for_linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost
[linux-2.6-block.git] / net / mac80211 / rx.c
index 260eed45b6d2ff105052643169465c04d333c182..5dae166cb7f56b7cb9d9097496db9e8fa8d755ce 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);
+}
+
 /*
  * monitor mode reception
  *
@@ -42,7 +52,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 {
@@ -100,7 +110,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 +185,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 +239,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 +289,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 |=
@@ -448,7 +458,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 +539,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 +990,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 +1024,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 */
@@ -1073,10 +1077,8 @@ ieee80211_rx_h_check_dup(struct ieee80211_rx_data *rx)
                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++;
-                       }
+                       I802_DEBUG_INC(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;
@@ -1195,11 +1197,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;
 
@@ -1241,7 +1245,7 @@ int ieee80211_sta_ps_transition(struct ieee80211_sta *sta, bool start)
        struct sta_info *sta_inf = container_of(sta, 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_inf->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);
@@ -1265,7 +1269,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 +1281,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;
 
        /*
@@ -1367,11 +1371,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
                        }
                }
        } 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->last_rx = jiffies;
        } else if (!is_multicast_ether_addr(hdr->addr1)) {
                /*
                 * Mesh beacons will update last_rx when if they are found to
@@ -1386,9 +1386,6 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
                }
        }
 
-       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);
 
@@ -1416,7 +1413,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 ||
@@ -1517,13 +1514,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;
@@ -1795,7 +1785,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;
        }
 
@@ -1878,7 +1868,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);
@@ -2054,18 +2044,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,7 +2108,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->local->napi)
+               if (!(rx->flags & IEEE80211_RX_REORDER_TIMER) &&
+                   rx->local->napi)
                        napi_gro_receive(rx->local->napi, skb);
                else
                        netif_receive_skb(skb);
@@ -2206,7 +2194,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;
 
@@ -2237,8 +2224,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)
@@ -2329,11 +2315,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
 
@@ -2444,6 +2428,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;
@@ -2459,6 +2446,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)
@@ -2471,6 +2461,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;
        }
@@ -2551,7 +2543,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,
@@ -2560,9 +2552,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;
 
@@ -2590,9 +2579,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 */
@@ -2888,7 +2874,7 @@ 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,
@@ -2953,7 +2939,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;
                }
@@ -3076,8 +3062,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) {
@@ -3231,7 +3216,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 = 0,
+               .flags = IEEE80211_RX_REORDER_TIMER,
        };
        struct tid_ampdu_rx *tid_agg_rx;
 
@@ -3245,16 +3230,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);
@@ -3263,30 +3257,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 */
@@ -3295,25 +3282,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_beacon(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 */
@@ -3322,22 +3302,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
@@ -3349,10 +3324,10 @@ 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;
@@ -3361,30 +3336,22 @@ static bool prepare_for_handlers(struct ieee80211_rx_data *rx,
                            !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;
 }
 
 /*
@@ -3398,13 +3365,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) {
@@ -3447,7 +3411,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        rx.local = local;
 
        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 */