mac80211: remove mixed-cell and userspace MLME code
[cascardo/linux.git] / net / mac80211 / rx.c
index 57ce697..47d395a 100644 (file)
@@ -86,8 +86,7 @@ ieee80211_rx_radiotap_len(struct ieee80211_local *local,
 
        if (status->flag & RX_FLAG_TSFT)
                len += 8;
-       if (local->hw.flags & IEEE80211_HW_SIGNAL_DB ||
-           local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
+       if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
                len += 1;
        if (local->hw.flags & IEEE80211_HW_NOISE_DBM)
                len += 1;
@@ -143,6 +142,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_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
+               *pos |= IEEE80211_RADIOTAP_F_BADFCS;
        if (status->flag & RX_FLAG_SHORTPRE)
                *pos |= IEEE80211_RADIOTAP_F_SHORTPRE;
        pos++;
@@ -158,7 +159,7 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
                 */
                *pos = 0;
        } else {
-               rthdr->it_present |= (1 << IEEE80211_RADIOTAP_RATE);
+               rthdr->it_present |= cpu_to_le32(1 << IEEE80211_RADIOTAP_RATE);
                *pos = rate->bitrate / 5;
        }
        pos++;
@@ -199,23 +200,14 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        *pos = status->antenna;
        pos++;
 
-       /* IEEE80211_RADIOTAP_DB_ANTSIGNAL */
-       if (local->hw.flags & IEEE80211_HW_SIGNAL_DB) {
-               *pos = status->signal;
-               rthdr->it_present |=
-                       cpu_to_le32(1 << IEEE80211_RADIOTAP_DB_ANTSIGNAL);
-               pos++;
-       }
-
        /* IEEE80211_RADIOTAP_DB_ANTNOISE is not used */
 
        /* IEEE80211_RADIOTAP_RX_FLAGS */
        /* ensure 2 byte alignment for the 2 byte field as required */
        if ((pos - (unsigned char *)rthdr) & 1)
                pos++;
-       /* FIXME: when radiotap gets a 'bad PLCP' flag use it here */
-       if (status->flag & (RX_FLAG_FAILED_FCS_CRC | RX_FLAG_FAILED_PLCP_CRC))
-               *(__le16 *)pos |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADFCS);
+       if (status->flag & RX_FLAG_FAILED_PLCP_CRC)
+               *(__le16 *)pos |= cpu_to_le16(IEEE80211_RADIOTAP_F_RX_BADPLCP);
        pos += 2;
 }
 
@@ -740,6 +732,39 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
        return result;
 }
 
+static ieee80211_rx_result debug_noinline
+ieee80211_rx_h_check_more_data(struct ieee80211_rx_data *rx)
+{
+       struct ieee80211_local *local;
+       struct ieee80211_hdr *hdr;
+       struct sk_buff *skb;
+
+       local = rx->local;
+       skb = rx->skb;
+       hdr = (struct ieee80211_hdr *) skb->data;
+
+       if (!local->pspolling)
+               return RX_CONTINUE;
+
+       if (!ieee80211_has_fromds(hdr->frame_control))
+               /* this is not from AP */
+               return RX_CONTINUE;
+
+       if (!ieee80211_is_data(hdr->frame_control))
+               return RX_CONTINUE;
+
+       if (!ieee80211_has_moredata(hdr->frame_control)) {
+               /* AP has no more frames buffered for us */
+               local->pspolling = false;
+               return RX_CONTINUE;
+       }
+
+       /* more data bit is set, let's request a new frame from the AP */
+       ieee80211_send_pspoll(local, rx->sdata);
+
+       return RX_CONTINUE;
+}
+
 static void ap_sta_ps_start(struct sta_info *sta)
 {
        struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -814,7 +839,7 @@ ieee80211_rx_h_sta_process(struct ieee80211_rx_data *rx)
        if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
                u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
                                                NL80211_IFTYPE_ADHOC);
-               if (compare_ether_addr(bssid, rx->sdata->u.sta.bssid) == 0)
+               if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0)
                        sta->last_rx = jiffies;
        } else
        if (!is_multicast_ether_addr(hdr->addr1) ||
@@ -1225,12 +1250,12 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
 
        switch (hdr->frame_control &
                cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS)) {
-       case __constant_cpu_to_le16(IEEE80211_FCTL_TODS):
+       case 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 __constant_cpu_to_le16(IEEE80211_FCTL_TODS | IEEE80211_FCTL_FROMDS):
+       case 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;
@@ -1244,13 +1269,13 @@ ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
                        }
                }
                break;
-       case __constant_cpu_to_le16(IEEE80211_FCTL_FROMDS):
+       case 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 __constant_cpu_to_le16(0):
+       case cpu_to_le16(0):
                if (sdata->vif.type != NL80211_IFTYPE_ADHOC)
                        return -1;
                break;
@@ -1649,11 +1674,9 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
                start_seq_num = le16_to_cpu(bar->start_seq_num) >> 4;
 
                /* reset session timer */
-               if (tid_agg_rx->timeout) {
-                       unsigned long expires =
-                               jiffies + (tid_agg_rx->timeout / 1000) * HZ;
-                       mod_timer(&tid_agg_rx->session_timer, expires);
-               }
+               if (tid_agg_rx->timeout)
+                       mod_timer(&tid_agg_rx->session_timer,
+                                 TU_TO_EXP_TIME(tid_agg_rx->timeout));
 
                /* manage reordering buffer according to requested */
                /* sequence number */
@@ -1667,9 +1690,9 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
        return RX_CONTINUE;
 }
 
-void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
-                                   struct ieee80211_mgmt *mgmt,
-                                   size_t len)
+static void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
+                                          struct ieee80211_mgmt *mgmt,
+                                          size_t len)
 {
        struct ieee80211_local *local = sdata->local;
        struct sk_buff *skb;
@@ -1680,13 +1703,13 @@ void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
                return;
        }
 
-       if (compare_ether_addr(mgmt->sa, sdata->u.sta.bssid) != 0 ||
-           compare_ether_addr(mgmt->bssid, sdata->u.sta.bssid) != 0) {
+       if (compare_ether_addr(mgmt->sa, sdata->u.mgd.bssid) != 0 ||
+           compare_ether_addr(mgmt->bssid, sdata->u.mgd.bssid) != 0) {
                /* Not from the current AP. */
                return;
        }
 
-       if (sdata->u.sta.state == IEEE80211_STA_MLME_ASSOCIATE) {
+       if (sdata->u.mgd.state == IEEE80211_STA_MLME_ASSOCIATE) {
                /* Association in progress; ignore SA Query */
                return;
        }
@@ -1705,7 +1728,7 @@ void ieee80211_process_sa_query_req(struct ieee80211_sub_if_data *sdata,
        memset(resp, 0, 24);
        memcpy(resp->da, mgmt->sa, ETH_ALEN);
        memcpy(resp->sa, sdata->dev->dev_addr, ETH_ALEN);
-       memcpy(resp->bssid, sdata->u.sta.bssid, ETH_ALEN);
+       memcpy(resp->bssid, sdata->u.mgd.bssid, ETH_ALEN);
        resp->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
                                          IEEE80211_STYPE_ACTION);
        skb_put(skb, 1 + sizeof(resp->u.action.u.sa_query));
@@ -1723,7 +1746,6 @@ 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_if_sta *ifsta = &sdata->u.sta;
        struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *) rx->skb->data;
        struct ieee80211_bss *bss;
        int len = rx->skb->len;
@@ -1746,6 +1768,17 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
 
        switch (mgmt->u.action.category) {
        case WLAN_CATEGORY_BACK:
+               /*
+                * The aggregation code is not prepared to handle
+                * anything but STA/AP due to the BSSID handling;
+                * IBSS could work in the code but isn't supported
+                * by drivers or the standard.
+                */
+               if (sdata->vif.type != NL80211_IFTYPE_STATION &&
+                   sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
+                   sdata->vif.type != NL80211_IFTYPE_AP)
+                       return RX_DROP_MONITOR;
+
                switch (mgmt->u.action.u.addba_req.action_code) {
                case WLAN_ACTION_ADDBA_REQ:
                        if (len < (IEEE80211_MIN_ACTION_SIZE +
@@ -1770,6 +1803,10 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
        case WLAN_CATEGORY_SPECTRUM_MGMT:
                if (local->hw.conf.channel->band != IEEE80211_BAND_5GHZ)
                        return RX_DROP_MONITOR;
+
+               if (sdata->vif.type != NL80211_IFTYPE_STATION)
+                       return RX_DROP_MONITOR;
+
                switch (mgmt->u.action.u.measurement.action_code) {
                case WLAN_ACTION_SPCT_MSR_REQ:
                        if (len < (IEEE80211_MIN_ACTION_SIZE +
@@ -1782,12 +1819,13 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                                   sizeof(mgmt->u.action.u.chan_switch)))
                                return RX_DROP_MONITOR;
 
-                       if (memcmp(mgmt->bssid, ifsta->bssid, ETH_ALEN) != 0)
+                       if (memcmp(mgmt->bssid, sdata->u.mgd.bssid, ETH_ALEN))
                                return RX_DROP_MONITOR;
 
-                       bss = ieee80211_rx_bss_get(local, ifsta->bssid,
+                       bss = ieee80211_rx_bss_get(local, sdata->u.mgd.bssid,
                                           local->hw.conf.channel->center_freq,
-                                          ifsta->ssid, ifsta->ssid_len);
+                                          sdata->u.mgd.ssid,
+                                          sdata->u.mgd.ssid_len);
                        if (!bss)
                                return RX_DROP_MONITOR;
 
@@ -1839,15 +1877,13 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
        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->vif.type != NL80211_IFTYPE_ADHOC)
+               return ieee80211_ibss_rx_mgmt(sdata, rx->skb, rx->status);
 
-       if (sdata->flags & IEEE80211_SDATA_USERSPACE_MLME)
-               return RX_DROP_MONITOR;
+       if (sdata->vif.type == NL80211_IFTYPE_STATION)
+               return ieee80211_sta_rx_mgmt(sdata, rx->skb, rx->status);
 
-       ieee80211_sta_rx_mgmt(sdata, rx->skb, rx->status);
-       return RX_QUEUED;
+       return RX_DROP_MONITOR;
 }
 
 static void ieee80211_rx_michael_mic_report(struct net_device *dev,
@@ -1996,6 +2032,7 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
        CALL_RXH(ieee80211_rx_h_passive_scan)
        CALL_RXH(ieee80211_rx_h_check)
        CALL_RXH(ieee80211_rx_h_decrypt)
+       CALL_RXH(ieee80211_rx_h_check_more_data)
        CALL_RXH(ieee80211_rx_h_sta_process)
        CALL_RXH(ieee80211_rx_h_defragment)
        CALL_RXH(ieee80211_rx_h_ps_poll)
@@ -2039,16 +2076,17 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
 /* main receive path */
 
 static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
-                               u8 *bssid, struct ieee80211_rx_data *rx,
+                               struct ieee80211_rx_data *rx,
                                struct ieee80211_hdr *hdr)
 {
+       u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len, sdata->vif.type);
        int multicast = is_multicast_ether_addr(hdr->addr1);
 
        switch (sdata->vif.type) {
        case NL80211_IFTYPE_STATION:
                if (!bssid)
                        return 0;
-               if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
+               if (!ieee80211_bssid_match(bssid, sdata->u.mgd.bssid)) {
                        if (!(rx->flags & IEEE80211_RX_IN_SCAN))
                                return 0;
                        rx->flags &= ~IEEE80211_RX_RA_MATCH;
@@ -2066,7 +2104,7 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata,
                if (ieee80211_is_beacon(hdr->frame_control)) {
                        return 1;
                }
-               else if (!ieee80211_bssid_match(bssid, sdata->u.sta.bssid)) {
+               else if (!ieee80211_bssid_match(bssid, sdata->u.ibss.bssid)) {
                        if (!(rx->flags & IEEE80211_RX_IN_SCAN))
                                return 0;
                        rx->flags &= ~IEEE80211_RX_RA_MATCH;
@@ -2144,7 +2182,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        int prepares;
        struct ieee80211_sub_if_data *prev = NULL;
        struct sk_buff *skb_new;
-       u8 *bssid;
 
        hdr = (struct ieee80211_hdr *)skb->data;
        memset(&rx, 0, sizeof(rx));
@@ -2183,9 +2220,8 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
                        continue;
 
-               bssid = ieee80211_get_bssid(hdr, skb->len, sdata->vif.type);
                rx.flags |= IEEE80211_RX_RA_MATCH;
-               prepares = prepare_for_handlers(sdata, bssid, &rx, hdr);
+               prepares = prepare_for_handlers(sdata, &rx, hdr);
 
                if (!prepares)
                        continue;
@@ -2390,11 +2426,9 @@ static u8 ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
        /* new un-ordered ampdu frame - process it */
 
        /* reset session timer */
-       if (tid_agg_rx->timeout) {
-               unsigned long expires =
-                       jiffies + (tid_agg_rx->timeout / 1000) * HZ;
-               mod_timer(&tid_agg_rx->session_timer, expires);
-       }
+       if (tid_agg_rx->timeout)
+               mod_timer(&tid_agg_rx->session_timer,
+                         TU_TO_EXP_TIME(tid_agg_rx->timeout));
 
        /* if this mpdu is fragmented - terminate rx aggregation session */
        sc = le16_to_cpu(hdr->seq_ctrl);