mac80211: Use rhltable instead of rhashtable
[cascardo/linux.git] / net / mac80211 / rx.c
index 9dce3b1..f7cf342 100644 (file)
@@ -180,6 +180,11 @@ ieee80211_rx_radiotap_hdrlen(struct ieee80211_local *local,
                len += 12;
        }
 
+       if (local->hw.radiotap_timestamp.units_pos >= 0) {
+               len = ALIGN(len, 8);
+               len += 12;
+       }
+
        if (status->chains) {
                /* antenna and antenna signal fields */
                len += 2 * hweight8(status->chains);
@@ -447,6 +452,31 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local,
                pos += 2;
        }
 
+       if (local->hw.radiotap_timestamp.units_pos >= 0) {
+               u16 accuracy = 0;
+               u8 flags = IEEE80211_RADIOTAP_TIMESTAMP_FLAG_32BIT;
+
+               rthdr->it_present |=
+                       cpu_to_le32(1 << IEEE80211_RADIOTAP_TIMESTAMP);
+
+               /* ensure 8 byte alignment */
+               while ((pos - (u8 *)rthdr) & 7)
+                       pos++;
+
+               put_unaligned_le64(status->device_timestamp, pos);
+               pos += sizeof(u64);
+
+               if (local->hw.radiotap_timestamp.accuracy >= 0) {
+                       accuracy = local->hw.radiotap_timestamp.accuracy;
+                       flags |= IEEE80211_RADIOTAP_TIMESTAMP_FLAG_ACCURACY;
+               }
+               put_unaligned_le16(accuracy, pos);
+               pos += sizeof(u16);
+
+               *pos++ = local->hw.radiotap_timestamp.units_pos;
+               *pos++ = flags;
+       }
+
        for_each_set_bit(chain, &chains, IEEE80211_MAX_CHAINS) {
                *pos++ = status->chain_signal[chain];
                *pos++ = chain;
@@ -485,6 +515,9 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
        struct net_device *prev_dev = NULL;
        int present_fcs_len = 0;
        unsigned int rtap_vendor_space = 0;
+       struct ieee80211_mgmt *mgmt;
+       struct ieee80211_sub_if_data *monitor_sdata =
+               rcu_dereference(local->monitor_sdata);
 
        if (unlikely(status->flag & RX_FLAG_RADIOTAP_VENDOR_DATA)) {
                struct ieee80211_vendor_radiotap *rtap = (void *)origskb->data;
@@ -567,7 +600,7 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
                if (sdata->vif.type != NL80211_IFTYPE_MONITOR)
                        continue;
 
-               if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES)
+               if (sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES)
                        continue;
 
                if (!ieee80211_sdata_running(sdata))
@@ -585,6 +618,23 @@ ieee80211_rx_monitor(struct ieee80211_local *local, struct sk_buff *origskb,
                ieee80211_rx_stats(sdata->dev, skb->len);
        }
 
+       mgmt = (void *)skb->data;
+       if (monitor_sdata &&
+           skb->len >= IEEE80211_MIN_ACTION_SIZE + 1 + VHT_MUMIMO_GROUPS_DATA_LEN &&
+           ieee80211_is_action(mgmt->frame_control) &&
+           mgmt->u.action.category == WLAN_CATEGORY_VHT &&
+           mgmt->u.action.u.vht_group_notif.action_code == WLAN_VHT_ACTION_GROUPID_MGMT &&
+           is_valid_ether_addr(monitor_sdata->u.mntr.mu_follow_addr) &&
+           ether_addr_equal(mgmt->da, monitor_sdata->u.mntr.mu_follow_addr)) {
+               struct sk_buff *mu_skb = skb_copy(skb, GFP_ATOMIC);
+
+               if (mu_skb) {
+                       mu_skb->pkt_type = IEEE80211_SDATA_QUEUE_TYPE_FRAME;
+                       skb_queue_tail(&monitor_sdata->skb_queue, mu_skb);
+                       ieee80211_queue_work(&local->hw, &monitor_sdata->work);
+               }
+       }
+
        if (prev_dev) {
                skb->dev = prev_dev;
                netif_receive_skb(skb);
@@ -1072,8 +1122,15 @@ static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
        tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
 
        tid_agg_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[tid]);
-       if (!tid_agg_rx)
+       if (!tid_agg_rx) {
+               if (ack_policy == IEEE80211_QOS_CTL_ACK_POLICY_BLOCKACK &&
+                   !test_bit(tid, rx->sta->ampdu_mlme.agg_session_valid) &&
+                   !test_and_set_bit(tid, rx->sta->ampdu_mlme.unexpected_agg))
+                       ieee80211_send_delba(rx->sdata, rx->sta->sta.addr, tid,
+                                            WLAN_BACK_RECIPIENT,
+                                            WLAN_REASON_QSTA_REQUIRE_SETUP);
                goto dont_reorder;
+       }
 
        /* qos null data frames are excluded */
        if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
@@ -2535,6 +2592,12 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
 
                tid = le16_to_cpu(bar_data.control) >> 12;
 
+               if (!test_bit(tid, rx->sta->ampdu_mlme.agg_session_valid) &&
+                   !test_and_set_bit(tid, rx->sta->ampdu_mlme.unexpected_agg))
+                       ieee80211_send_delba(rx->sdata, rx->sta->sta.addr, tid,
+                                            WLAN_BACK_RECIPIENT,
+                                            WLAN_REASON_QSTA_REQUIRE_SETUP);
+
                tid_agg_rx = rcu_dereference(rx->sta->ampdu_mlme.tid_rx[tid]);
                if (!tid_agg_rx)
                        return RX_DROP_MONITOR;
@@ -3147,7 +3210,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
                        continue;
 
                if (sdata->vif.type != NL80211_IFTYPE_MONITOR ||
-                   !(sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES))
+                   !(sdata->u.mntr.flags & MONITOR_FLAG_COOK_FRAMES))
                        continue;
 
                if (prev_dev) {
@@ -3940,7 +4003,7 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
        __le16 fc;
        struct ieee80211_rx_data rx;
        struct ieee80211_sub_if_data *prev;
-       struct rhash_head *tmp;
+       struct rhlist_head *tmp;
        int err = 0;
 
        fc = ((struct ieee80211_hdr *)skb->data)->frame_control;
@@ -3983,13 +4046,10 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
                goto out;
        } else if (ieee80211_is_data(fc)) {
                struct sta_info *sta, *prev_sta;
-               const struct bucket_table *tbl;
 
                prev_sta = NULL;
 
-               tbl = rht_dereference_rcu(local->sta_hash.tbl, &local->sta_hash);
-
-               for_each_sta_info(local, tbl, hdr->addr2, sta, tmp) {
+               for_each_sta_info(local, hdr->addr2, sta, tmp) {
                        if (!prev_sta) {
                                prev_sta = sta;
                                continue;