Merge remote-tracking branch 'net-next/master' into mac80211-next
authorJohannes Berg <johannes.berg@intel.com>
Wed, 10 Jun 2015 10:44:58 +0000 (12:44 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 10 Jun 2015 10:45:09 +0000 (12:45 +0200)
Merge back net-next to get wireless driver changes (from Kalle)
to be able to create the API change across all trees properly.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
19 files changed:
drivers/net/wireless/ath/wcn36xx/smd.c
drivers/net/wireless/iwlwifi/mvm/mac80211.c
include/net/mac80211.h
net/mac80211/cfg.c
net/mac80211/debugfs.c
net/mac80211/debugfs_key.c
net/mac80211/ibss.c
net/mac80211/key.c
net/mac80211/key.h
net/mac80211/mesh.c
net/mac80211/mesh_hwmp.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/scan.c
net/mac80211/sta_info.h
net/mac80211/status.c
net/mac80211/tdls.c
net/mac80211/tx.c
net/mac80211/wpa.c

index dbd8944..c9263e1 100644 (file)
@@ -216,9 +216,7 @@ static void wcn36xx_smd_set_sta_params(struct wcn36xx *wcn,
                memcpy(&sta_params->bssid, vif->addr, ETH_ALEN);
 
        sta_params->encrypt_type = priv_vif->encrypt_type;
-       sta_params->short_preamble_supported =
-               !(WCN36XX_FLAGS(wcn) &
-                 IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE);
+       sta_params->short_preamble_supported = true;
 
        sta_params->rifs_mode = 0;
        sta_params->rmf = 0;
index 08367fb..81daf00 100644 (file)
@@ -474,7 +474,7 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
                hw->wiphy->n_cipher_suites++;
        }
 
-       hw->flags |= IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS;
+       hw->flags |= IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS;
        hw->wiphy->features |=
                NL80211_FEATURE_SCHED_SCAN_RANDOM_MAC_ADDR |
                NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR |
index 887fe95..faadb73 100644 (file)
@@ -446,12 +446,8 @@ struct ieee80211_event {
  * @ibss_creator: indicates if a new IBSS network is being created
  * @aid: association ID number, valid only when @assoc is true
  * @use_cts_prot: use CTS protection
- * @use_short_preamble: use 802.11b short preamble;
- *     if the hardware cannot handle this it must set the
- *     IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE hardware flag
- * @use_short_slot: use short slot time (only relevant for ERP);
- *     if the hardware cannot handle this it must set the
- *     IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE hardware flag
+ * @use_short_preamble: use 802.11b short preamble
+ * @use_short_slot: use short slot time (only relevant for ERP)
  * @dtim_period: num of beacons before the next DTIM, for beaconing,
  *     valid in station mode only if after the driver was notified
  *     with the %BSS_CHANGED_BEACON_INFO flag, will be non-zero then.
@@ -874,6 +870,9 @@ struct ieee80211_tx_info {
                        u32 flags;
                        /* 4 bytes free */
                } control;
+               struct {
+                       u64 cookie;
+               } ack;
                struct {
                        struct ieee80211_tx_rate rates[IEEE80211_TX_MAX_RATES];
                        s32 ack_signal;
@@ -1479,6 +1478,9 @@ enum ieee80211_key_flags {
  *     wants to be given when a frame is transmitted and needs to be
  *     encrypted in hardware.
  * @cipher: The key's cipher suite selector.
+ * @tx_pn: PN used for TX on non-TKIP keys, may be used by the driver
+ *     as well if it needs to do software PN assignment by itself
+ *     (e.g. due to TSO)
  * @flags: key flags, see &enum ieee80211_key_flags.
  * @keyidx: the key index (0-3)
  * @keylen: key material length
@@ -1491,6 +1493,7 @@ enum ieee80211_key_flags {
  * @iv_len: The IV length for this key type
  */
 struct ieee80211_key_conf {
+       atomic64_t tx_pn;
        u32 cipher;
        u8 icv_len;
        u8 iv_len;
@@ -1777,13 +1780,6 @@ struct ieee80211_txq {
  *     multicast frames when there are power saving stations so that
  *     the driver can fetch them with ieee80211_get_buffered_bc().
  *
- * @IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE:
- *     Hardware is not capable of short slot operation on the 2.4 GHz band.
- *
- * @IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE:
- *     Hardware is not capable of receiving frames with short preamble on
- *     the 2.4 GHz band.
- *
  * @IEEE80211_HW_SIGNAL_UNSPEC:
  *     Hardware can provide signal values but we don't know its units. We
  *     expect values between 0 and @max_signal.
@@ -1889,15 +1885,13 @@ struct ieee80211_txq {
  * @IEEE80211_HW_SUPPORTS_CLONED_SKBS: The driver will never modify the payload
  *     or tailroom of TX skbs without copying them first.
  *
- * @IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS: The HW supports scanning on all bands
+ * @IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS: The HW supports scanning on all bands
  *     in one command, mac80211 doesn't have to run separate scans per band.
  */
 enum ieee80211_hw_flags {
        IEEE80211_HW_HAS_RATE_CONTROL                   = 1<<0,
        IEEE80211_HW_RX_INCLUDES_FCS                    = 1<<1,
        IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING        = 1<<2,
-       IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE          = 1<<3,
-       IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE      = 1<<4,
        IEEE80211_HW_SIGNAL_UNSPEC                      = 1<<5,
        IEEE80211_HW_SIGNAL_DBM                         = 1<<6,
        IEEE80211_HW_NEED_DTIM_BEFORE_ASSOC             = 1<<7,
@@ -1923,7 +1917,7 @@ enum ieee80211_hw_flags {
        IEEE80211_HW_SUPPORTS_HT_CCK_RATES              = 1<<27,
        IEEE80211_HW_CHANCTX_STA_CSA                    = 1<<28,
        IEEE80211_HW_SUPPORTS_CLONED_SKBS               = 1<<29,
-       IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS           = 1<<30,
+       IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS           = 1<<30,
 };
 
 /**
@@ -2590,8 +2584,7 @@ void ieee80211_free_txskb(struct ieee80211_hw *hw, struct sk_buff *skb);
  *
  * @FIF_OTHER_BSS: pass frames destined to other BSSes
  *
- * @FIF_PSPOLL: pass PS Poll frames, if PROMISC_IN_BSS is not set then only
- *     those addressed to this station.
+ * @FIF_PSPOLL: pass PS Poll frames
  *
  * @FIF_PROBE_REQ: pass probe request frames
  */
index 690b9f6..1d01190 100644 (file)
@@ -2,7 +2,7 @@
  * mac80211 configuration hooks for cfg80211
  *
  * Copyright 2006-2010 Johannes Berg <johannes@sipsolutions.net>
- * Copyright 2013-2014  Intel Mobile Communications GmbH
+ * Copyright 2013-2015  Intel Mobile Communications GmbH
  *
  * This file is GPLv2 as found in COPYING.
  */
@@ -361,66 +361,25 @@ static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
                break;
        case WLAN_CIPHER_SUITE_CCMP:
        case WLAN_CIPHER_SUITE_CCMP_256:
-               if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
-                   !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
-                       drv_get_key_seq(sdata->local, key, &kseq);
-                       memcpy(seq, kseq.ccmp.pn, 6);
-               } else {
-                       pn64 = atomic64_read(&key->u.ccmp.tx_pn);
-                       seq[0] = pn64;
-                       seq[1] = pn64 >> 8;
-                       seq[2] = pn64 >> 16;
-                       seq[3] = pn64 >> 24;
-                       seq[4] = pn64 >> 32;
-                       seq[5] = pn64 >> 40;
-               }
-               params.seq = seq;
-               params.seq_len = 6;
-               break;
        case WLAN_CIPHER_SUITE_AES_CMAC:
        case WLAN_CIPHER_SUITE_BIP_CMAC_256:
-               if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
-                   !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
-                       drv_get_key_seq(sdata->local, key, &kseq);
-                       memcpy(seq, kseq.aes_cmac.pn, 6);
-               } else {
-                       pn64 = atomic64_read(&key->u.aes_cmac.tx_pn);
-                       seq[0] = pn64;
-                       seq[1] = pn64 >> 8;
-                       seq[2] = pn64 >> 16;
-                       seq[3] = pn64 >> 24;
-                       seq[4] = pn64 >> 32;
-                       seq[5] = pn64 >> 40;
-               }
-               params.seq = seq;
-               params.seq_len = 6;
-               break;
+               BUILD_BUG_ON(offsetof(typeof(kseq), ccmp) !=
+                            offsetof(typeof(kseq), aes_cmac));
        case WLAN_CIPHER_SUITE_BIP_GMAC_128:
        case WLAN_CIPHER_SUITE_BIP_GMAC_256:
-               if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
-                   !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
-                       drv_get_key_seq(sdata->local, key, &kseq);
-                       memcpy(seq, kseq.aes_gmac.pn, 6);
-               } else {
-                       pn64 = atomic64_read(&key->u.aes_gmac.tx_pn);
-                       seq[0] = pn64;
-                       seq[1] = pn64 >> 8;
-                       seq[2] = pn64 >> 16;
-                       seq[3] = pn64 >> 24;
-                       seq[4] = pn64 >> 32;
-                       seq[5] = pn64 >> 40;
-               }
-               params.seq = seq;
-               params.seq_len = 6;
-               break;
+               BUILD_BUG_ON(offsetof(typeof(kseq), ccmp) !=
+                            offsetof(typeof(kseq), aes_gmac));
        case WLAN_CIPHER_SUITE_GCMP:
        case WLAN_CIPHER_SUITE_GCMP_256:
+               BUILD_BUG_ON(offsetof(typeof(kseq), ccmp) !=
+                            offsetof(typeof(kseq), gcmp));
+
                if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
                    !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
                        drv_get_key_seq(sdata->local, key, &kseq);
-                       memcpy(seq, kseq.gcmp.pn, 6);
+                       memcpy(seq, kseq.ccmp.pn, 6);
                } else {
-                       pn64 = atomic64_read(&key->u.gcmp.tx_pn);
+                       pn64 = atomic64_read(&key->conf.tx_pn);
                        seq[0] = pn64;
                        seq[1] = pn64 >> 8;
                        seq[2] = pn64 >> 16;
@@ -2558,6 +2517,19 @@ static bool ieee80211_coalesce_started_roc(struct ieee80211_local *local,
        return true;
 }
 
+static u64 ieee80211_mgmt_tx_cookie(struct ieee80211_local *local)
+{
+       lockdep_assert_held(&local->mtx);
+
+       local->roc_cookie_counter++;
+
+       /* wow, you wrapped 64 bits ... more likely a bug */
+       if (WARN_ON(local->roc_cookie_counter == 0))
+               local->roc_cookie_counter++;
+
+       return local->roc_cookie_counter;
+}
+
 static int ieee80211_start_roc_work(struct ieee80211_local *local,
                                    struct ieee80211_sub_if_data *sdata,
                                    struct ieee80211_channel *channel,
@@ -2595,7 +2567,6 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
        roc->req_duration = duration;
        roc->frame = txskb;
        roc->type = type;
-       roc->mgmt_tx_cookie = (unsigned long)txskb;
        roc->sdata = sdata;
        INIT_DELAYED_WORK(&roc->work, ieee80211_sw_roc_work);
        INIT_LIST_HEAD(&roc->dependents);
@@ -2605,17 +2576,10 @@ static int ieee80211_start_roc_work(struct ieee80211_local *local,
         * or the SKB (for mgmt TX)
         */
        if (!txskb) {
-               /* local->mtx protects this */
-               local->roc_cookie_counter++;
-               roc->cookie = local->roc_cookie_counter;
-               /* wow, you wrapped 64 bits ... more likely a bug */
-               if (WARN_ON(roc->cookie == 0)) {
-                       roc->cookie = 1;
-                       local->roc_cookie_counter++;
-               }
+               roc->cookie = ieee80211_mgmt_tx_cookie(local);
                *cookie = roc->cookie;
        } else {
-               *cookie = (unsigned long)txskb;
+               roc->mgmt_tx_cookie = *cookie;
        }
 
        /* if there's one pending or we're scanning, queue this one */
@@ -3288,13 +3252,43 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
        return err;
 }
 
+static struct sk_buff *ieee80211_make_ack_skb(struct ieee80211_local *local,
+                                             struct sk_buff *skb, u64 *cookie,
+                                             gfp_t gfp)
+{
+       unsigned long spin_flags;
+       struct sk_buff *ack_skb;
+       int id;
+
+       ack_skb = skb_copy(skb, gfp);
+       if (!ack_skb)
+               return ERR_PTR(-ENOMEM);
+
+       spin_lock_irqsave(&local->ack_status_lock, spin_flags);
+       id = idr_alloc(&local->ack_status_frames, ack_skb,
+                      1, 0x10000, GFP_ATOMIC);
+       spin_unlock_irqrestore(&local->ack_status_lock, spin_flags);
+
+       if (id < 0) {
+               kfree_skb(ack_skb);
+               return ERR_PTR(-ENOMEM);
+       }
+
+       IEEE80211_SKB_CB(skb)->ack_frame_id = id;
+
+       *cookie = ieee80211_mgmt_tx_cookie(local);
+       IEEE80211_SKB_CB(ack_skb)->ack.cookie = *cookie;
+
+       return ack_skb;
+}
+
 static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
                             struct cfg80211_mgmt_tx_params *params,
                             u64 *cookie)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
        struct ieee80211_local *local = sdata->local;
-       struct sk_buff *skb;
+       struct sk_buff *skb, *ack_skb;
        struct sta_info *sta;
        const struct ieee80211_mgmt *mgmt = (void *)params->buf;
        bool need_offchan = false;
@@ -3406,6 +3400,7 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
        /* Update CSA counters */
        if (sdata->vif.csa_active &&
            (sdata->vif.type == NL80211_IFTYPE_AP ||
+            sdata->vif.type == NL80211_IFTYPE_MESH_POINT ||
             sdata->vif.type == NL80211_IFTYPE_ADHOC) &&
            params->n_csa_offsets) {
                int i;
@@ -3432,8 +3427,23 @@ static int ieee80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
 
        skb->dev = sdata->dev;
 
+       if (!params->dont_wait_for_ack) {
+               /* make a copy to preserve the frame contents
+                * in case of encryption.
+                */
+               ack_skb = ieee80211_make_ack_skb(local, skb, cookie,
+                                                GFP_KERNEL);
+               if (IS_ERR(ack_skb)) {
+                       ret = PTR_ERR(ack_skb);
+                       kfree_skb(skb);
+                       goto out_unlock;
+               }
+       } else {
+               /* for cookie below */
+               ack_skb = skb;
+       }
+
        if (!need_offchan) {
-               *cookie = (unsigned long) skb;
                ieee80211_tx_skb(sdata, skb);
                ret = 0;
                goto out_unlock;
@@ -3526,7 +3536,7 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
        struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_qos_hdr *nullfunc;
-       struct sk_buff *skb;
+       struct sk_buff *skb, *ack_skb;
        int size = sizeof(*nullfunc);
        __le16 fc;
        bool qos;
@@ -3534,20 +3544,24 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
        struct sta_info *sta;
        struct ieee80211_chanctx_conf *chanctx_conf;
        enum ieee80211_band band;
+       int ret;
+
+       /* the lock is needed to assign the cookie later */
+       mutex_lock(&local->mtx);
 
        rcu_read_lock();
        chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
        if (WARN_ON(!chanctx_conf)) {
-               rcu_read_unlock();
-               return -EINVAL;
+               ret = -EINVAL;
+               goto unlock;
        }
        band = chanctx_conf->def.chan->band;
        sta = sta_info_get_bss(sdata, peer);
        if (sta) {
                qos = sta->sta.wme;
        } else {
-               rcu_read_unlock();
-               return -ENOLINK;
+               ret = -ENOLINK;
+               goto unlock;
        }
 
        if (qos) {
@@ -3563,8 +3577,8 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
 
        skb = dev_alloc_skb(local->hw.extra_tx_headroom + size);
        if (!skb) {
-               rcu_read_unlock();
-               return -ENOMEM;
+               ret = -ENOMEM;
+               goto unlock;
        }
 
        skb->dev = dev;
@@ -3590,13 +3604,23 @@ static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
        if (qos)
                nullfunc->qos_ctrl = cpu_to_le16(7);
 
+       ack_skb = ieee80211_make_ack_skb(local, skb, cookie, GFP_ATOMIC);
+       if (IS_ERR(ack_skb)) {
+               kfree_skb(skb);
+               ret = PTR_ERR(ack_skb);
+               goto unlock;
+       }
+
        local_bh_disable();
        ieee80211_xmit(sdata, sta, skb);
        local_bh_enable();
+
+       ret = 0;
+unlock:
        rcu_read_unlock();
+       mutex_unlock(&local->mtx);
 
-       *cookie = (unsigned long) skb;
-       return 0;
+       return ret;
 }
 
 static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
index b17206d..1b94d27 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * mac80211 debugfs for wireless PHYs
  *
@@ -112,12 +111,6 @@ static ssize_t hwflags_read(struct file *file, char __user *user_buf,
        if (local->hw.flags & IEEE80211_HW_HOST_BROADCAST_PS_BUFFERING)
                sf += scnprintf(buf + sf, mxln - sf,
                                "HOST_BCAST_PS_BUFFERING\n");
-       if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE)
-               sf += scnprintf(buf + sf, mxln - sf,
-                               "2GHZ_SHORT_SLOT_INCAPABLE\n");
-       if (local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE)
-               sf += scnprintf(buf + sf, mxln - sf,
-                               "2GHZ_SHORT_PREAMBLE_INCAPABLE\n");
        if (local->hw.flags & IEEE80211_HW_SIGNAL_UNSPEC)
                sf += scnprintf(buf + sf, mxln - sf, "SIGNAL_UNSPEC\n");
        if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
index 71ac1b5..e82bf1e 100644 (file)
@@ -95,28 +95,13 @@ static ssize_t key_tx_spec_read(struct file *file, char __user *userbuf,
                break;
        case WLAN_CIPHER_SUITE_CCMP:
        case WLAN_CIPHER_SUITE_CCMP_256:
-               pn = atomic64_read(&key->u.ccmp.tx_pn);
-               len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
-                               (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
-                               (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
-               break;
        case WLAN_CIPHER_SUITE_AES_CMAC:
        case WLAN_CIPHER_SUITE_BIP_CMAC_256:
-               pn = atomic64_read(&key->u.aes_cmac.tx_pn);
-               len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
-                               (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
-                               (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
-               break;
        case WLAN_CIPHER_SUITE_BIP_GMAC_128:
        case WLAN_CIPHER_SUITE_BIP_GMAC_256:
-               pn = atomic64_read(&key->u.aes_gmac.tx_pn);
-               len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
-                               (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
-                               (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
-               break;
        case WLAN_CIPHER_SUITE_GCMP:
        case WLAN_CIPHER_SUITE_GCMP_256:
-               pn = atomic64_read(&key->u.gcmp.tx_pn);
+               pn = atomic64_read(&key->conf.tx_pn);
                len = scnprintf(buf, sizeof(buf), "%02x%02x%02x%02x%02x%02x\n",
                                (u8)(pn >> 40), (u8)(pn >> 32), (u8)(pn >> 24),
                                (u8)(pn >> 16), (u8)(pn >> 8), (u8)pn);
index 21716af..7f72bc9 100644 (file)
@@ -146,6 +146,7 @@ ieee80211_ibss_build_presp(struct ieee80211_sub_if_data *sdata,
                                csa_settings->chandef.chan->center_freq);
                presp->csa_counter_offsets[0] = (pos - presp->head);
                *pos++ = csa_settings->count;
+               presp->csa_current_counter = csa_settings->count;
        }
 
        /* put the remaining rates in WLAN_EID_EXT_SUPP_RATES */
index 577a11a..b9aac80 100644 (file)
@@ -896,27 +896,19 @@ void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
                break;
        case WLAN_CIPHER_SUITE_CCMP:
        case WLAN_CIPHER_SUITE_CCMP_256:
-               pn64 = atomic64_read(&key->u.ccmp.tx_pn);
-               seq->ccmp.pn[5] = pn64;
-               seq->ccmp.pn[4] = pn64 >> 8;
-               seq->ccmp.pn[3] = pn64 >> 16;
-               seq->ccmp.pn[2] = pn64 >> 24;
-               seq->ccmp.pn[1] = pn64 >> 32;
-               seq->ccmp.pn[0] = pn64 >> 40;
-               break;
        case WLAN_CIPHER_SUITE_AES_CMAC:
        case WLAN_CIPHER_SUITE_BIP_CMAC_256:
-               pn64 = atomic64_read(&key->u.aes_cmac.tx_pn);
-               seq->ccmp.pn[5] = pn64;
-               seq->ccmp.pn[4] = pn64 >> 8;
-               seq->ccmp.pn[3] = pn64 >> 16;
-               seq->ccmp.pn[2] = pn64 >> 24;
-               seq->ccmp.pn[1] = pn64 >> 32;
-               seq->ccmp.pn[0] = pn64 >> 40;
-               break;
+               BUILD_BUG_ON(offsetof(typeof(*seq), ccmp) !=
+                            offsetof(typeof(*seq), aes_cmac));
        case WLAN_CIPHER_SUITE_BIP_GMAC_128:
        case WLAN_CIPHER_SUITE_BIP_GMAC_256:
-               pn64 = atomic64_read(&key->u.aes_gmac.tx_pn);
+               BUILD_BUG_ON(offsetof(typeof(*seq), ccmp) !=
+                            offsetof(typeof(*seq), aes_gmac));
+       case WLAN_CIPHER_SUITE_GCMP:
+       case WLAN_CIPHER_SUITE_GCMP_256:
+               BUILD_BUG_ON(offsetof(typeof(*seq), ccmp) !=
+                            offsetof(typeof(*seq), gcmp));
+               pn64 = atomic64_read(&key->conf.tx_pn);
                seq->ccmp.pn[5] = pn64;
                seq->ccmp.pn[4] = pn64 >> 8;
                seq->ccmp.pn[3] = pn64 >> 16;
@@ -924,16 +916,6 @@ void ieee80211_get_key_tx_seq(struct ieee80211_key_conf *keyconf,
                seq->ccmp.pn[1] = pn64 >> 32;
                seq->ccmp.pn[0] = pn64 >> 40;
                break;
-       case WLAN_CIPHER_SUITE_GCMP:
-       case WLAN_CIPHER_SUITE_GCMP_256:
-               pn64 = atomic64_read(&key->u.gcmp.tx_pn);
-               seq->gcmp.pn[5] = pn64;
-               seq->gcmp.pn[4] = pn64 >> 8;
-               seq->gcmp.pn[3] = pn64 >> 16;
-               seq->gcmp.pn[2] = pn64 >> 24;
-               seq->gcmp.pn[1] = pn64 >> 32;
-               seq->gcmp.pn[0] = pn64 >> 40;
-               break;
        default:
                WARN_ON(1);
        }
@@ -1008,43 +990,25 @@ void ieee80211_set_key_tx_seq(struct ieee80211_key_conf *keyconf,
                break;
        case WLAN_CIPHER_SUITE_CCMP:
        case WLAN_CIPHER_SUITE_CCMP_256:
-               pn64 = (u64)seq->ccmp.pn[5] |
-                      ((u64)seq->ccmp.pn[4] << 8) |
-                      ((u64)seq->ccmp.pn[3] << 16) |
-                      ((u64)seq->ccmp.pn[2] << 24) |
-                      ((u64)seq->ccmp.pn[1] << 32) |
-                      ((u64)seq->ccmp.pn[0] << 40);
-               atomic64_set(&key->u.ccmp.tx_pn, pn64);
-               break;
        case WLAN_CIPHER_SUITE_AES_CMAC:
        case WLAN_CIPHER_SUITE_BIP_CMAC_256:
-               pn64 = (u64)seq->aes_cmac.pn[5] |
-                      ((u64)seq->aes_cmac.pn[4] << 8) |
-                      ((u64)seq->aes_cmac.pn[3] << 16) |
-                      ((u64)seq->aes_cmac.pn[2] << 24) |
-                      ((u64)seq->aes_cmac.pn[1] << 32) |
-                      ((u64)seq->aes_cmac.pn[0] << 40);
-               atomic64_set(&key->u.aes_cmac.tx_pn, pn64);
-               break;
+               BUILD_BUG_ON(offsetof(typeof(*seq), ccmp) !=
+                            offsetof(typeof(*seq), aes_cmac));
        case WLAN_CIPHER_SUITE_BIP_GMAC_128:
        case WLAN_CIPHER_SUITE_BIP_GMAC_256:
-               pn64 = (u64)seq->aes_gmac.pn[5] |
-                      ((u64)seq->aes_gmac.pn[4] << 8) |
-                      ((u64)seq->aes_gmac.pn[3] << 16) |
-                      ((u64)seq->aes_gmac.pn[2] << 24) |
-                      ((u64)seq->aes_gmac.pn[1] << 32) |
-                      ((u64)seq->aes_gmac.pn[0] << 40);
-               atomic64_set(&key->u.aes_gmac.tx_pn, pn64);
-               break;
+               BUILD_BUG_ON(offsetof(typeof(*seq), ccmp) !=
+                            offsetof(typeof(*seq), aes_gmac));
        case WLAN_CIPHER_SUITE_GCMP:
        case WLAN_CIPHER_SUITE_GCMP_256:
-               pn64 = (u64)seq->gcmp.pn[5] |
-                      ((u64)seq->gcmp.pn[4] << 8) |
-                      ((u64)seq->gcmp.pn[3] << 16) |
-                      ((u64)seq->gcmp.pn[2] << 24) |
-                      ((u64)seq->gcmp.pn[1] << 32) |
-                      ((u64)seq->gcmp.pn[0] << 40);
-               atomic64_set(&key->u.gcmp.tx_pn, pn64);
+               BUILD_BUG_ON(offsetof(typeof(*seq), ccmp) !=
+                            offsetof(typeof(*seq), gcmp));
+               pn64 = (u64)seq->ccmp.pn[5] |
+                      ((u64)seq->ccmp.pn[4] << 8) |
+                      ((u64)seq->ccmp.pn[3] << 16) |
+                      ((u64)seq->ccmp.pn[2] << 24) |
+                      ((u64)seq->ccmp.pn[1] << 32) |
+                      ((u64)seq->ccmp.pn[0] << 40);
+               atomic64_set(&key->conf.tx_pn, pn64);
                break;
        default:
                WARN_ON(1);
index 2119526..3f4f9ea 100644 (file)
@@ -77,7 +77,6 @@ struct ieee80211_key {
                        u32 mic_failures;
                } tkip;
                struct {
-                       atomic64_t tx_pn;
                        /*
                         * Last received packet number. The first
                         * IEEE80211_NUM_TIDS counters are used with Data
@@ -89,21 +88,18 @@ struct ieee80211_key {
                        u32 replays; /* dot11RSNAStatsCCMPReplays */
                } ccmp;
                struct {
-                       atomic64_t tx_pn;
                        u8 rx_pn[IEEE80211_CMAC_PN_LEN];
                        struct crypto_cipher *tfm;
                        u32 replays; /* dot11RSNAStatsCMACReplays */
                        u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
                } aes_cmac;
                struct {
-                       atomic64_t tx_pn;
                        u8 rx_pn[IEEE80211_GMAC_PN_LEN];
                        struct crypto_aead *tfm;
                        u32 replays; /* dot11RSNAStatsCMACReplays */
                        u32 icverrors; /* dot11RSNAStatsCMACICVErrors */
                } aes_gmac;
                struct {
-                       atomic64_t tx_pn;
                        /* Last received packet number. The first
                         * IEEE80211_NUM_TIDS counters are used with Data
                         * frames and the last counter is used with Robust
index d468424..817098a 100644 (file)
@@ -680,6 +680,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
                *pos++ = 0x0;
                *pos++ = ieee80211_frequency_to_channel(
                                csa->settings.chandef.chan->center_freq);
+               bcn->csa_current_counter = csa->settings.count;
                bcn->csa_counter_offsets[0] = hdr_len + 6;
                *pos++ = csa->settings.count;
                *pos++ = WLAN_EID_CHAN_SWITCH_PARAM;
index 214e63b..085edc1 100644 (file)
@@ -510,14 +510,14 @@ static u32 hwmp_route_info_get(struct ieee80211_sub_if_data *sdata,
 
 static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
                                    struct ieee80211_mgmt *mgmt,
-                                   const u8 *preq_elem, u32 metric)
+                                   const u8 *preq_elem, u32 orig_metric)
 {
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
        struct mesh_path *mpath = NULL;
        const u8 *target_addr, *orig_addr;
        const u8 *da;
        u8 target_flags, ttl, flags;
-       u32 orig_sn, target_sn, lifetime, orig_metric;
+       u32 orig_sn, target_sn, lifetime, target_metric;
        bool reply = false;
        bool forward = true;
        bool root_is_gate;
@@ -528,7 +528,6 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
        target_sn = PREQ_IE_TARGET_SN(preq_elem);
        orig_sn = PREQ_IE_ORIG_SN(preq_elem);
        target_flags = PREQ_IE_TARGET_F(preq_elem);
-       orig_metric = metric;
        /* Proactive PREQ gate announcements */
        flags = PREQ_IE_FLAGS(preq_elem);
        root_is_gate = !!(flags & RANN_FLAG_IS_GATE);
@@ -539,7 +538,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
                mhwmp_dbg(sdata, "PREQ is for us\n");
                forward = false;
                reply = true;
-               metric = 0;
+               target_metric = 0;
                if (time_after(jiffies, ifmsh->last_sn_update +
                                        net_traversal_jiffies(sdata)) ||
                    time_before(jiffies, ifmsh->last_sn_update)) {
@@ -556,7 +555,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
                                reply = true;
                                target_addr = sdata->vif.addr;
                                target_sn = ++ifmsh->sn;
-                               metric = 0;
+                               target_metric = 0;
                                ifmsh->last_sn_update = jiffies;
                        }
                        if (root_is_gate)
@@ -574,7 +573,7 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
                        } else if ((!(target_flags & MP_F_DO)) &&
                                        (mpath->flags & MESH_PATH_ACTIVE)) {
                                reply = true;
-                               metric = mpath->metric;
+                               target_metric = mpath->metric;
                                target_sn = mpath->sn;
                                if (target_flags & MP_F_RF)
                                        target_flags |= MP_F_DO;
@@ -593,7 +592,8 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
                        mesh_path_sel_frame_tx(MPATH_PREP, 0, orig_addr,
                                               orig_sn, 0, target_addr,
                                               target_sn, mgmt->sa, 0, ttl,
-                                              lifetime, metric, 0, sdata);
+                                              lifetime, target_metric, 0,
+                                              sdata);
                } else {
                        ifmsh->mshstats.dropped_frames_ttl++;
                }
@@ -619,13 +619,12 @@ static void hwmp_preq_frame_process(struct ieee80211_sub_if_data *sdata,
                if (flags & IEEE80211_PREQ_PROACTIVE_PREP_FLAG) {
                        target_addr = PREQ_IE_TARGET_ADDR(preq_elem);
                        target_sn = PREQ_IE_TARGET_SN(preq_elem);
-                       metric = orig_metric;
                }
 
                mesh_path_sel_frame_tx(MPATH_PREQ, flags, orig_addr,
                                       orig_sn, target_flags, target_addr,
                                       target_sn, da, hopcount, ttl, lifetime,
-                                      metric, preq_id, sdata);
+                                      orig_metric, preq_id, sdata);
                if (!is_multicast_ether_addr(da))
                        ifmsh->mshstats.fwded_unicast++;
                else
@@ -854,7 +853,7 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
 {
        struct ieee802_11_elems elems;
        size_t baselen;
-       u32 last_hop_metric;
+       u32 path_metric;
        struct sta_info *sta;
 
        /* need action_code */
@@ -877,21 +876,21 @@ void mesh_rx_path_sel_frame(struct ieee80211_sub_if_data *sdata,
                if (elems.preq_len != 37)
                        /* Right now we support just 1 destination and no AE */
                        return;
-               last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.preq,
-                                                     MPATH_PREQ);
-               if (last_hop_metric)
+               path_metric = hwmp_route_info_get(sdata, mgmt, elems.preq,
+                                                 MPATH_PREQ);
+               if (path_metric)
                        hwmp_preq_frame_process(sdata, mgmt, elems.preq,
-                                               last_hop_metric);
+                                               path_metric);
        }
        if (elems.prep) {
                if (elems.prep_len != 31)
                        /* Right now we support no AE */
                        return;
-               last_hop_metric = hwmp_route_info_get(sdata, mgmt, elems.prep,
-                                                     MPATH_PREP);
-               if (last_hop_metric)
+               path_metric = hwmp_route_info_get(sdata, mgmt, elems.prep,
+                                                 MPATH_PREP);
+               if (path_metric)
                        hwmp_prep_frame_process(sdata, mgmt, elems.prep,
-                                               last_hop_metric);
+                                               path_metric);
        }
        if (elems.perr) {
                if (elems.perr_len != 15)
index ac843fc..5438d13 100644 (file)
@@ -106,9 +106,7 @@ static u32 mesh_set_short_slot_time(struct ieee80211_sub_if_data *sdata)
                /* (IEEE 802.11-2012 19.4.5) */
                short_slot = true;
                goto out;
-       } else if (band != IEEE80211_BAND_2GHZ ||
-                  (band == IEEE80211_BAND_2GHZ &&
-                   local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
+       } else if (band != IEEE80211_BAND_2GHZ)
                goto out;
 
        for (i = 0; i < sband->n_bitrates; i++)
@@ -394,8 +392,9 @@ static void mesh_sta_info_init(struct ieee80211_sub_if_data *sdata,
        sta->last_rx = jiffies;
 
        /* rates and capabilities don't change during peering */
-       if (sta->plink_state == NL80211_PLINK_ESTAB)
+       if (sta->plink_state == NL80211_PLINK_ESTAB && sta->processed_beacon)
                goto out;
+       sta->processed_beacon = true;
 
        if (sta->sta.supp_rates[band] != rates)
                changed |= IEEE80211_RC_SUPP_RATES_CHANGED;
index 387fe70..235ed68 100644 (file)
@@ -669,10 +669,8 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
        capab = WLAN_CAPABILITY_ESS;
 
        if (sband->band == IEEE80211_BAND_2GHZ) {
-               if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
-                       capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
-               if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
-                       capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
+               capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
+               capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
        }
 
        if (assoc_data->capability & WLAN_CAPABILITY_PRIVACY)
@@ -2521,6 +2519,34 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
        sdata->u.mgd.auth_data = NULL;
 }
 
+static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
+                                        bool assoc)
+{
+       struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
+
+       sdata_assert_lock(sdata);
+
+       if (!assoc) {
+               /*
+                * we are not associated yet, the only timer that could be
+                * running is the timeout for the association response which
+                * which is not relevant anymore.
+                */
+               del_timer_sync(&sdata->u.mgd.timer);
+               sta_info_destroy_addr(sdata, assoc_data->bss->bssid);
+
+               eth_zero_addr(sdata->u.mgd.bssid);
+               ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
+               sdata->u.mgd.flags = 0;
+               mutex_lock(&sdata->local->mtx);
+               ieee80211_vif_release_channel(sdata);
+               mutex_unlock(&sdata->local->mtx);
+       }
+
+       kfree(assoc_data);
+       sdata->u.mgd.assoc_data = NULL;
+}
+
 static void ieee80211_auth_challenge(struct ieee80211_sub_if_data *sdata,
                                     struct ieee80211_mgmt *mgmt, size_t len)
 {
@@ -2713,28 +2739,42 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
                                     struct ieee80211_mgmt *mgmt, size_t len)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
-       const u8 *bssid = NULL;
-       u16 reason_code;
+       u16 reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
 
        sdata_assert_lock(sdata);
 
        if (len < 24 + 2)
                return;
 
-       if (!ifmgd->associated ||
-           !ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid))
-               return;
+       if (ifmgd->associated &&
+           ether_addr_equal(mgmt->bssid, ifmgd->associated->bssid)) {
+               const u8 *bssid = ifmgd->associated->bssid;
 
-       bssid = ifmgd->associated->bssid;
+               sdata_info(sdata, "deauthenticated from %pM (Reason: %u=%s)\n",
+                          bssid, reason_code,
+                          ieee80211_get_reason_code_string(reason_code));
 
-       reason_code = le16_to_cpu(mgmt->u.deauth.reason_code);
+               ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
 
-       sdata_info(sdata, "deauthenticated from %pM (Reason: %u=%s)\n",
-                  bssid, reason_code, ieee80211_get_reason_code_string(reason_code));
+               ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false,
+                                           reason_code);
+               return;
+       }
 
-       ieee80211_set_disassoc(sdata, 0, 0, false, NULL);
+       if (ifmgd->assoc_data &&
+           ether_addr_equal(mgmt->bssid, ifmgd->assoc_data->bss->bssid)) {
+               const u8 *bssid = ifmgd->assoc_data->bss->bssid;
 
-       ieee80211_report_disconnect(sdata, (u8 *)mgmt, len, false, reason_code);
+               sdata_info(sdata,
+                          "deauthenticated from %pM while associating (Reason: %u=%s)\n",
+                          bssid, reason_code,
+                          ieee80211_get_reason_code_string(reason_code));
+
+               ieee80211_destroy_assoc_data(sdata, false);
+
+               cfg80211_rx_mlme_mgmt(sdata->dev, (u8 *)mgmt, len);
+               return;
+       }
 }
 
 
@@ -2814,34 +2854,6 @@ static void ieee80211_get_rates(struct ieee80211_supported_band *sband,
        }
 }
 
-static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
-                                        bool assoc)
-{
-       struct ieee80211_mgd_assoc_data *assoc_data = sdata->u.mgd.assoc_data;
-
-       sdata_assert_lock(sdata);
-
-       if (!assoc) {
-               /*
-                * we are not associated yet, the only timer that could be
-                * running is the timeout for the association response which
-                * which is not relevant anymore.
-                */
-               del_timer_sync(&sdata->u.mgd.timer);
-               sta_info_destroy_addr(sdata, assoc_data->bss->bssid);
-
-               eth_zero_addr(sdata->u.mgd.bssid);
-               ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
-               sdata->u.mgd.flags = 0;
-               mutex_lock(&sdata->local->mtx);
-               ieee80211_vif_release_channel(sdata);
-               mutex_unlock(&sdata->local->mtx);
-       }
-
-       kfree(assoc_data);
-       sdata->u.mgd.assoc_data = NULL;
-}
-
 static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
                                    struct cfg80211_bss *cbss,
                                    struct ieee80211_mgmt *mgmt, size_t len)
@@ -4589,6 +4601,9 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
        eth_zero_addr(ifmgd->bssid);
        ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
        ifmgd->auth_data = NULL;
+       mutex_lock(&sdata->local->mtx);
+       ieee80211_vif_release_channel(sdata);
+       mutex_unlock(&sdata->local->mtx);
  err_free:
        kfree(auth_data);
        return err;
index 7bb6a93..1454c1b 100644 (file)
@@ -6,7 +6,7 @@
  * Copyright 2005, Devicescape Software, Inc.
  * Copyright 2006-2007 Jiri Benc <jbenc@suse.cz>
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
- * Copyright 2013-2014  Intel Mobile Communications GmbH
+ * Copyright 2013-2015  Intel Mobile Communications GmbH
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -69,6 +69,7 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
        int clen, srlen;
        enum nl80211_bss_scan_width scan_width;
        s32 signal = 0;
+       bool signal_valid;
 
        if (local->hw.flags & IEEE80211_HW_SIGNAL_DBM)
                signal = rx_status->signal * 100;
@@ -86,6 +87,11 @@ ieee80211_bss_info_update(struct ieee80211_local *local,
                                               GFP_ATOMIC);
        if (!cbss)
                return NULL;
+       /* In case the signal is invalid update the status */
+       signal_valid = abs(channel->center_freq - cbss->channel->center_freq)
+               <= local->hw.wiphy->max_adj_channel_rssi_comp;
+       if (!signal_valid)
+               rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
 
        bss = (void *)cbss->priv;
 
@@ -257,7 +263,7 @@ static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
        if (test_bit(SCAN_HW_CANCELLED, &local->scanning))
                return false;
 
-       if (local->hw.flags & IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS) {
+       if (local->hw.flags & IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS) {
                for (i = 0; i < req->n_channels; i++) {
                        local->hw_scan_req->req.channels[i] = req->channels[i];
                        bands_used |= BIT(req->channels[i]->band);
@@ -326,7 +332,7 @@ static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
                return;
 
        if (hw_scan && !aborted &&
-           !(local->hw.flags & IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS) &&
+           !(local->hw.flags & IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS) &&
            ieee80211_prep_hw_scan(local)) {
                int rc;
 
@@ -520,7 +526,7 @@ static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
 
                local->hw_scan_ies_bufsize = local->scan_ies_len + req->ie_len;
 
-               if (local->hw.flags & IEEE80211_SINGLE_HW_SCAN_ON_ALL_BANDS) {
+               if (local->hw.flags & IEEE80211_HW_SINGLE_SCAN_ON_ALL_BANDS) {
                        int i, n_bands = 0;
                        u8 bands_counted = 0;
 
index 9bd1e97..226f8ca 100644 (file)
@@ -369,6 +369,8 @@ struct ieee80211_fast_tx {
  * @rx_msdu: MSDUs received from this station, using IEEE80211_NUM_TID
  *     entry for non-QoS frames
  * @fast_tx: TX fastpath information
+ * @processed_beacon: set to true after peer rates and capabilities are
+ *     processed
  */
 struct sta_info {
        /* General information, mostly static */
@@ -473,6 +475,7 @@ struct sta_info {
        enum nl80211_mesh_power_mode local_pm;
        enum nl80211_mesh_power_mode peer_pm;
        enum nl80211_mesh_power_mode nonpeer_pm;
+       bool processed_beacon;
 #endif
 
 #ifdef CONFIG_MAC80211_DEBUGFS
index 4615949..67c4287 100644 (file)
@@ -429,6 +429,74 @@ static void ieee80211_tdls_td_tx_handle(struct ieee80211_local *local,
        }
 }
 
+static struct ieee80211_sub_if_data *
+ieee80211_sdata_from_skb(struct ieee80211_local *local, struct sk_buff *skb)
+{
+       struct ieee80211_sub_if_data *sdata;
+
+       if (skb->dev) {
+               list_for_each_entry_rcu(sdata, &local->interfaces, list) {
+                       if (!sdata->dev)
+                               continue;
+
+                       if (skb->dev == sdata->dev)
+                               return sdata;
+               }
+
+               return NULL;
+       }
+
+       return rcu_dereference(local->p2p_sdata);
+}
+
+static void ieee80211_report_ack_skb(struct ieee80211_local *local,
+                                    struct ieee80211_tx_info *info,
+                                    bool acked, bool dropped)
+{
+       struct sk_buff *skb;
+       unsigned long flags;
+
+       spin_lock_irqsave(&local->ack_status_lock, flags);
+       skb = idr_find(&local->ack_status_frames, info->ack_frame_id);
+       if (skb)
+               idr_remove(&local->ack_status_frames, info->ack_frame_id);
+       spin_unlock_irqrestore(&local->ack_status_lock, flags);
+
+       if (!skb)
+               return;
+
+       if (dropped) {
+               dev_kfree_skb_any(skb);
+               return;
+       }
+
+       if (info->flags & IEEE80211_TX_INTFL_NL80211_FRAME_TX) {
+               u64 cookie = IEEE80211_SKB_CB(skb)->ack.cookie;
+               struct ieee80211_sub_if_data *sdata;
+               struct ieee80211_hdr *hdr = (void *)skb->data;
+
+               rcu_read_lock();
+               sdata = ieee80211_sdata_from_skb(local, skb);
+               if (sdata) {
+                       if (ieee80211_is_nullfunc(hdr->frame_control) ||
+                           ieee80211_is_qos_nullfunc(hdr->frame_control))
+                               cfg80211_probe_status(sdata->dev, hdr->addr1,
+                                                     cookie, acked,
+                                                     GFP_ATOMIC);
+                       else
+                               cfg80211_mgmt_tx_status(&sdata->wdev, cookie,
+                                                       skb->data, skb->len,
+                                                       acked, GFP_ATOMIC);
+               }
+               rcu_read_unlock();
+
+               dev_kfree_skb_any(skb);
+       } else {
+               /* consumes skb */
+               skb_complete_wifi_ack(skb, acked);
+       }
+}
+
 static void ieee80211_report_used_skb(struct ieee80211_local *local,
                                      struct sk_buff *skb, bool dropped)
 {
@@ -439,28 +507,12 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local,
        if (dropped)
                acked = false;
 
-       if (info->flags & (IEEE80211_TX_INTFL_NL80211_FRAME_TX |
-                          IEEE80211_TX_INTFL_MLME_CONN_TX)) {
-               struct ieee80211_sub_if_data *sdata = NULL;
-               struct ieee80211_sub_if_data *iter_sdata;
-               u64 cookie = (unsigned long)skb;
+       if (info->flags & IEEE80211_TX_INTFL_MLME_CONN_TX) {
+               struct ieee80211_sub_if_data *sdata;
 
                rcu_read_lock();
 
-               if (skb->dev) {
-                       list_for_each_entry_rcu(iter_sdata, &local->interfaces,
-                                               list) {
-                               if (!iter_sdata->dev)
-                                       continue;
-
-                               if (skb->dev == iter_sdata->dev) {
-                                       sdata = iter_sdata;
-                                       break;
-                               }
-                       }
-               } else {
-                       sdata = rcu_dereference(local->p2p_sdata);
-               }
+               sdata = ieee80211_sdata_from_skb(local, skb);
 
                if (!sdata) {
                        skb->dev = NULL;
@@ -478,38 +530,14 @@ static void ieee80211_report_used_skb(struct ieee80211_local *local,
                                ieee80211_mgd_conn_tx_status(sdata,
                                                             hdr->frame_control,
                                                             acked);
-               } else if (ieee80211_is_nullfunc(hdr->frame_control) ||
-                          ieee80211_is_qos_nullfunc(hdr->frame_control)) {
-                       cfg80211_probe_status(sdata->dev, hdr->addr1,
-                                             cookie, acked, GFP_ATOMIC);
                } else {
-                       cfg80211_mgmt_tx_status(&sdata->wdev, cookie, skb->data,
-                                               skb->len, acked, GFP_ATOMIC);
+                       /* we assign ack frame ID for the others */
+                       WARN_ON(1);
                }
 
                rcu_read_unlock();
-       }
-
-       if (unlikely(info->ack_frame_id)) {
-               struct sk_buff *ack_skb;
-               unsigned long flags;
-
-               spin_lock_irqsave(&local->ack_status_lock, flags);
-               ack_skb = idr_find(&local->ack_status_frames,
-                                  info->ack_frame_id);
-               if (ack_skb)
-                       idr_remove(&local->ack_status_frames,
-                                  info->ack_frame_id);
-               spin_unlock_irqrestore(&local->ack_status_lock, flags);
-
-               if (ack_skb) {
-                       if (!dropped) {
-                               /* consumes ack_skb */
-                               skb_complete_wifi_ack(ack_skb, acked);
-                       } else {
-                               dev_kfree_skb_any(ack_skb);
-                       }
-               }
+       } else if (info->ack_frame_id) {
+               ieee80211_report_ack_skb(local, info, acked, dropped);
        }
 }
 
index 75e8e3b..28298cc 100644 (file)
@@ -167,23 +167,16 @@ static void ieee80211_tdls_add_bss_coex_ie(struct sk_buff *skb)
 static u16 ieee80211_get_tdls_sta_capab(struct ieee80211_sub_if_data *sdata,
                                        u16 status_code)
 {
-       struct ieee80211_local *local = sdata->local;
-       u16 capab;
-
        /* The capability will be 0 when sending a failure code */
        if (status_code != 0)
                return 0;
 
-       capab = 0;
-       if (ieee80211_get_sdata_band(sdata) != IEEE80211_BAND_2GHZ)
-               return capab;
-
-       if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_SLOT_INCAPABLE))
-               capab |= WLAN_CAPABILITY_SHORT_SLOT_TIME;
-       if (!(local->hw.flags & IEEE80211_HW_2GHZ_SHORT_PREAMBLE_INCAPABLE))
-               capab |= WLAN_CAPABILITY_SHORT_PREAMBLE;
+       if (ieee80211_get_sdata_band(sdata) == IEEE80211_BAND_2GHZ) {
+               return WLAN_CAPABILITY_SHORT_SLOT_TIME |
+                      WLAN_CAPABILITY_SHORT_PREAMBLE;
+       }
 
-       return capab;
+       return 0;
 }
 
 static void ieee80211_tdls_add_link_ie(struct ieee80211_sub_if_data *sdata,
index 8df1342..7fe528a 100644 (file)
@@ -2719,9 +2719,12 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
        if (hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
                tid = skb->priority & IEEE80211_QOS_CTL_TAG1D_MASK;
                tid_tx = rcu_dereference(sta->ampdu_mlme.tid_tx[tid]);
-               if (tid_tx &&
-                   !test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state))
-                       return false;
+               if (tid_tx) {
+                       if (!test_bit(HT_AGG_STATE_OPERATIONAL, &tid_tx->state))
+                               return false;
+                       if (tid_tx->timeout)
+                               tid_tx->last_tx = jiffies;
+               }
        }
 
        /* after this point (skb is modified) we cannot return false */
@@ -2813,17 +2816,9 @@ static bool ieee80211_xmit_fast(struct ieee80211_sub_if_data *sdata,
                switch (fast_tx->key->conf.cipher) {
                case WLAN_CIPHER_SUITE_CCMP:
                case WLAN_CIPHER_SUITE_CCMP_256:
-                       pn = atomic64_inc_return(&fast_tx->key->u.ccmp.tx_pn);
-                       crypto_hdr[0] = pn;
-                       crypto_hdr[1] = pn >> 8;
-                       crypto_hdr[4] = pn >> 16;
-                       crypto_hdr[5] = pn >> 24;
-                       crypto_hdr[6] = pn >> 32;
-                       crypto_hdr[7] = pn >> 40;
-                       break;
                case WLAN_CIPHER_SUITE_GCMP:
                case WLAN_CIPHER_SUITE_GCMP_256:
-                       pn = atomic64_inc_return(&fast_tx->key->u.gcmp.tx_pn);
+                       pn = atomic64_inc_return(&fast_tx->key->conf.tx_pn);
                        crypto_hdr[0] = pn;
                        crypto_hdr[1] = pn >> 8;
                        crypto_hdr[4] = pn >> 16;
index 9d63d93..943f760 100644 (file)
@@ -444,7 +444,7 @@ static int ccmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb,
        hdr = (struct ieee80211_hdr *) pos;
        pos += hdrlen;
 
-       pn64 = atomic64_inc_return(&key->u.ccmp.tx_pn);
+       pn64 = atomic64_inc_return(&key->conf.tx_pn);
 
        pn[5] = pn64;
        pn[4] = pn64 >> 8;
@@ -670,7 +670,7 @@ static int gcmp_encrypt_skb(struct ieee80211_tx_data *tx, struct sk_buff *skb)
        hdr = (struct ieee80211_hdr *)pos;
        pos += hdrlen;
 
-       pn64 = atomic64_inc_return(&key->u.gcmp.tx_pn);
+       pn64 = atomic64_inc_return(&key->conf.tx_pn);
 
        pn[5] = pn64;
        pn[4] = pn64 >> 8;
@@ -940,7 +940,7 @@ ieee80211_crypto_aes_cmac_encrypt(struct ieee80211_tx_data *tx)
        mmie->key_id = cpu_to_le16(key->conf.keyidx);
 
        /* PN = PN + 1 */
-       pn64 = atomic64_inc_return(&key->u.aes_cmac.tx_pn);
+       pn64 = atomic64_inc_return(&key->conf.tx_pn);
 
        bip_ipn_set64(mmie->sequence_number, pn64);
 
@@ -984,7 +984,7 @@ ieee80211_crypto_aes_cmac_256_encrypt(struct ieee80211_tx_data *tx)
        mmie->key_id = cpu_to_le16(key->conf.keyidx);
 
        /* PN = PN + 1 */
-       pn64 = atomic64_inc_return(&key->u.aes_cmac.tx_pn);
+       pn64 = atomic64_inc_return(&key->conf.tx_pn);
 
        bip_ipn_set64(mmie->sequence_number, pn64);
 
@@ -1129,7 +1129,7 @@ ieee80211_crypto_aes_gmac_encrypt(struct ieee80211_tx_data *tx)
        mmie->key_id = cpu_to_le16(key->conf.keyidx);
 
        /* PN = PN + 1 */
-       pn64 = atomic64_inc_return(&key->u.aes_gmac.tx_pn);
+       pn64 = atomic64_inc_return(&key->conf.tx_pn);
 
        bip_ipn_set64(mmie->sequence_number, pn64);