Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
authorJohn W. Linville <linville@tuxdriver.com>
Mon, 8 Sep 2014 15:14:56 +0000 (11:14 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 8 Sep 2014 15:14:56 +0000 (11:14 -0400)
13 files changed:
1  2 
drivers/net/wireless/iwlwifi/Kconfig
drivers/net/wireless/iwlwifi/iwl-7000.c
drivers/net/wireless/iwlwifi/iwl-8000.c
include/net/bluetooth/hci_core.h
net/bluetooth/hci_core.c
net/bluetooth/hci_event.c
net/ieee802154/6lowpan_rtnl.c
net/mac80211/chan.c
net/mac80211/debugfs_sta.c
net/mac80211/mesh_plink.c
net/mac80211/mlme.c
net/mac80211/sta_info.c
net/mac802154/wpan.c

index 760e96f63bb02ed2bd19c1be6582a27a345207c0,824f5e2877835d8a829f643d8b15cf1ed85e2572..267e48a2915e7885993979337619d777c8cb74c8
@@@ -51,7 -51,6 +51,6 @@@ config IWLWIFI_LED
  
  config IWLDVM
        tristate "Intel Wireless WiFi DVM Firmware support"
-       depends on m
        default IWLWIFI
        help
          This is the driver that supports the DVM firmware which is
@@@ -60,7 -59,6 +59,6 @@@
  
  config IWLMVM
        tristate "Intel Wireless WiFi MVM Firmware support"
-       depends on m
        help
          This is the driver that supports the MVM firmware which is
          currently only available for 7260 and 3160 devices.
@@@ -87,16 -85,6 +85,16 @@@ config IWLWIFI_BCAST_FILTERIN
          If unsure, don't enable this option, as some programs might
          expect incoming broadcasts for their normal operations.
  
 +config IWLWIFI_UAPSD
 +      bool "enable U-APSD by default"
 +      depends on IWLMVM
 +      help
 +        Say Y here to enable U-APSD by default. This may cause
 +        interoperability problems with some APs, manifesting in lower than
 +        expected throughput due to those APs not enabling aggregation
 +
 +        If unsure, say N.
 +
  menu "Debugging Options"
  
  config IWLWIFI_DEBUG
index 446654aed0177c6c0f1bb1410d0b50b2cfd40072,d67a37a786aa136a20b192f0a7712992ffdb527d..7e26d0dbfcf7a191933df3e0a5468560dc2fd587
@@@ -6,7 -6,6 +6,7 @@@
   * GPL LICENSE SUMMARY
   *
   * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
 + * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of version 2 of the GNU General Public License as
@@@ -32,7 -31,6 +32,7 @@@
   * BSD LICENSE
   *
   * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved.
 + * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
@@@ -69,8 -67,8 +69,8 @@@
  #include "iwl-agn-hw.h"
  
  /* Highest firmware API version supported */
- #define IWL7260_UCODE_API_MAX 9
- #define IWL3160_UCODE_API_MAX 9
+ #define IWL7260_UCODE_API_MAX 10
+ #define IWL3160_UCODE_API_MAX 10
  
  /* Oldest version we won't warn about */
  #define IWL7260_UCODE_API_OK  9
index 90388e70db9b5f230e3f6e0c89931b6fefb80033,e93c6972290b84de3cf26214ca6894d0db0c4f79..23a67bfc086f3e35c774d4027d9b9b8f3c35b273
@@@ -6,7 -6,6 +6,7 @@@
   * GPL LICENSE SUMMARY
   *
   * Copyright(c) 2014 Intel Corporation. All rights reserved.
 + * Copyright(c) 2014 Intel Mobile Communications GmbH
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of version 2 of the GNU General Public License as
@@@ -32,7 -31,6 +32,7 @@@
   * BSD LICENSE
   *
   * Copyright(c) 2014 Intel Corporation. All rights reserved.
 + * Copyright(c) 2014 Intel Mobile Communications GmbH
   * All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
@@@ -69,7 -67,7 +69,7 @@@
  #include "iwl-agn-hw.h"
  
  /* Highest firmware API version supported */
- #define IWL8000_UCODE_API_MAX 9
+ #define IWL8000_UCODE_API_MAX 10
  
  /* Oldest version we won't warn about */
  #define IWL8000_UCODE_API_OK  8
index 5f0b77b71b45b79f6f2abed9219769eeefb4e4f3,6f884e6c731e41daccdf4119cb1f0f8a4ee9335f..b0ded1333865309ecd9e771bf33ee872c3abd56e
@@@ -302,7 -302,7 +302,7 @@@ struct hci_dev 
        __u32                   req_status;
        __u32                   req_result;
  
 -      struct crypto_blkcipher *tfm_aes;
 +      void                    *smp_data;
  
        struct discovery_state  discovery;
        struct hci_conn_hash    conn_hash;
@@@ -464,6 -464,8 +464,8 @@@ struct hci_conn_params 
                HCI_AUTO_CONN_ALWAYS,
                HCI_AUTO_CONN_LINK_LOSS,
        } auto_connect;
+       struct hci_conn *conn;
  };
  
  extern struct list_head hci_dev_list;
@@@ -968,9 -970,6 +970,9 @@@ void hci_conn_del_sysfs(struct hci_con
  #define lmp_host_le_capable(dev)   (!!((dev)->features[1][0] & LMP_HOST_LE))
  #define lmp_host_le_br_capable(dev) (!!((dev)->features[1][0] & LMP_HOST_LE_BREDR))
  
 +#define hdev_is_powered(hdev) (test_bit(HCI_UP, &hdev->flags) && \
 +                              !test_bit(HCI_AUTO_OFF, &hdev->dev_flags))
 +
  /* ----- HCI protocols ----- */
  #define HCI_PROTO_DEFER             0x01
  
@@@ -1259,8 -1258,6 +1261,8 @@@ bool hci_req_pending(struct hci_dev *hd
  void hci_req_add_le_scan_disable(struct hci_request *req);
  void hci_req_add_le_passive_scan(struct hci_request *req);
  
 +void hci_update_page_scan(struct hci_dev *hdev, struct hci_request *req);
 +
  struct sk_buff *__hci_cmd_sync(struct hci_dev *hdev, u16 opcode, u32 plen,
                               const void *param, u32 timeout);
  struct sk_buff *__hci_cmd_sync_ev(struct hci_dev *hdev, u16 opcode, u32 plen,
@@@ -1356,7 -1353,6 +1358,7 @@@ void mgmt_device_found(struct hci_dev *
  void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type,
                      u8 addr_type, s8 rssi, u8 *name, u8 name_len);
  void mgmt_discovering(struct hci_dev *hdev, u8 discovering);
 +bool mgmt_powering_down(struct hci_dev *hdev);
  void mgmt_new_ltk(struct hci_dev *hdev, struct smp_ltk *key, bool persistent);
  void mgmt_new_irk(struct hci_dev *hdev, struct smp_irk *irk);
  void mgmt_new_csrk(struct hci_dev *hdev, struct smp_csrk *csrk,
diff --combined net/bluetooth/hci_core.c
index abeb5e47311e47bd85439d1842349e135bbb3abb,1d9c29a00568d9b6ac3eea93848ec6637e5a5a5d..9b7145959a49e7ea7b52cf7fb11e9a8f68fa7346
@@@ -1898,8 -1898,6 +1898,8 @@@ static int __hci_init(struct hci_dev *h
                debugfs_create_u16("discov_interleaved_timeout", 0644,
                                   hdev->debugfs,
                                   &hdev->discov_interleaved_timeout);
 +
 +              smp_register(hdev);
        }
  
        return 0;
@@@ -2538,8 -2536,13 +2538,13 @@@ static void hci_pend_le_actions_clear(s
  {
        struct hci_conn_params *p;
  
-       list_for_each_entry(p, &hdev->le_conn_params, list)
+       list_for_each_entry(p, &hdev->le_conn_params, list) {
+               if (p->conn) {
+                       hci_conn_drop(p->conn);
+                       p->conn = NULL;
+               }
                list_del_init(&p->action);
+       }
  
        BT_DBG("All LE pending actions cleared");
  }
@@@ -2580,8 -2583,8 +2585,8 @@@ static int hci_dev_do_close(struct hci_
  
        hci_dev_lock(hdev);
        hci_inquiry_cache_flush(hdev);
-       hci_conn_hash_flush(hdev);
        hci_pend_le_actions_clear(hdev);
+       hci_conn_hash_flush(hdev);
        hci_dev_unlock(hdev);
  
        hci_notify(hdev, HCI_DEV_DOWN);
@@@ -3235,7 -3238,7 +3240,7 @@@ struct smp_irk *hci_find_irk_by_rpa(str
        }
  
        list_for_each_entry(irk, &hdev->identity_resolving_keys, list) {
 -              if (smp_irk_matches(hdev->tfm_aes, irk->val, rpa)) {
 +              if (smp_irk_matches(hdev, irk->val, rpa)) {
                        bacpy(&irk->rpa, rpa);
                        return irk;
                }
@@@ -3729,6 -3732,9 +3734,9 @@@ void hci_conn_params_del(struct hci_de
        if (!params)
                return;
  
+       if (params->conn)
+               hci_conn_drop(params->conn);
        list_del(&params->action);
        list_del(&params->list);
        kfree(params);
@@@ -3759,6 -3765,8 +3767,8 @@@ void hci_conn_params_clear_all(struct h
        struct hci_conn_params *params, *tmp;
  
        list_for_each_entry_safe(params, tmp, &hdev->le_conn_params, list) {
+               if (params->conn)
+                       hci_conn_drop(params->conn);
                list_del(&params->action);
                list_del(&params->list);
                kfree(params);
@@@ -3884,7 -3892,7 +3894,7 @@@ int hci_update_random_address(struct hc
                    !bacmp(&hdev->random_addr, &hdev->rpa))
                        return 0;
  
 -              err = smp_generate_rpa(hdev->tfm_aes, hdev->irk, &hdev->rpa);
 +              err = smp_generate_rpa(hdev, hdev->irk, &hdev->rpa);
                if (err < 0) {
                        BT_ERR("%s failed to generate new RPA", hdev->name);
                        return err;
@@@ -4092,9 -4100,18 +4102,9 @@@ int hci_register_dev(struct hci_dev *hd
  
        dev_set_name(&hdev->dev, "%s", hdev->name);
  
 -      hdev->tfm_aes = crypto_alloc_blkcipher("ecb(aes)", 0,
 -                                             CRYPTO_ALG_ASYNC);
 -      if (IS_ERR(hdev->tfm_aes)) {
 -              BT_ERR("Unable to create crypto context");
 -              error = PTR_ERR(hdev->tfm_aes);
 -              hdev->tfm_aes = NULL;
 -              goto err_wqueue;
 -      }
 -
        error = device_add(&hdev->dev);
        if (error < 0)
 -              goto err_tfm;
 +              goto err_wqueue;
  
        hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev,
                                    RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops,
  
        return id;
  
 -err_tfm:
 -      crypto_free_blkcipher(hdev->tfm_aes);
  err_wqueue:
        destroy_workqueue(hdev->workqueue);
        destroy_workqueue(hdev->req_workqueue);
@@@ -4187,7 -4206,8 +4197,7 @@@ void hci_unregister_dev(struct hci_dev 
                rfkill_destroy(hdev->rfkill);
        }
  
 -      if (hdev->tfm_aes)
 -              crypto_free_blkcipher(hdev->tfm_aes);
 +      smp_unregister(hdev);
  
        device_del(&hdev->dev);
  
@@@ -5670,52 -5690,3 +5680,52 @@@ void hci_update_background_scan(struct 
        if (err)
                BT_ERR("Failed to run HCI request: err %d", err);
  }
 +
 +static bool disconnected_whitelist_entries(struct hci_dev *hdev)
 +{
 +      struct bdaddr_list *b;
 +
 +      list_for_each_entry(b, &hdev->whitelist, list) {
 +              struct hci_conn *conn;
 +
 +              conn = hci_conn_hash_lookup_ba(hdev, ACL_LINK, &b->bdaddr);
 +              if (!conn)
 +                      return true;
 +
 +              if (conn->state != BT_CONNECTED && conn->state != BT_CONFIG)
 +                      return true;
 +      }
 +
 +      return false;
 +}
 +
 +void hci_update_page_scan(struct hci_dev *hdev, struct hci_request *req)
 +{
 +      u8 scan;
 +
 +      if (!test_bit(HCI_BREDR_ENABLED, &hdev->dev_flags))
 +              return;
 +
 +      if (!hdev_is_powered(hdev))
 +              return;
 +
 +      if (mgmt_powering_down(hdev))
 +              return;
 +
 +      if (test_bit(HCI_CONNECTABLE, &hdev->dev_flags) ||
 +          disconnected_whitelist_entries(hdev))
 +              scan = SCAN_PAGE;
 +      else
 +              scan = SCAN_DISABLED;
 +
 +      if (test_bit(HCI_PSCAN, &hdev->flags) == !!(scan & SCAN_PAGE))
 +              return;
 +
 +      if (test_bit(HCI_DISCOVERABLE, &hdev->dev_flags))
 +              scan |= SCAN_INQUIRY;
 +
 +      if (req)
 +              hci_req_add(req, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
 +      else
 +              hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
 +}
index da7ab6b9bb691383d977e039b39e94f8714507d4,a6000823f0ff34d938631bed2e39a6b17a26ac13..3a99f30a3317e91955f29d6c1d783f02ece75398
@@@ -2071,8 -2071,6 +2071,8 @@@ static void hci_conn_complete_evt(struc
                        cp.handle = ev->handle;
                        hci_send_cmd(hdev, HCI_OP_READ_REMOTE_FEATURES,
                                     sizeof(cp), &cp);
 +
 +                      hci_update_page_scan(hdev, NULL);
                }
  
                /* Set packet type for incoming connection */
@@@ -2249,12 -2247,9 +2249,12 @@@ static void hci_disconn_complete_evt(st
        mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type,
                                reason, mgmt_connected);
  
 -      if (conn->type == ACL_LINK &&
 -          test_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
 -              hci_remove_link_key(hdev, &conn->dst);
 +      if (conn->type == ACL_LINK) {
 +              if (test_bit(HCI_CONN_FLUSH_KEY, &conn->flags))
 +                      hci_remove_link_key(hdev, &conn->dst);
 +
 +              hci_update_page_scan(hdev, NULL);
 +      }
  
        params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
        if (params) {
@@@ -4226,8 -4221,13 +4226,13 @@@ static void hci_le_conn_complete_evt(st
        hci_proto_connect_cfm(conn, ev->status);
  
        params = hci_conn_params_lookup(hdev, &conn->dst, conn->dst_type);
-       if (params)
+       if (params) {
                list_del_init(&params->action);
+               if (params->conn) {
+                       hci_conn_drop(params->conn);
+                       params->conn = NULL;
+               }
+       }
  
  unlock:
        hci_update_background_scan(hdev);
@@@ -4309,8 -4309,16 +4314,16 @@@ static void check_pending_le_conn(struc
  
        conn = hci_connect_le(hdev, addr, addr_type, BT_SECURITY_LOW,
                              HCI_LE_AUTOCONN_TIMEOUT, HCI_ROLE_MASTER);
-       if (!IS_ERR(conn))
+       if (!IS_ERR(conn)) {
+               /* Store the pointer since we don't really have any
+                * other owner of the object besides the params that
+                * triggered it. This way we can abort the connection if
+                * the parameters get removed and keep the reference
+                * count consistent once the connection is established.
+                */
+               params->conn = conn;
                return;
+       }
  
        switch (PTR_ERR(conn)) {
        case -EBUSY:
index 509d7a625a4bf056049e3a9fb543ac3ec02f93f8,6591d27e53a43413656a18a6eedb25d7bb5fe034..5e788cdc499a34c5a156e65e4afeda2927587118
@@@ -77,6 -77,14 +77,6 @@@ lowpan_dev_info *lowpan_dev_info(const 
        return netdev_priv(dev);
  }
  
 -static inline void lowpan_address_flip(u8 *src, u8 *dest)
 -{
 -      int i;
 -
 -      for (i = 0; i < IEEE802154_ADDR_LEN; i++)
 -              (dest)[IEEE802154_ADDR_LEN - i - 1] = (src)[i];
 -}
 -
  static int lowpan_header_create(struct sk_buff *skb, struct net_device *dev,
                                unsigned short type, const void *_daddr,
                                const void *_saddr, unsigned int len)
@@@ -238,7 -246,7 +238,7 @@@ lowpan_alloc_frag(struct sk_buff *skb, 
                        return ERR_PTR(-rc);
                }
        } else {
-               frag = ERR_PTR(ENOMEM);
+               frag = ERR_PTR(-ENOMEM);
        }
  
        return frag;
@@@ -429,7 -437,7 +429,7 @@@ static void lowpan_setup(struct net_dev
        /* Frame Control + Sequence Number + Address fields + Security Header */
        dev->hard_header_len    = 2 + 1 + 20 + 14;
        dev->needed_tailroom    = 2; /* FCS */
-       dev->mtu                = 1281;
+       dev->mtu                = IPV6_MIN_MTU;
        dev->tx_queue_len       = 0;
        dev->flags              = IFF_BROADCAST | IFF_MULTICAST;
        dev->watchdog_timeo     = 0;
diff --combined net/mac80211/chan.c
index 0da6f3a027e7e9cf18163238c4017972c31d246a,399ad82c997f99c33833c03c67e6acddf7019b6f..4c74e8da64b909cc36befe4c5ecb29af5ff7629e
@@@ -541,18 -541,20 +541,20 @@@ static void ieee80211_recalc_chanctx_ch
                        continue;
                if (rcu_access_pointer(sdata->vif.chanctx_conf) != conf)
                        continue;
+               if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+                       continue;
  
                if (!compat)
                        compat = &sdata->vif.bss_conf.chandef;
  
                compat = cfg80211_chandef_compatible(
                                &sdata->vif.bss_conf.chandef, compat);
 -              if (!compat)
 +              if (WARN_ON_ONCE(!compat))
                        break;
        }
        rcu_read_unlock();
  
 -      if (WARN_ON_ONCE(!compat))
 +      if (!compat)
                return;
  
        ieee80211_change_chanctx(local, ctx, compat);
@@@ -637,6 -639,41 +639,6 @@@ out
        return ret;
  }
  
 -static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
 -{
 -      struct ieee80211_local *local = sdata->local;
 -      struct ieee80211_chanctx_conf *conf;
 -      struct ieee80211_chanctx *ctx;
 -      bool use_reserved_switch = false;
 -
 -      lockdep_assert_held(&local->chanctx_mtx);
 -
 -      conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
 -                                       lockdep_is_held(&local->chanctx_mtx));
 -      if (!conf)
 -              return;
 -
 -      ctx = container_of(conf, struct ieee80211_chanctx, conf);
 -
 -      if (sdata->reserved_chanctx) {
 -              if (sdata->reserved_chanctx->replace_state ==
 -                  IEEE80211_CHANCTX_REPLACES_OTHER &&
 -                  ieee80211_chanctx_num_reserved(local,
 -                                                 sdata->reserved_chanctx) > 1)
 -                      use_reserved_switch = true;
 -
 -              ieee80211_vif_unreserve_chanctx(sdata);
 -      }
 -
 -      ieee80211_assign_vif_chanctx(sdata, NULL);
 -      if (ieee80211_chanctx_refcount(local, ctx) == 0)
 -              ieee80211_free_chanctx(local, ctx);
 -
 -      /* Unreserving may ready an in-place reservation. */
 -      if (use_reserved_switch)
 -              ieee80211_vif_use_reserved_switch(local);
 -}
 -
  void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
                                   struct ieee80211_chanctx *chanctx)
  {
        drv_change_chanctx(local, chanctx, IEEE80211_CHANCTX_CHANGE_RX_CHAINS);
  }
  
 -int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
 -                            const struct cfg80211_chan_def *chandef,
 -                            enum ieee80211_chanctx_mode mode)
 -{
 -      struct ieee80211_local *local = sdata->local;
 -      struct ieee80211_chanctx *ctx;
 -      u8 radar_detect_width = 0;
 -      int ret;
 -
 -      lockdep_assert_held(&local->mtx);
 -
 -      WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
 -
 -      mutex_lock(&local->chanctx_mtx);
 -
 -      ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
 -                                          chandef,
 -                                          sdata->wdev.iftype);
 -      if (ret < 0)
 -              goto out;
 -      if (ret > 0)
 -              radar_detect_width = BIT(chandef->width);
 -
 -      sdata->radar_required = ret;
 -
 -      ret = ieee80211_check_combinations(sdata, chandef, mode,
 -                                         radar_detect_width);
 -      if (ret < 0)
 -              goto out;
 -
 -      __ieee80211_vif_release_channel(sdata);
 -
 -      ctx = ieee80211_find_chanctx(local, chandef, mode);
 -      if (!ctx)
 -              ctx = ieee80211_new_chanctx(local, chandef, mode);
 -      if (IS_ERR(ctx)) {
 -              ret = PTR_ERR(ctx);
 -              goto out;
 -      }
 -
 -      sdata->vif.bss_conf.chandef = *chandef;
 -
 -      ret = ieee80211_assign_vif_chanctx(sdata, ctx);
 -      if (ret) {
 -              /* if assign fails refcount stays the same */
 -              if (ieee80211_chanctx_refcount(local, ctx) == 0)
 -                      ieee80211_free_chanctx(local, ctx);
 -              goto out;
 -      }
 -
 -      ieee80211_recalc_smps_chanctx(local, ctx);
 -      ieee80211_recalc_radar_chanctx(local, ctx);
 - out:
 -      mutex_unlock(&local->chanctx_mtx);
 -      return ret;
 -}
 -
  static void
  __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
                                      bool clear)
@@@ -1175,7 -1269,8 +1177,7 @@@ err
        return err;
  }
  
 -int
 -ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
 +static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
  {
        struct ieee80211_sub_if_data *sdata, *sdata_tmp;
        struct ieee80211_chanctx *ctx, *ctx_tmp, *old_ctx;
        return err;
  }
  
 +static void __ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata)
 +{
 +      struct ieee80211_local *local = sdata->local;
 +      struct ieee80211_chanctx_conf *conf;
 +      struct ieee80211_chanctx *ctx;
 +      bool use_reserved_switch = false;
 +
 +      lockdep_assert_held(&local->chanctx_mtx);
 +
 +      conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
 +                                       lockdep_is_held(&local->chanctx_mtx));
 +      if (!conf)
 +              return;
 +
 +      ctx = container_of(conf, struct ieee80211_chanctx, conf);
 +
 +      if (sdata->reserved_chanctx) {
 +              if (sdata->reserved_chanctx->replace_state ==
 +                  IEEE80211_CHANCTX_REPLACES_OTHER &&
 +                  ieee80211_chanctx_num_reserved(local,
 +                                                 sdata->reserved_chanctx) > 1)
 +                      use_reserved_switch = true;
 +
 +              ieee80211_vif_unreserve_chanctx(sdata);
 +      }
 +
 +      ieee80211_assign_vif_chanctx(sdata, NULL);
 +      if (ieee80211_chanctx_refcount(local, ctx) == 0)
 +              ieee80211_free_chanctx(local, ctx);
 +
 +      /* Unreserving may ready an in-place reservation. */
 +      if (use_reserved_switch)
 +              ieee80211_vif_use_reserved_switch(local);
 +}
 +
 +int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
 +                            const struct cfg80211_chan_def *chandef,
 +                            enum ieee80211_chanctx_mode mode)
 +{
 +      struct ieee80211_local *local = sdata->local;
 +      struct ieee80211_chanctx *ctx;
 +      u8 radar_detect_width = 0;
 +      int ret;
 +
 +      lockdep_assert_held(&local->mtx);
 +
 +      WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));
 +
 +      mutex_lock(&local->chanctx_mtx);
 +
 +      ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
 +                                          chandef,
 +                                          sdata->wdev.iftype);
 +      if (ret < 0)
 +              goto out;
 +      if (ret > 0)
 +              radar_detect_width = BIT(chandef->width);
 +
 +      sdata->radar_required = ret;
 +
 +      ret = ieee80211_check_combinations(sdata, chandef, mode,
 +                                         radar_detect_width);
 +      if (ret < 0)
 +              goto out;
 +
 +      __ieee80211_vif_release_channel(sdata);
 +
 +      ctx = ieee80211_find_chanctx(local, chandef, mode);
 +      if (!ctx)
 +              ctx = ieee80211_new_chanctx(local, chandef, mode);
 +      if (IS_ERR(ctx)) {
 +              ret = PTR_ERR(ctx);
 +              goto out;
 +      }
 +
 +      sdata->vif.bss_conf.chandef = *chandef;
 +
 +      ret = ieee80211_assign_vif_chanctx(sdata, ctx);
 +      if (ret) {
 +              /* if assign fails refcount stays the same */
 +              if (ieee80211_chanctx_refcount(local, ctx) == 0)
 +                      ieee80211_free_chanctx(local, ctx);
 +              goto out;
 +      }
 +
 +      ieee80211_recalc_smps_chanctx(local, ctx);
 +      ieee80211_recalc_radar_chanctx(local, ctx);
 + out:
 +      mutex_unlock(&local->chanctx_mtx);
 +      return ret;
 +}
 +
  int ieee80211_vif_use_reserved_context(struct ieee80211_sub_if_data *sdata)
  {
        struct ieee80211_local *local = sdata->local;
index 4a20fb8f1e23f767139247133e605dbc00cc1997,86173c0de40e91d658e883514232c720a4c51e0e..33eb4a43a2f342d7c8af78908498020da753b6e2
@@@ -77,8 -77,7 +77,8 @@@ static ssize_t sta_flags_read(struct fi
                            TEST(AUTH), TEST(ASSOC), TEST(PS_STA),
                            TEST(PS_DRIVER), TEST(AUTHORIZED),
                            TEST(SHORT_PREAMBLE),
 -                          TEST(WME), TEST(WDS), TEST(CLEAR_PS_FILT),
 +                          sta->sta.wme ? "WME\n" : "",
 +                          TEST(WDS), TEST(CLEAR_PS_FILT),
                            TEST(MFP), TEST(BLOCK_BA), TEST(PSPOLL),
                            TEST(UAPSD), TEST(SP), TEST(TDLS_PEER),
                            TEST(TDLS_PEER_AUTH), TEST(4ADDR_EVENT),
@@@ -168,7 -167,7 +168,7 @@@ static ssize_t sta_agg_status_read(stru
        p += scnprintf(p, sizeof(buf) + buf - p, "next dialog_token: %#02x\n",
                        sta->ampdu_mlme.dialog_token_allocator + 1);
        p += scnprintf(p, sizeof(buf) + buf - p,
-                      "TID\t\tRX active\tDTKN\tSSN\t\tTX\tDTKN\tpending\n");
+                      "TID\t\tRX\tDTKN\tSSN\t\tTX\tDTKN\tpending\n");
  
        for (i = 0; i < IEEE80211_NUM_TIDS; i++) {
                tid_rx = rcu_dereference(sta->ampdu_mlme.tid_rx[i]);
index 8f0887fc7128c4e04e0e7b4d5e4f1dd7445a40f5,c47194d2714933bd8e1dc3658ffd165cd50a5a4a..b488e1859b18e8ed7797cffbb5ab2319138fdb28
@@@ -431,12 -431,14 +431,12 @@@ __mesh_sta_info_alloc(struct ieee80211_
                return NULL;
  
        sta->plink_state = NL80211_PLINK_LISTEN;
 +      sta->sta.wme = true;
  
        sta_info_pre_move_state(sta, IEEE80211_STA_AUTH);
        sta_info_pre_move_state(sta, IEEE80211_STA_ASSOC);
        sta_info_pre_move_state(sta, IEEE80211_STA_AUTHORIZED);
  
 -      set_sta_flag(sta, WLAN_STA_WME);
 -      sta->sta.wme = true;
 -
        return sta;
  }
  
@@@ -957,7 -959,8 +957,8 @@@ mesh_plink_get_event(struct ieee80211_s
                if (!matches_local)
                        event = CNF_RJCT;
                if (!mesh_plink_free_count(sdata) ||
-                   (sta->llid != llid || sta->plid != plid))
+                   sta->llid != llid ||
+                   (sta->plid && sta->plid != plid))
                        event = CNF_IGNR;
                else
                        event = CNF_ACPT;
@@@ -1001,6 -1004,7 +1002,6 @@@ mesh_process_plink_frame(struct ieee802
        enum ieee80211_self_protected_actioncode ftype;
        u32 changed = 0;
        u8 ie_len = elems->peering_len;
 -      __le16 _plid, _llid;
        u16 plid, llid = 0;
  
        if (!elems->peering) {
        /* Note the lines below are correct, the llid in the frame is the plid
         * from the point of view of this host.
         */
 -      memcpy(&_plid, PLINK_GET_LLID(elems->peering), sizeof(__le16));
 -      plid = le16_to_cpu(_plid);
 +      plid = get_unaligned_le16(PLINK_GET_LLID(elems->peering));
        if (ftype == WLAN_SP_MESH_PEERING_CONFIRM ||
 -          (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8)) {
 -              memcpy(&_llid, PLINK_GET_PLID(elems->peering), sizeof(__le16));
 -              llid = le16_to_cpu(_llid);
 -      }
 +          (ftype == WLAN_SP_MESH_PEERING_CLOSE && ie_len == 8))
 +              llid = get_unaligned_le16(PLINK_GET_PLID(elems->peering));
  
        /* WARNING: Only for sta pointer, is dropped & re-acquired */
        rcu_read_lock();
                goto unlock_rcu;
        }
  
+       /* 802.11-2012 13.3.7.2 - update plid on CNF if not set */
+       if (!sta->plid && event == CNF_ACPT)
+               sta->plid = plid;
        changed |= mesh_plink_fsm(sdata, sta, event);
  
  unlock_rcu:
diff --combined net/mac80211/mlme.c
index 29fe91d6a094fc72a54ccba3bbe3d377416672a7,b82a12a9f0f110779756027944dce6293d1387fb..8a73de6a5f5b46a5659a81159f6a7e78de376dc2
@@@ -149,7 -149,6 +149,7 @@@ static u3
  ieee80211_determine_chantype(struct ieee80211_sub_if_data *sdata,
                             struct ieee80211_supported_band *sband,
                             struct ieee80211_channel *channel,
 +                           const struct ieee80211_ht_cap *ht_cap,
                             const struct ieee80211_ht_operation *ht_oper,
                             const struct ieee80211_vht_operation *vht_oper,
                             struct cfg80211_chan_def *chandef, bool tracking)
        chandef->center_freq1 = channel->center_freq;
        chandef->center_freq2 = 0;
  
 -      if (!ht_oper || !sband->ht_cap.ht_supported) {
 +      if (!ht_cap || !ht_oper || !sband->ht_cap.ht_supported) {
                ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
                goto out;
        }
  
        chandef->width = NL80211_CHAN_WIDTH_20;
  
 +      if (!(ht_cap->cap_info &
 +            cpu_to_le16(IEEE80211_HT_CAP_SUP_WIDTH_20_40))) {
 +              ret = IEEE80211_STA_DISABLE_40MHZ | IEEE80211_STA_DISABLE_VHT;
 +              goto out;
 +      }
 +
        ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan,
                                                  channel->band);
        /* check that channel matches the right operating channel */
@@@ -335,7 -328,6 +335,7 @@@ out
  
  static int ieee80211_config_bw(struct ieee80211_sub_if_data *sdata,
                               struct sta_info *sta,
 +                             const struct ieee80211_ht_cap *ht_cap,
                               const struct ieee80211_ht_operation *ht_oper,
                               const struct ieee80211_vht_operation *vht_oper,
                               const u8 *bssid, u32 *changed)
        sband = local->hw.wiphy->bands[chan->band];
  
        /* calculate new channel (type) based on HT/VHT operation IEs */
 -      flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper,
 -                                           vht_oper, &chandef, true);
 +      flags = ieee80211_determine_chantype(sdata, sband, chan,
 +                                           ht_cap, ht_oper, vht_oper,
 +                                           &chandef, true);
  
        /*
         * Downgrade the new channel if we associated with restricted
@@@ -2686,7 -2677,8 +2686,7 @@@ static bool ieee80211_assoc_success(str
        if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED)
                set_sta_flag(sta, WLAN_STA_MFP);
  
 -      if (elems.wmm_param)
 -              set_sta_flag(sta, WLAN_STA_WME);
 +      sta->sta.wme = elems.wmm_param;
  
        err = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
        if (!err && !(ifmgd->flags & IEEE80211_STA_CONTROL_PORT))
@@@ -3182,8 -3174,7 +3182,8 @@@ static void ieee80211_rx_mgmt_beacon(st
        mutex_lock(&local->sta_mtx);
        sta = sta_info_get(sdata, bssid);
  
 -      if (ieee80211_config_bw(sdata, sta, elems.ht_operation,
 +      if (ieee80211_config_bw(sdata, sta,
 +                              elems.ht_cap_elem, elems.ht_operation,
                                elems.vht_operation, bssid, &changed)) {
                mutex_unlock(&local->sta_mtx);
                ieee80211_set_disassoc(sdata, IEEE80211_STYPE_DEAUTH,
@@@ -3817,7 -3808,6 +3817,7 @@@ static int ieee80211_prep_channel(struc
  {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 +      const struct ieee80211_ht_cap *ht_cap = NULL;
        const struct ieee80211_ht_operation *ht_oper = NULL;
        const struct ieee80211_vht_operation *vht_oper = NULL;
        struct ieee80211_supported_band *sband;
  
        if (!(ifmgd->flags & IEEE80211_STA_DISABLE_HT) &&
            sband->ht_cap.ht_supported) {
 -              const u8 *ht_oper_ie, *ht_cap;
 +              const u8 *ht_oper_ie, *ht_cap_ie;
  
                ht_oper_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_OPERATION);
                if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper))
                        ht_oper = (void *)(ht_oper_ie + 2);
  
 -              ht_cap = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY);
 -              if (!ht_cap || ht_cap[1] < sizeof(struct ieee80211_ht_cap)) {
 +              ht_cap_ie = ieee80211_bss_get_ie(cbss, WLAN_EID_HT_CAPABILITY);
 +              if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap))
 +                      ht_cap = (void *)(ht_cap_ie + 2);
 +
 +              if (!ht_cap) {
                        ifmgd->flags |= IEEE80211_STA_DISABLE_HT;
                        ht_oper = NULL;
                }
  
        ifmgd->flags |= ieee80211_determine_chantype(sdata, sband,
                                                     cbss->channel,
 -                                                   ht_oper, vht_oper,
 +                                                   ht_cap, ht_oper, vht_oper,
                                                     &chandef, false);
  
        sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss),
@@@ -4389,8 -4376,7 +4389,7 @@@ int ieee80211_mgd_assoc(struct ieee8021
        rcu_read_unlock();
  
        if (bss->wmm_used && bss->uapsd_supported &&
-           (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD) &&
-           sdata->wmm_acm != 0xff) {
+           (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
                assoc_data->uapsd = true;
                ifmgd->flags |= IEEE80211_STA_UAPSD_ENABLED;
        } else {
diff --combined net/mac80211/sta_info.c
index e1f957d5935e0e5dc113a8570a4ac8d08acaa1a4,441875f03750ca5a41255faaf9e062c8af1efc32..7300305420244a6825ead12e641145c984e5530c
@@@ -1094,8 -1094,11 +1094,11 @@@ void ieee80211_sta_ps_deliver_wakeup(st
        unsigned long flags;
        struct ps_data *ps;
  
-       if (sdata->vif.type == NL80211_IFTYPE_AP ||
-           sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+       if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
+               sdata = container_of(sdata->bss, struct ieee80211_sub_if_data,
+                                    u.ap);
+       if (sdata->vif.type == NL80211_IFTYPE_AP)
                ps = &sdata->bss->ps;
        else if (ieee80211_vif_is_mesh(&sdata->vif))
                ps = &sdata->u.mesh.ps;
@@@ -1179,7 -1182,7 +1182,7 @@@ static void ieee80211_send_null_respons
        struct sk_buff *skb;
        int size = sizeof(*nullfunc);
        __le16 fc;
 -      bool qos = test_sta_flag(sta, WLAN_STA_WME);
 +      bool qos = sta->sta.wme;
        struct ieee80211_tx_info *info;
        struct ieee80211_chanctx_conf *chanctx_conf;
  
@@@ -1834,7 -1837,7 +1837,7 @@@ void sta_set_sinfo(struct sta_info *sta
                sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_AUTHORIZED);
        if (test_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE))
                sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_SHORT_PREAMBLE);
 -      if (test_sta_flag(sta, WLAN_STA_WME))
 +      if (sta->sta.wme)
                sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_WME);
        if (test_sta_flag(sta, WLAN_STA_MFP))
                sinfo->sta_flags.set |= BIT(NL80211_STA_FLAG_MFP);
diff --combined net/mac802154/wpan.c
index ce1757001917a3654f732274bc24130f78e6406c,547838822d5e9c0d7064d72e2dc3be1ff2c14e14..b7961129ce4d28f838362120c97c511770c981e5
@@@ -462,7 -462,10 +462,10 @@@ mac802154_subif_frame(struct mac802154_
                        skb->pkt_type = PACKET_OTHERHOST;
                break;
        default:
-               break;
+               spin_unlock_bh(&sdata->mib_lock);
+               pr_debug("invalid dest mode\n");
+               kfree_skb(skb);
+               return NET_RX_DROP;
        }
  
        spin_unlock_bh(&sdata->mib_lock);
        rc = mac802154_llsec_decrypt(&sdata->sec, skb);
        if (rc) {
                pr_debug("decryption failed: %i\n", rc);
 -              kfree_skb(skb);
 -              return NET_RX_DROP;
 +              goto fail;
        }
  
        sdata->dev->stats.rx_packets++;
        default:
                pr_warn("ieee802154: bad frame received (type = %d)\n",
                        mac_cb(skb)->type);
 -              kfree_skb(skb);
 -              return NET_RX_DROP;
 +              goto fail;
        }
 +
 +fail:
 +      kfree_skb(skb);
 +      return NET_RX_DROP;
  }
  
  static void mac802154_print_addr(const char *name,
@@@ -575,6 -576,7 +578,7 @@@ void mac802154_wpans_rx(struct mac80215
        ret = mac802154_parse_frame_start(skb, &hdr);
        if (ret) {
                pr_debug("got invalid frame\n");
+               kfree_skb(skb);
                return;
        }