]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - net/mac80211/rx.c
fat: i_blocks warning fix
[linux-2.6-omap-h63xx.git] / net / mac80211 / rx.c
index 6db854505193ec178d60a657fa14534e8e5b25f5..cf6b121e1bbf58407608132c24b613c2cbd34129 100644 (file)
@@ -143,6 +143,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        /* IEEE80211_RADIOTAP_FLAGS */
        if (local->hw.flags & IEEE80211_HW_RX_INCLUDES_FCS)
                *pos |= IEEE80211_RADIOTAP_F_FCS;
+       if (status->flag & RX_FLAG_SHORTPRE)
+               *pos |= IEEE80211_RADIOTAP_F_SHORTPRE;
        pos++;
 
        /* IEEE80211_RADIOTAP_RATE */
@@ -155,8 +157,11 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        if (status->band == IEEE80211_BAND_5GHZ)
                *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM |
                                             IEEE80211_CHAN_5GHZ);
+       else if (rate->flags & IEEE80211_RATE_ERP_G)
+               *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_OFDM |
+                                            IEEE80211_CHAN_2GHZ);
        else
-               *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_DYN |
+               *(__le16 *)pos = cpu_to_le16(IEEE80211_CHAN_CCK |
                                             IEEE80211_CHAN_2GHZ);
        pos += 2;
 
@@ -290,7 +295,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
                if (!netif_running(sdata->dev))
                        continue;
 
-               if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR)
+               if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
                        continue;
 
                if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)
@@ -398,12 +403,12 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
        struct ieee80211_local *local = rx->local;
        struct sk_buff *skb = rx->skb;
 
-       if (unlikely(local->sta_hw_scanning))
-               return ieee80211_sta_rx_scan(rx->dev, skb, rx->status);
+       if (unlikely(local->hw_scanning))
+               return ieee80211_scan_rx(rx->sdata, skb, rx->status);
 
-       if (unlikely(local->sta_sw_scanning)) {
+       if (unlikely(local->sw_scanning)) {
                /* drop all the other packets during a software scan anyway */
-               if (ieee80211_sta_rx_scan(rx->dev, skb, rx->status)
+               if (ieee80211_scan_rx(rx->sdata, skb, rx->status)
                    != RX_QUEUED)
                        dev_kfree_skb(skb);
                return RX_QUEUED;
@@ -461,7 +466,7 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
 
        if (ieee80211_is_data(hdr->frame_control) &&
            is_multicast_ether_addr(hdr->addr1) &&
-           mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->dev))
+           mesh_rmc_check(hdr->addr4, msh_h_get(hdr, hdrlen), rx->sdata))
                return RX_DROP_MONITOR;
 #undef msh_h_get
 
@@ -496,8 +501,8 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
        /* Drop disallowed frame classes based on STA auth/assoc state;
         * IEEE 802.11, Chap 5.5.
         *
-        * 80211.o does filtering only based on association state, i.e., it
-        * drops Class 3 frames from not associated stations. hostapd sends
+        * mac80211 filters only based on association state, i.e. it drops
+        * Class 3 frames from not associated stations. hostapd sends
         * deauth/disassoc frames when needed. In addition, hostapd is
         * responsible for filtering on both auth and assoc states.
         */
@@ -507,7 +512,7 @@ ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
 
        if (unlikely((ieee80211_is_data(hdr->frame_control) ||
                      ieee80211_is_pspoll(hdr->frame_control)) &&
-                    rx->sdata->vif.type != IEEE80211_IF_TYPE_IBSS &&
+                    rx->sdata->vif.type != NL80211_IFTYPE_ADHOC &&
                     (!rx->sta || !test_sta_flags(rx->sta, WLAN_STA_ASSOC)))) {
                if ((!ieee80211_has_fromds(hdr->frame_control) &&
                     !ieee80211_has_tods(hdr->frame_control) &&
@@ -645,32 +650,28 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
        return result;
 }
 
-static void ap_sta_ps_start(struct net_device *dev, struct sta_info *sta)
+static void ap_sta_ps_start(struct sta_info *sta)
 {
-       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_sub_if_data *sdata = sta->sdata;
        DECLARE_MAC_BUF(mac);
 
-       sdata = sta->sdata;
-
        atomic_inc(&sdata->bss->num_sta_ps);
        set_and_clear_sta_flags(sta, WLAN_STA_PS, WLAN_STA_PSPOLL);
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
        printk(KERN_DEBUG "%s: STA %s aid %d enters power save mode\n",
-              dev->name, print_mac(mac, sta->addr), sta->aid);
+              sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid);
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 }
 
-static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
+static int ap_sta_ps_end(struct sta_info *sta)
 {
-       struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
+       struct ieee80211_sub_if_data *sdata = sta->sdata;
+       struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb;
        int sent = 0;
-       struct ieee80211_sub_if_data *sdata;
        struct ieee80211_tx_info *info;
        DECLARE_MAC_BUF(mac);
 
-       sdata = sta->sdata;
-
        atomic_dec(&sdata->bss->num_sta_ps);
 
        clear_sta_flags(sta, WLAN_STA_PS | WLAN_STA_PSPOLL);
@@ -680,7 +681,7 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
 
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
        printk(KERN_DEBUG "%s: STA %s aid %d exits power save mode\n",
-              dev->name, print_mac(mac, sta->addr), sta->aid);
+              sdata->dev->name, print_mac(mac, sta->sta.addr), sta->sta.aid);
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 
        /* Send all buffered frames to the station */
@@ -696,8 +697,8 @@ static int ap_sta_ps_end(struct net_device *dev, struct sta_info *sta)
                sent++;
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
                printk(KERN_DEBUG "%s: STA %s aid %d send PS frame "
-                      "since STA not sleeping anymore\n", dev->name,
-                      print_mac(mac, sta->addr), sta->aid);
+                      "since STA not sleeping anymore\n", sdata->dev->name,
+                      print_mac(mac, sta->sta.addr), sta->sta.aid);
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
                info->flags |= IEEE80211_TX_CTL_REQUEUE;
                dev_queue_xmit(skb);
@@ -710,7 +711,6 @@ static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
 {
        struct sta_info *sta = rx->sta;
-       struct net_device *dev = rx->dev;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
 
        if (!sta)
@@ -719,14 +719,14 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
        /* Update last_rx only for IBSS packets which are for the current
         * BSSID to avoid keeping the current IBSS network alive in cases where
         * other STAs are using different BSSID. */
-       if (rx->sdata->vif.type == IEEE80211_IF_TYPE_IBSS) {
+       if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
                u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
-                                               IEEE80211_IF_TYPE_IBSS);
+                                               NL80211_IFTYPE_ADHOC);
                if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)
                        sta->last_rx = jiffies;
        } else
        if (!is_multicast_ether_addr(hdr->addr1) ||
-           rx->sdata->vif.type == IEEE80211_IF_TYPE_STA) {
+           rx->sdata->vif.type == NL80211_IFTYPE_STATION) {
                /* Update last_rx only for unicast frames in order to prevent
                 * the Probe Request frames (the only broadcast frames from a
                 * STA in infrastructure mode) from keeping a connection alive.
@@ -746,16 +746,16 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
        sta->last_noise = rx->status->noise;
 
        if (!ieee80211_has_morefrags(hdr->frame_control) &&
-           (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP ||
-            rx->sdata->vif.type == IEEE80211_IF_TYPE_VLAN)) {
+           (rx->sdata->vif.type == NL80211_IFTYPE_AP ||
+            rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN)) {
                /* Change STA power saving mode only in the end of a frame
                 * exchange sequence */
                if (test_sta_flags(sta, WLAN_STA_PS) &&
                    !ieee80211_has_pm(hdr->frame_control))
-                       rx->sent_ps_buffered += ap_sta_ps_end(dev, sta);
+                       rx->sent_ps_buffered += ap_sta_ps_end(sta);
                else if (!test_sta_flags(sta, WLAN_STA_PS) &&
                         ieee80211_has_pm(hdr->frame_control))
-                       ap_sta_ps_start(dev, sta);
+                       ap_sta_ps_start(sta);
        }
 
        /* Drop data::nullfunc frames silently, since they are used only to
@@ -816,7 +816,7 @@ ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
 
 static inline struct ieee80211_fragment_entry *
 ieee80211_reassemble_find(struct ieee80211_sub_if_data *sdata,
-                         u16 fc, unsigned int frag, unsigned int seq,
+                         unsigned int frag, unsigned int seq,
                          int rx_queue, struct ieee80211_hdr *hdr)
 {
        struct ieee80211_fragment_entry *entry;
@@ -825,7 +825,6 @@ 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;
-               u16 f_fc;
 
                idx--;
                if (idx < 0)
@@ -837,10 +836,13 @@ 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_fc = le16_to_cpu(f_hdr->frame_control);
+               f_hdr = (struct ieee80211_hdr *)entry->skb_list.next->data;
 
-               if ((fc & IEEE80211_FCTL_FTYPE) != (f_fc & IEEE80211_FCTL_FTYPE) ||
+               /*
+                * Check ftype and addresses are equal, else check next fragment
+                */
+               if (((hdr->frame_control ^ f_hdr->frame_control) &
+                    cpu_to_le16(IEEE80211_FCTL_FTYPE)) ||
                    compare_ether_addr(hdr->addr1, f_hdr->addr1) != 0 ||
                    compare_ether_addr(hdr->addr2, f_hdr->addr2) != 0)
                        continue;
@@ -860,16 +862,18 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_hdr *hdr;
        u16 sc;
+       __le16 fc;
        unsigned int frag, seq;
        struct ieee80211_fragment_entry *entry;
        struct sk_buff *skb;
        DECLARE_MAC_BUF(mac);
 
-       hdr = (struct ieee80211_hdr *) rx->skb->data;
+       hdr = (struct ieee80211_hdr *)rx->skb->data;
+       fc = hdr->frame_control;
        sc = le16_to_cpu(hdr->seq_ctrl);
        frag = sc & IEEE80211_SCTL_FRAG;
 
-       if (likely((!(rx->fc & IEEE80211_FCTL_MOREFRAGS) && frag == 0) ||
+       if (likely((!ieee80211_has_morefrags(fc) && frag == 0) ||
                   (rx->skb)->len < 24 ||
                   is_multicast_ether_addr(hdr->addr1))) {
                /* not fragmented */
@@ -884,7 +888,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
                entry = ieee80211_reassemble_add(rx->sdata, frag, seq,
                                                 rx->queue, &(rx->skb));
                if (rx->key && rx->key->conf.alg == ALG_CCMP &&
-                   (rx->fc & IEEE80211_FCTL_PROTECTED)) {
+                   ieee80211_has_protected(fc)) {
                        /* Store CCMP PN so that we can verify that the next
                         * fragment has a sequential PN value. */
                        entry->ccmp = 1;
@@ -898,8 +902,7 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
        /* This is a fragment for a frame that should already be pending in
         * fragment cache. Add this fragment to the end of the pending entry.
         */
-       entry = ieee80211_reassemble_find(rx->sdata, rx->fc, frag, seq,
-                                         rx->queue, hdr);
+       entry = ieee80211_reassemble_find(rx->sdata, frag, seq, rx->queue, hdr);
        if (!entry) {
                I802_DEBUG_INC(rx->local->rx_handlers_drop_defrag);
                return RX_DROP_MONITOR;
@@ -924,11 +927,11 @@ ieee80211_rx_h_defragment(struct ieee80211_rx_data *rx)
                memcpy(entry->last_pn, pn, CCMP_PN_LEN);
        }
 
-       skb_pull(rx->skb, ieee80211_get_hdrlen(rx->fc));
+       skb_pull(rx->skb, ieee80211_hdrlen(fc));
        __skb_queue_tail(&entry->skb_list, rx->skb);
        entry->last_frag = frag;
        entry->extra_len += rx->skb->len;
-       if (rx->fc & IEEE80211_FCTL_MOREFRAGS) {
+       if (ieee80211_has_morefrags(fc)) {
                rx->skb = NULL;
                return RX_QUEUED;
        }
@@ -968,15 +971,14 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
        struct sk_buff *skb;
        int no_pending_pkts;
        DECLARE_MAC_BUF(mac);
+       __le16 fc = ((struct ieee80211_hdr *)rx->skb->data)->frame_control;
 
-       if (likely(!rx->sta ||
-                  (rx->fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_CTL ||
-                  (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_PSPOLL ||
+       if (likely(!rx->sta || !ieee80211_is_pspoll(fc) ||
                   !(rx->flags & IEEE80211_RX_RA_MATCH)))
                return RX_CONTINUE;
 
-       if ((sdata->vif.type != IEEE80211_IF_TYPE_AP) &&
-           (sdata->vif.type != IEEE80211_IF_TYPE_VLAN))
+       if ((sdata->vif.type != NL80211_IFTYPE_AP) &&
+           (sdata->vif.type != NL80211_IFTYPE_AP_VLAN))
                return RX_DROP_UNUSABLE;
 
        skb = skb_dequeue(&rx->sta->tx_filtered);
@@ -1000,7 +1002,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
 
 #ifdef CONFIG_MAC80211_VERBOSE_PS_DEBUG
                printk(KERN_DEBUG "STA %s aid %d: PS Poll (entries after %d)\n",
-                      print_mac(mac, rx->sta->addr), rx->sta->aid,
+                      print_mac(mac, rx->sta->sta.addr), rx->sta->sta.aid,
                       skb_queue_len(&rx->sta->ps_tx_buf));
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
 
@@ -1025,7 +1027,7 @@ ieee80211_rx_h_ps_poll(struct ieee80211_rx_data *rx)
                 */
                printk(KERN_DEBUG "%s: STA %s sent PS Poll even "
                       "though there are no buffered frames for it\n",
-                      rx->dev->name, print_mac(mac, rx->sta->addr));
+                      rx->dev->name, print_mac(mac, rx->sta->sta.addr));
 #endif /* CONFIG_MAC80211_VERBOSE_PS_DEBUG */
        }
 
@@ -1050,7 +1052,6 @@ ieee80211_rx_h_remove_qos_control(struct ieee80211_rx_data *rx)
                ieee80211_hdrlen(hdr->frame_control) - IEEE80211_QOS_CTL_LEN);
        hdr = (struct ieee80211_hdr *)skb_pull(rx->skb, IEEE80211_QOS_CTL_LEN);
        /* change frame type to non QOS */
-       rx->fc &= ~IEEE80211_STYPE_QOS_DATA;
        hdr->frame_control &= ~cpu_to_le16(IEEE80211_STYPE_QOS_DATA);
 
        return RX_CONTINUE;
@@ -1067,7 +1068,7 @@ ieee80211_802_1x_port_control(struct ieee80211_rx_data *rx)
 }
 
 static int
-ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx)
+ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx, __le16 fc)
 {
        /*
         * Pass through unencrypted frames if the hardware has
@@ -1077,9 +1078,8 @@ ieee80211_drop_unencrypted(struct ieee80211_rx_data *rx)
                return 0;
 
        /* Drop unencrypted frames if key is set. */
-       if (unlikely(!(rx->fc & IEEE80211_FCTL_PROTECTED) &&
-                    (rx->fc & IEEE80211_FCTL_FTYPE) == IEEE80211_FTYPE_DATA &&
-                    (rx->fc & IEEE80211_FCTL_STYPE) != IEEE80211_STYPE_NULLFUNC &&
+       if (unlikely(!ieee80211_has_protected(fc) &&
+                    !ieee80211_is_nullfunc(fc) &&
                     (rx->key || rx->sdata->drop_unencrypted)))
                return -EACCES;
 
@@ -1091,7 +1091,7 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
 {
        struct net_device *dev = rx->dev;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) rx->skb->data;
-       u16 fc, hdrlen, ethertype;
+       u16 hdrlen, ethertype;
        u8 *payload;
        u8 dst[ETH_ALEN];
        u8 src[ETH_ALEN] __aligned(2);
@@ -1102,16 +1102,10 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
        DECLARE_MAC_BUF(mac3);
        DECLARE_MAC_BUF(mac4);
 
-       fc = rx->fc;
-
-       if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
+       if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
                return -1;
 
-       hdrlen = ieee80211_get_hdrlen(fc);
-
-       if (ieee80211_vif_is_mesh(&sdata->vif))
-               hdrlen += ieee80211_get_mesh_hdrlen(
-                               (struct ieee80211s_hdr *) (skb->data + hdrlen));
+       hdrlen = ieee80211_hdrlen(hdr->frame_control);
 
        /* convert IEEE 802.11 header + possible LLC headers into Ethernet
         * header
@@ -1122,42 +1116,38 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
         *   1     0   BSSID SA    DA    n/a
         *   1     1   RA    TA    DA    SA
         */
-
-       switch (fc & (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
-       case IEEE80211_FCTL_TODS:
-               /* BSSID SA DA */
-               memcpy(dst, hdr->addr3, ETH_ALEN);
-               memcpy(src, hdr->addr2, ETH_ALEN);
-
-               if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_AP &&
-                            sdata->vif.type != IEEE80211_IF_TYPE_VLAN))
+       memcpy(dst, ieee80211_get_DA(hdr), ETH_ALEN);
+       memcpy(src, ieee80211_get_SA(hdr), ETH_ALEN);
+
+       switch (hdr->frame_control &
+               cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
+       case __constant_cpu_to_le16(IEEE80211_FCTL_TODS):
+               if (unlikely(sdata->vif.type != NL80211_IFTYPE_AP &&
+                            sdata->vif.type != NL80211_IFTYPE_AP_VLAN))
                        return -1;
                break;
-       case (IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
-               /* RA TA DA SA */
-               memcpy(dst, hdr->addr3, ETH_ALEN);
-               memcpy(src, hdr->addr4, ETH_ALEN);
-
-                if (unlikely(sdata->vif.type != IEEE80211_IF_TYPE_WDS &&
-                            sdata->vif.type != IEEE80211_IF_TYPE_MESH_POINT))
+       case __constant_cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
+               if (unlikely(sdata->vif.type != NL80211_IFTYPE_WDS &&
+                            sdata->vif.type != NL80211_IFTYPE_MESH_POINT))
                        return -1;
+               if (ieee80211_vif_is_mesh(&sdata->vif)) {
+                       struct ieee80211s_hdr *meshdr = (struct ieee80211s_hdr *)
+                               (skb->data + hdrlen);
+                       hdrlen += ieee80211_get_mesh_hdrlen(meshdr);
+                       if (meshdr->flags & MESH_FLAGS_AE_A5_A6) {
+                               memcpy(dst, meshdr->eaddr1, ETH_ALEN);
+                               memcpy(src, meshdr->eaddr2, ETH_ALEN);
+                       }
+               }
                break;
-       case IEEE80211_FCTL_FROMDS:
-               /* DA BSSID SA */
-               memcpy(dst, hdr->addr1, ETH_ALEN);
-               memcpy(src, hdr->addr3, ETH_ALEN);
-
-               if (sdata->vif.type != IEEE80211_IF_TYPE_STA ||
+       case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS):
+               if (sdata->vif.type != NL80211_IFTYPE_STATION ||
                    (is_multicast_ether_addr(dst) &&
                     !compare_ether_addr(src, dev->dev_addr)))
                        return -1;
                break;
-       case 0:
-               /* DA SA BSSID */
-               memcpy(dst, hdr->addr1, ETH_ALEN);
-               memcpy(src, hdr->addr2, ETH_ALEN);
-
-               if (sdata->vif.type != IEEE80211_IF_TYPE_IBSS)
+       case __constant_cpu_to_le16(0):
+               if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
                        return -1;
                break;
        }
@@ -1193,7 +1183,7 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
 /*
  * requires that rx->skb is a frame with ethernet header
  */
-static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx)
+static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx, __le16 fc)
 {
        static const u8 pae_group_addr[ETH_ALEN] __aligned(2)
                = { 0x01, 0x80, 0xC2, 0x00, 0x00, 0x03 };
@@ -1209,7 +1199,7 @@ static bool ieee80211_frame_allowed(struct ieee80211_rx_data *rx)
                return true;
 
        if (ieee80211_802_1x_port_control(rx) ||
-           ieee80211_drop_unencrypted(rx))
+           ieee80211_drop_unencrypted(rx, fc))
                return false;
 
        return true;
@@ -1231,8 +1221,9 @@ ieee80211_deliver_skb(struct ieee80211_rx_data *rx)
        skb = rx->skb;
        xmit_skb = NULL;
 
-       if (local->bridge_packets && (sdata->vif.type == IEEE80211_IF_TYPE_AP ||
-                                     sdata->vif.type == IEEE80211_IF_TYPE_VLAN) &&
+       if ((sdata->vif.type == NL80211_IFTYPE_AP ||
+            sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
+           !(sdata->flags & IEEE80211_SDATA_DONT_BRIDGE_PACKETS) &&
            (rx->flags & IEEE80211_RX_RA_MATCH)) {
                if (is_multicast_ether_addr(ehdr->h_dest)) {
                        /*
@@ -1279,20 +1270,21 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
 {
        struct net_device *dev = rx->dev;
        struct ieee80211_local *local = rx->local;
-       u16 fc, ethertype;
+       u16 ethertype;
        u8 *payload;
        struct sk_buff *skb = rx->skb, *frame = NULL;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       __le16 fc = hdr->frame_control;
        const struct ethhdr *eth;
        int remaining, err;
        u8 dst[ETH_ALEN];
        u8 src[ETH_ALEN];
        DECLARE_MAC_BUF(mac);
 
-       fc = rx->fc;
-       if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
+       if (unlikely(!ieee80211_is_data(fc)))
                return RX_CONTINUE;
 
-       if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
+       if (unlikely(!ieee80211_is_data_present(fc)))
                return RX_DROP_MONITOR;
 
        if (!(rx->flags & IEEE80211_RX_AMSDU))
@@ -1374,7 +1366,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
                        memcpy(skb_push(frame, ETH_ALEN), dst, ETH_ALEN);
                }
 
-               if (!ieee80211_frame_allowed(rx)) {
+               if (!ieee80211_frame_allowed(rx, fc)) {
                        if (skb == frame) /* last frame */
                                return RX_DROP_UNUSABLE;
                        dev_kfree_skb(frame);
@@ -1387,7 +1379,8 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
        return RX_QUEUED;
 }
 
-static ieee80211_rx_result debug_noinline
+#ifdef CONFIG_MAC80211_MESH
+static ieee80211_rx_result
 ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
 {
        struct ieee80211_hdr *hdr;
@@ -1406,6 +1399,25 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
                /* illegal frame */
                return RX_DROP_MONITOR;
 
+       if (mesh_hdr->flags & MESH_FLAGS_AE_A5_A6){
+               struct ieee80211_sub_if_data *sdata;
+               struct mesh_path *mppath;
+
+               sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
+               rcu_read_lock();
+               mppath = mpp_path_lookup(mesh_hdr->eaddr2, sdata);
+               if (!mppath) {
+                       mpp_path_add(mesh_hdr->eaddr2, hdr->addr4, sdata);
+               } else {
+                       spin_lock_bh(&mppath->state_lock);
+                       mppath->exp_time = jiffies;
+                       if (compare_ether_addr(mppath->mpp, hdr->addr4) != 0)
+                               memcpy(mppath->mpp, hdr->addr4, ETH_ALEN);
+                       spin_unlock_bh(&mppath->state_lock);
+               }
+               rcu_read_unlock();
+       }
+
        if (compare_ether_addr(rx->dev->dev_addr, hdr->addr3) == 0)
                return RX_CONTINUE;
 
@@ -1413,7 +1425,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
 
        if (rx->flags & IEEE80211_RX_RA_MATCH) {
                if (!mesh_hdr->ttl)
-                       IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.sta,
+                       IEEE80211_IFSTA_MESH_CTR_INC(&rx->sdata->u.mesh,
                                                     dropped_frames_ttl);
                else {
                        struct ieee80211_hdr *fwd_hdr;
@@ -1442,27 +1454,27 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        else
                return RX_DROP_MONITOR;
 }
-
+#endif
 
 static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
 {
        struct net_device *dev = rx->dev;
-       u16 fc;
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
+       __le16 fc = hdr->frame_control;
        int err;
 
-       fc = rx->fc;
-       if (unlikely((fc & IEEE80211_FCTL_FTYPE) != IEEE80211_FTYPE_DATA))
+       if (unlikely(!ieee80211_is_data(hdr->frame_control)))
                return RX_CONTINUE;
 
-       if (unlikely(!WLAN_FC_DATA_PRESENT(fc)))
+       if (unlikely(!ieee80211_is_data_present(hdr->frame_control)))
                return RX_DROP_MONITOR;
 
        err = ieee80211_data_to_8023(rx);
        if (unlikely(err))
                return RX_DROP_UNUSABLE;
 
-       if (!ieee80211_frame_allowed(rx))
+       if (!ieee80211_frame_allowed(rx, fc))
                return RX_DROP_MONITOR;
 
        rx->skb->dev = dev;
@@ -1519,23 +1531,98 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
        return RX_CONTINUE;
 }
 
+static ieee80211_rx_result debug_noinline
+ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
+{
+       struct ieee80211_local *local = rx->local;
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
+       struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
+       int len = rx->skb->len;
+
+       if (!ieee80211_is_action(mgmt->frame_control))
+               return RX_CONTINUE;
+
+       if (!rx->sta)
+               return RX_DROP_MONITOR;
+
+       if (!(rx->flags & IEEE80211_RX_RA_MATCH))
+               return RX_DROP_MONITOR;
+
+       /* all categories we currently handle have action_code */
+       if (len < IEEE80211_MIN_ACTION_SIZE + 1)
+               return RX_DROP_MONITOR;
+
+       /*
+        * FIXME: revisit this, I'm sure we should handle most
+        *        of these frames in other modes as well!
+        */
+       if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+           sdata->vif.type != NL80211_IFTYPE_ADHOC)
+               return RX_CONTINUE;
+
+       switch (mgmt->u.action.category) {
+       case WLAN_CATEGORY_BACK:
+               switch (mgmt->u.action.u.addba_req.action_code) {
+               case WLAN_ACTION_ADDBA_REQ:
+                       if (len < (IEEE80211_MIN_ACTION_SIZE +
+                                  sizeof(mgmt->u.action.u.addba_req)))
+                               return RX_DROP_MONITOR;
+                       ieee80211_process_addba_request(local, rx->sta, mgmt, len);
+                       break;
+               case WLAN_ACTION_ADDBA_RESP:
+                       if (len < (IEEE80211_MIN_ACTION_SIZE +
+                                  sizeof(mgmt->u.action.u.addba_resp)))
+                               return RX_DROP_MONITOR;
+                       ieee80211_process_addba_resp(local, rx->sta, mgmt, len);
+                       break;
+               case WLAN_ACTION_DELBA:
+                       if (len < (IEEE80211_MIN_ACTION_SIZE +
+                                  sizeof(mgmt->u.action.u.delba)))
+                               return RX_DROP_MONITOR;
+                       ieee80211_process_delba(sdata, rx->sta, mgmt, len);
+                       break;
+               }
+               break;
+       case WLAN_CATEGORY_SPECTRUM_MGMT:
+               if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ)
+                       return RX_DROP_MONITOR;
+               switch (mgmt->u.action.u.measurement.action_code) {
+               case WLAN_ACTION_SPCT_MSR_REQ:
+                       if (len < (IEEE80211_MIN_ACTION_SIZE +
+                                  sizeof(mgmt->u.action.u.measurement)))
+                               return RX_DROP_MONITOR;
+                       ieee80211_process_measurement_req(sdata, mgmt, len);
+                       break;
+               }
+               break;
+       default:
+               return RX_CONTINUE;
+       }
+
+       rx->sta->rx_packets++;
+       dev_kfree_skb(rx->skb);
+       return RX_QUEUED;
+}
+
 static ieee80211_rx_result debug_noinline
 ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
 {
-       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
 
        if (!(rx->flags & IEEE80211_RX_RA_MATCH))
                return RX_DROP_MONITOR;
 
-       sdata = IEEE80211_DEV_TO_SUB_IF(rx->dev);
-       if ((sdata->vif.type == IEEE80211_IF_TYPE_STA ||
-            sdata->vif.type == IEEE80211_IF_TYPE_IBSS ||
-            sdata->vif.type == IEEE80211_IF_TYPE_MESH_POINT) &&
-           !(sdata->flags & IEEE80211_SDATA_USERSPACE_MLME))
-               ieee80211_sta_rx_mgmt(rx->dev, rx->skb, rx->status);
-       else
+       if (ieee80211_vif_is_mesh(&sdata->vif))
+               return ieee80211_mesh_rx_mgmt(sdata, rx->skb, rx->status);
+
+       if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+           sdata->vif.type != NL80211_IFTYPE_ADHOC)
                return RX_DROP_MONITOR;
 
+       if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)
+               return RX_DROP_MONITOR;
+
+       ieee80211_sta_rx_mgmt(sdata, rx->skb, rx->status);
        return RX_QUEUED;
 }
 
@@ -1565,7 +1652,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
        if (!ieee80211_has_protected(hdr->frame_control))
                goto ignore;
 
-       if (rx->sdata->vif.type == IEEE80211_IF_TYPE_AP && keyidx) {
+       if (rx->sdata->vif.type == NL80211_IFTYPE_AP && keyidx) {
                /*
                 * APs with pairwise keys should never receive Michael MIC
                 * errors for non-zero keyidx because these are reserved for
@@ -1579,7 +1666,7 @@ static void ieee80211_rx_michael_mic_report(struct net_device *dev,
            !ieee80211_is_auth(hdr->frame_control))
                goto ignore;
 
-       mac80211_ev_michael_mic_failure(rx->dev, keyidx, hdr);
+       mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr);
  ignore:
        dev_kfree_skb(rx->skb);
        rx->skb = NULL;
@@ -1635,7 +1722,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx)
                if (!netif_running(sdata->dev))
                        continue;
 
-               if (sdata->vif.type != IEEE80211_IF_TYPE_MNTR ||
+               if (sdata->vif.type != NL80211_IFTYPE_MONITOR ||
                    !(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES))
                        continue;
 
@@ -1694,10 +1781,13 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
        /* must be after MMIC verify so header is counted in MPDU mic */
        CALL_RXH(ieee80211_rx_h_remove_qos_control)
        CALL_RXH(ieee80211_rx_h_amsdu)
+#ifdef CONFIG_MAC80211_MESH
        if (ieee80211_vif_is_mesh(&sdata->vif))
                CALL_RXH(ieee80211_rx_h_mesh_fwding);
+#endif
        CALL_RXH(ieee80211_rx_h_data)
        CALL_RXH(ieee80211_rx_h_ctrl)
+       CALL_RXH(ieee80211_rx_h_action)
        CALL_RXH(ieee80211_rx_h_mgmt)
 
 #undef CALL_RXH
@@ -1733,7 +1823,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
        int multicast = is_multicast_ether_addr(hdr->addr1);
 
        switch (sdata->vif.type) {
-       case IEEE80211_IF_TYPE_STA:
+       case NL80211_IFTYPE_STATION:
                if (!bssid)
                        return 0;
                if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
@@ -1748,14 +1838,10 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
                        rx->flags &= ~IEEE80211_RX_RA_MATCH;
                }
                break;
-       case IEEE80211_IF_TYPE_IBSS:
+       case NL80211_IFTYPE_ADHOC:
                if (!bssid)
                        return 0;
                if (ieee80211_is_beacon(hdr->frame_control)) {
-                       if (!rx->sta)
-                               rx->sta = ieee80211_ibss_add_sta(sdata->dev,
-                                               rx->skb, bssid, hdr->addr2,
-                                               BIT(rx->status->rate_idx));
                        return 1;
                }
                else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
@@ -1769,11 +1855,11 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
                                return 0;
                        rx->flags &= ~IEEE80211_RX_RA_MATCH;
                } else if (!rx->sta)
-                       rx->sta = ieee80211_ibss_add_sta(sdata->dev, rx->skb,
+                       rx->sta = ieee80211_ibss_add_sta(sdata, rx->skb,
                                                bssid, hdr->addr2,
                                                BIT(rx->status->rate_idx));
                break;
-       case IEEE80211_IF_TYPE_MESH_POINT:
+       case NL80211_IFTYPE_MESH_POINT:
                if (!multicast &&
                    compare_ether_addr(sdata->dev->dev_addr,
                                       hdr->addr1) != 0) {
@@ -1783,8 +1869,8 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
                        rx->flags &= ~IEEE80211_RX_RA_MATCH;
                }
                break;
-       case IEEE80211_IF_TYPE_VLAN:
-       case IEEE80211_IF_TYPE_AP:
+       case NL80211_IFTYPE_AP_VLAN:
+       case NL80211_IFTYPE_AP:
                if (!bssid) {
                        if (compare_ether_addr(sdata->dev->dev_addr,
                                               hdr->addr1))
@@ -1796,16 +1882,17 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
                        rx->flags &= ~IEEE80211_RX_RA_MATCH;
                }
                break;
-       case IEEE80211_IF_TYPE_WDS:
+       case NL80211_IFTYPE_WDS:
                if (bssid || !ieee80211_is_data(hdr->frame_control))
                        return 0;
                if (compare_ether_addr(sdata->u.wds.remote_addr, hdr->addr2))
                        return 0;
                break;
-       case IEEE80211_IF_TYPE_MNTR:
+       case NL80211_IFTYPE_MONITOR:
                /* take everything */
                break;
-       case IEEE80211_IF_TYPE_INVALID:
+       case NL80211_IFTYPE_UNSPECIFIED:
+       case __NL80211_IFTYPE_AFTER_LAST:
                /* should never get here */
                WARN_ON(1);
                break;
@@ -1827,23 +1914,20 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        struct ieee80211_sub_if_data *sdata;
        struct ieee80211_hdr *hdr;
        struct ieee80211_rx_data rx;
-       u16 type;
        int prepares;
        struct ieee80211_sub_if_data *prev = NULL;
        struct sk_buff *skb_new;
        u8 *bssid;
 
-       hdr = (struct ieee80211_hdr *) skb->data;
+       hdr = (struct ieee80211_hdr *)skb->data;
        memset(&rx, 0, sizeof(rx));
        rx.skb = skb;
        rx.local = local;
 
        rx.status = status;
        rx.rate = rate;
-       rx.fc = le16_to_cpu(hdr->frame_control);
-       type = rx.fc & IEEE80211_FCTL_FTYPE;
 
-       if (type == IEEE80211_FTYPE_DATA || type == IEEE80211_FTYPE_MGMT)
+       if (ieee80211_is_data(hdr->frame_control) || ieee80211_is_mgmt(hdr->frame_control))
                local->dot11ReceivedFragmentCount++;
 
        rx.sta = sta_info_get(local, hdr->addr2);
@@ -1857,7 +1941,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                return;
        }
 
-       if (unlikely(local->sta_sw_scanning || local->sta_hw_scanning))
+       if (unlikely(local->sw_scanning || local->hw_scanning))
                rx.flags |= IEEE80211_RX_IN_SCAN;
 
        ieee80211_parse_qos(&rx);
@@ -1869,7 +1953,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                if (!netif_running(sdata->dev))
                        continue;
 
-               if (sdata->vif.type == IEEE80211_IF_TYPE_MNTR)
+               if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
                        continue;
 
                bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
@@ -1904,14 +1988,12 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                                       prev->dev->name);
                        continue;
                }
-               rx.fc = le16_to_cpu(hdr->frame_control);
                ieee80211_invoke_rx_handlers(prev, &rx, skb_new);
                prev = sdata;
        }
-       if (prev) {
-               rx.fc = le16_to_cpu(hdr->frame_control);
+       if (prev)
                ieee80211_invoke_rx_handlers(prev, &rx, skb);
-       else
+       else
                dev_kfree_skb(skb);
 }
 
@@ -2080,7 +2162,7 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
        /* if this mpdu is fragmented - terminate rx aggregation session */
        sc = le16_to_cpu(hdr->seq_ctrl);
        if (sc & IEEE80211_SCTL_FRAG) {
-               ieee80211_sta_stop_rx_ba_session(sta->sdata->dev, sta->addr,
+               ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr,
                        tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
                ret = 1;
                goto end_reorder;