Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wirel...
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / net / mac80211 / rx.c
index c5d4530d8284e59f07b44af1ce904fea5fc26018..7fa8c6be7bf02564cd5714033fbdb8761b30b03d 100644 (file)
@@ -143,7 +143,8 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
        if (status->flag & RX_FLAG_HT) {
                /*
                 * MCS information is a separate field in radiotap,
-                * added below.
+                * added below. The byte here is needed as padding
+                * for the channel though, so initialise it to 0.
                 */
                *pos = 0;
        } else {
@@ -403,11 +404,13 @@ ieee80211_rx_h_passive_scan(struct ieee80211_rx_data *rx)
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
        struct sk_buff *skb = rx->skb;
 
-       if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN)))
+       if (likely(!(status->rx_flags & IEEE80211_RX_IN_SCAN) &&
+                  !local->sched_scanning))
                return RX_CONTINUE;
 
        if (test_bit(SCAN_HW_SCANNING, &local->scanning) ||
-           test_bit(SCAN_SW_SCANNING, &local->scanning))
+           test_bit(SCAN_SW_SCANNING, &local->scanning) ||
+           local->sched_scanning)
                return ieee80211_scan_rx(rx->sdata, skb);
 
        /* scanning finished during invoking of handlers */
@@ -487,22 +490,26 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
         * establisment frame, beacon or probe, drop the frame.
         */
 
-       if (!rx->sta || sta_plink_state(rx->sta) != PLINK_ESTAB) {
+       if (!rx->sta || sta_plink_state(rx->sta) != NL80211_PLINK_ESTAB) {
                struct ieee80211_mgmt *mgmt;
 
                if (!ieee80211_is_mgmt(hdr->frame_control))
                        return RX_DROP_MONITOR;
 
                if (ieee80211_is_action(hdr->frame_control)) {
+                       u8 category;
                        mgmt = (struct ieee80211_mgmt *)hdr;
-                       if (mgmt->u.action.category != WLAN_CATEGORY_MESH_PLINK)
+                       category = mgmt->u.action.category;
+                       if (category != WLAN_CATEGORY_MESH_ACTION &&
+                               category != WLAN_CATEGORY_SELF_PROTECTED)
                                return RX_DROP_MONITOR;
                        return RX_CONTINUE;
                }
 
                if (ieee80211_is_probe_req(hdr->frame_control) ||
                    ieee80211_is_probe_resp(hdr->frame_control) ||
-                   ieee80211_is_beacon(hdr->frame_control))
+                   ieee80211_is_beacon(hdr->frame_control) ||
+                   ieee80211_is_auth(hdr->frame_control))
                        return RX_CONTINUE;
 
                return RX_DROP_MONITOR;
@@ -650,7 +657,7 @@ static void ieee80211_sta_reorder_release(struct ieee80211_hw *hw,
  set_release_timer:
 
                mod_timer(&tid_agg_rx->reorder_timer,
-                         tid_agg_rx->reorder_time[j] +
+                         tid_agg_rx->reorder_time[j] + 1 +
                          HT_RX_REORDER_BUF_TIMEOUT);
        } else {
                del_timer(&tid_agg_rx->reorder_timer);
@@ -707,6 +714,8 @@ static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
        /*
         * If the current MPDU is in the right order and nothing else
         * is stored we can process it directly, no need to buffer it.
+        * If it is first but there's something stored, we may be able
+        * to release frames after this one.
         */
        if (mpdu_seq_num == tid_agg_rx->head_seq_num &&
            tid_agg_rx->stored_mpdu_num == 0) {
@@ -1583,7 +1592,7 @@ ieee80211_drop_unencrypted_mgmt(struct ieee80211_rx_data *rx)
 }
 
 static int
-__ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
+__ieee80211_data_to_8023(struct ieee80211_rx_data *rx, bool *port_control)
 {
        struct ieee80211_sub_if_data *sdata = rx->sdata;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
@@ -1591,6 +1600,7 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
        struct ethhdr *ehdr;
        int ret;
 
+       *port_control = false;
        if (ieee80211_has_a4(hdr->frame_control) &&
            sdata->vif.type == NL80211_IFTYPE_AP_VLAN && !sdata->u.vlan.sta)
                return -1;
@@ -1609,11 +1619,13 @@ __ieee80211_data_to_8023(struct ieee80211_rx_data *rx)
                return -1;
 
        ret = ieee80211_data_to_8023(rx->skb, sdata->vif.addr, sdata->vif.type);
-       if (ret < 0 || !check_port_control)
+       if (ret < 0)
                return ret;
 
        ehdr = (struct ethhdr *) rx->skb->data;
-       if (ehdr->h_proto != rx->sdata->control_port_protocol)
+       if (ehdr->h_proto == rx->sdata->control_port_protocol)
+               *port_control = true;
+       else if (check_port_control)
                return -1;
 
        return 0;
@@ -1771,7 +1783,7 @@ ieee80211_rx_h_amsdu(struct ieee80211_rx_data *rx)
 
        ieee80211_amsdu_to_8023s(skb, &frame_list, dev->dev_addr,
                                 rx->sdata->vif.type,
-                                rx->local->hw.extra_tx_headroom);
+                                rx->local->hw.extra_tx_headroom, true);
 
        while (!skb_queue_empty(&frame_list)) {
                rx->skb = __skb_dequeue(&frame_list);
@@ -1914,6 +1926,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
        struct net_device *dev = sdata->dev;
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
        __le16 fc = hdr->frame_control;
+       bool port_control;
        int err;
 
        if (unlikely(!ieee80211_is_data(hdr->frame_control)))
@@ -1930,13 +1943,21 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
            sdata->vif.type == NL80211_IFTYPE_AP)
                return RX_DROP_MONITOR;
 
-       err = __ieee80211_data_to_8023(rx);
+       err = __ieee80211_data_to_8023(rx, &port_control);
        if (unlikely(err))
                return RX_DROP_UNUSABLE;
 
        if (!ieee80211_frame_allowed(rx, fc))
                return RX_DROP_MONITOR;
 
+       if (rx->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
+           unlikely(port_control) && sdata->bss) {
+               sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
+                                    u.ap);
+               dev = sdata->dev;
+               rx->sdata = sdata;
+       }
+
        rx->skb->dev = dev;
 
        dev->stats.rx_packets++;
@@ -2189,7 +2210,7 @@ ieee80211_rx_h_action(struct ieee80211_rx_data *rx)
                        goto handled;
                }
                break;
-       case WLAN_CATEGORY_MESH_PLINK:
+       case WLAN_CATEGORY_MESH_ACTION:
                if (!ieee80211_vif_is_mesh(&sdata->vif))
                        break;
                goto queue;
@@ -2352,47 +2373,6 @@ ieee80211_rx_h_mgmt(struct ieee80211_rx_data *rx)
        return RX_QUEUED;
 }
 
-static void ieee80211_rx_michael_mic_report(struct ieee80211_hdr *hdr,
-                                           struct ieee80211_rx_data *rx)
-{
-       int keyidx;
-       unsigned int hdrlen;
-
-       hdrlen = ieee80211_hdrlen(hdr->frame_control);
-       if (rx->skb->len >= hdrlen + 4)
-               keyidx = rx->skb->data[hdrlen + 3] >> 6;
-       else
-               keyidx = -1;
-
-       if (!rx->sta) {
-               /*
-                * Some hardware seem to generate incorrect Michael MIC
-                * reports; ignore them to avoid triggering countermeasures.
-                */
-               return;
-       }
-
-       if (!ieee80211_has_protected(hdr->frame_control))
-               return;
-
-       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
-                * group keys and only the AP is sending real multicast
-                * frames in the BSS.
-                */
-               return;
-       }
-
-       if (!ieee80211_is_data(hdr->frame_control) &&
-           !ieee80211_is_auth(hdr->frame_control))
-               return;
-
-       mac80211_ev_michael_mic_failure(rx->sdata, keyidx, hdr, NULL,
-                                       GFP_ATOMIC);
-}
-
 /* TODO: use IEEE80211_RX_FRAGMENTED */
 static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
                                        struct ieee80211_rate *rate)
@@ -2736,12 +2716,6 @@ static bool ieee80211_prepare_and_rx_handle(struct ieee80211_rx_data *rx,
        if (!prepares)
                return false;
 
-       if (status->flag & RX_FLAG_MMIC_ERROR) {
-               if (status->rx_flags & IEEE80211_RX_RA_MATCH)
-                       ieee80211_rx_michael_mic_report(hdr, rx);
-               return false;
-       }
-
        if (!consume) {
                skb = skb_copy(skb, GFP_ATOMIC);
                if (!skb) {