Merge git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac80211-next
authorJohn W. Linville <linville@tuxdriver.com>
Thu, 22 May 2014 17:58:36 +0000 (13:58 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 22 May 2014 17:58:36 +0000 (13:58 -0400)
18 files changed:
1  2 
drivers/net/wireless/ath/ath6kl/cfg80211.c
drivers/net/wireless/ath/ath6kl/wmi.c
drivers/net/wireless/ath/ath6kl/wmi.h
drivers/net/wireless/ath/wil6210/main.c
drivers/net/wireless/ath/wil6210/wil6210.h
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/mwifiex/11n.h
drivers/net/wireless/mwifiex/main.h
drivers/net/wireless/mwifiex/tdls.c
drivers/net/wireless/mwifiex/wmm.c
include/net/cfg80211.h
net/mac80211/chan.c
net/mac80211/main.c
net/mac80211/trace.h
net/mac80211/util.c
net/rfkill/rfkill-gpio.c
net/wireless/scan.c
net/wireless/sme.c

index 09285084bcd3d0a17ab6c518b1d2ea4f616ffe26,1fffbde4b01ea154e6dedf8ced075c478945c973..0e26f4a34fda329910ecc278de9fe7bea8fa6c57
@@@ -724,9 -724,8 +724,9 @@@ ath6kl_add_bss_if_needed(struct ath6kl_
                        ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
                                   "added bss %pM to cfg80211\n", bssid);
                kfree(ie);
 -      } else
 +      } else {
                ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "cfg80211 already has a bss\n");
 +      }
  
        return bss;
  }
@@@ -971,6 -970,7 +971,6 @@@ static int ath6kl_set_probed_ssids(stru
                                          ssid_list[i].flag,
                                          ssid_list[i].ssid.ssid_len,
                                          ssid_list[i].ssid.ssid);
 -
        }
  
        /* Make sure no old entries are left behind */
@@@ -1759,7 -1759,7 +1759,7 @@@ static bool is_rate_ht40(s32 rate, u8 *
  }
  
  static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
-                             u8 *mac, struct station_info *sinfo)
+                             const u8 *mac, struct station_info *sinfo)
  {
        struct ath6kl *ar = ath6kl_priv(dev);
        struct ath6kl_vif *vif = netdev_priv(dev);
@@@ -1897,6 -1897,7 +1897,6 @@@ static int ath6kl_wow_usr(struct ath6k
  
        /* Configure the patterns that we received from the user. */
        for (i = 0; i < wow->n_patterns; i++) {
 -
                /*
                 * Convert given nl80211 specific mask value to equivalent
                 * driver specific mask value and send it to the chip along
@@@ -2849,9 -2850,8 +2849,9 @@@ static int ath6kl_start_ap(struct wiph
        if (p.prwise_crypto_type == 0) {
                p.prwise_crypto_type = NONE_CRYPT;
                ath6kl_set_cipher(vif, 0, true);
 -      } else if (info->crypto.n_ciphers_pairwise == 1)
 +      } else if (info->crypto.n_ciphers_pairwise == 1) {
                ath6kl_set_cipher(vif, info->crypto.ciphers_pairwise[0], true);
 +      }
  
        switch (info->crypto.cipher_group) {
        case WLAN_CIPHER_SUITE_WEP40:
        }
  
        if (info->inactivity_timeout) {
 -
                inactivity_timeout = info->inactivity_timeout;
  
                if (ar->hw.flags & ATH6KL_HW_AP_INACTIVITY_MINS)
@@@ -2974,7 -2975,7 +2974,7 @@@ static int ath6kl_stop_ap(struct wiphy 
  static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
  
  static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev,
-                             u8 *mac)
+                             const u8 *mac)
  {
        struct ath6kl *ar = ath6kl_priv(dev);
        struct ath6kl_vif *vif = netdev_priv(dev);
  }
  
  static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
-                                u8 *mac, struct station_parameters *params)
+                                const u8 *mac,
+                                struct station_parameters *params)
  {
        struct ath6kl *ar = ath6kl_priv(dev);
        struct ath6kl_vif *vif = netdev_priv(dev);
index 0c0e1e36e40fe7359e7190f2abc2015ab79578bb,051094604e219cf906f28e5c4dde5138cb3651cf..4d7f9e4712e991deea8553f7505a7f79b9a6f6e7
@@@ -289,9 -289,8 +289,9 @@@ int ath6kl_wmi_implicit_create_pstream(
                           ath6kl_wmi_determine_user_priority(((u8 *) llc_hdr) +
                                        sizeof(struct ath6kl_llc_snap_hdr),
                                        layer2_priority);
 -              } else
 +              } else {
                        usr_pri = layer2_priority & 0x7;
 +              }
  
                /*
                 * Queue the EAPOL frames in the same WMM_AC_VO queue
@@@ -360,9 -359,8 +360,9 @@@ int ath6kl_wmi_dot11_hdr_remove(struct 
                hdr_size = roundup(sizeof(struct ieee80211_qos_hdr),
                                   sizeof(u32));
                skb_pull(skb, hdr_size);
 -      } else if (sub_type == cpu_to_le16(IEEE80211_STYPE_DATA))
 +      } else if (sub_type == cpu_to_le16(IEEE80211_STYPE_DATA)) {
                skb_pull(skb, sizeof(struct ieee80211_hdr_3addr));
 +      }
  
        datap = skb->data;
        llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap);
@@@ -938,6 -936,7 +938,6 @@@ ath6kl_regd_find_country_by_rd(u16 regd
  
  static void ath6kl_wmi_regdomain_event(struct wmi *wmi, u8 *datap, int len)
  {
 -
        struct ath6kl_wmi_regdomain *ev;
        struct country_code_to_enum_rd *country = NULL;
        struct reg_dmn_pair_mapping *regpair = NULL;
        ev = (struct ath6kl_wmi_regdomain *) datap;
        reg_code = le32_to_cpu(ev->reg_code);
  
 -      if ((reg_code >> ATH6KL_COUNTRY_RD_SHIFT) & COUNTRY_ERD_FLAG)
 +      if ((reg_code >> ATH6KL_COUNTRY_RD_SHIFT) & COUNTRY_ERD_FLAG) {
                country = ath6kl_regd_find_country((u16) reg_code);
 -      else if (!(((u16) reg_code & WORLD_SKU_MASK) == WORLD_SKU_PREFIX)) {
 -
 +      } else if (!(((u16) reg_code & WORLD_SKU_MASK) == WORLD_SKU_PREFIX)) {
                regpair = ath6kl_get_regpair((u16) reg_code);
                country = ath6kl_regd_find_country_by_rd((u16) reg_code);
                if (regpair)
@@@ -1499,6 -1499,7 +1499,6 @@@ static int ath6kl_wmi_cac_event_rx(stru
  
        if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) &&
            (reply->status_code != IEEE80211_TSPEC_STATUS_ADMISS_ACCEPTED)) {
 -
                ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion);
                tsinfo = le16_to_cpu(ts->tsinfo);
                tsid = (tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) &
         * for delete qos stream from AP
         */
        else if (reply->cac_indication == CAC_INDICATION_DELETE) {
 -
                ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion);
                tsinfo = le16_to_cpu(ts->tsinfo);
                ts_id = ((tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) &
@@@ -2320,7 -2322,7 +2320,7 @@@ int ath6kl_wmi_addkey_cmd(struct wmi *w
        return ret;
  }
  
- int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk)
+ int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, const u8 *krk)
  {
        struct sk_buff *skb;
        struct wmi_add_krk_cmd *cmd;
@@@ -2477,6 -2479,7 +2477,6 @@@ static int ath6kl_wmi_sync_point(struc
                goto free_data_skb;
  
        for (index = 0; index < num_pri_streams; index++) {
 -
                if (WARN_ON(!data_sync_bufs[index].skb))
                        goto free_data_skb;
  
@@@ -2701,6 -2704,7 +2701,6 @@@ static void ath6kl_wmi_relinquish_impli
  
        for (i = 0; i < WMM_NUM_AC; i++) {
                if (stream_exist & (1 << i)) {
 -
                        /*
                         * FIXME: Is this lock & unlock inside
                         * for loop correct? may need rework.
@@@ -2866,9 -2870,8 +2866,9 @@@ int ath6kl_wmi_set_host_sleep_mode_cmd(
        if (host_mode == ATH6KL_HOST_MODE_ASLEEP) {
                ath6kl_wmi_relinquish_implicit_pstream_credits(wmi);
                cmd->asleep = cpu_to_le32(1);
 -      } else
 +      } else {
                cmd->awake = cpu_to_le32(1);
 +      }
  
        ret = ath6kl_wmi_cmd_send(wmi, if_idx, skb,
                                  WMI_SET_HOST_SLEEP_MODE_CMDID,
index 1f05ecd97c912b1efdfdea3910abd3aca71be38a,39ee35e60c1dc89ccb7d35973945b9dda879ea99..7809afbb3e937e65a3f5045069815e79f551ac1c
@@@ -898,6 -898,7 +898,6 @@@ struct wmi_start_scan_cmd 
   *  flags here
   */
  enum wmi_scan_ctrl_flags_bits {
 -
        /* set if can scan in the connect cmd */
        CONNECT_SCAN_CTRL_FLAGS = 0x01,
  
@@@ -2616,7 -2617,7 +2616,7 @@@ int ath6kl_wmi_addkey_cmd(struct wmi *w
                          u8 *key_material,
                          u8 key_op_ctrl, u8 *mac_addr,
                          enum wmi_sync_flag sync_flag);
- int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk);
+ int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, const u8 *krk);
  int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index);
  int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, u8 if_idx, const u8 *bssid,
                            const u8 *pmkid, bool set);
index 1b265fd19de26060329ffb3c7b2818feeb2fcc68,a6b1d5872786c6cb1bb6876e62ecb1b8df9d3462..670cc6de3b4cec171e36af8a05497b9acacf86a2
@@@ -81,7 -81,7 +81,7 @@@ static void wil_disconnect_cid(struct w
        memset(&sta->stats, 0, sizeof(sta->stats));
  }
  
- static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
+ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
  {
        int cid = -ENOENT;
        struct net_device *ndev = wil_to_ndev(wil);
@@@ -252,7 -252,7 +252,7 @@@ int wil_priv_init(struct wil6210_priv *
        return 0;
  }
  
- void wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
+ void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
  {
        del_timer_sync(&wil->connect_timer);
        _wil6210_disconnect(wil, bssid);
@@@ -363,8 -363,8 +363,8 @@@ static int wil_wait_for_fw_ready(struc
                wil_err(wil, "Firmware not ready\n");
                return -ETIME;
        } else {
 -              wil_dbg_misc(wil, "FW ready after %d ms\n",
 -                           jiffies_to_msecs(to-left));
 +              wil_info(wil, "FW ready after %d ms. HW version 0x%08x\n",
 +                       jiffies_to_msecs(to-left), wil->hw_version);
        }
        return 0;
  }
index d3b8659ca32e17853602a8a21525f345abaf92a2,6b353be6457913be240a21001ac740d7670e005e..3427ac4a4fa136127d25046c24d61eae161032d2
@@@ -35,7 -35,7 +35,7 @@@ static inline u32 WIL_GET_BITS(u32 x, i
  #define WIL6210_MEM_SIZE (2*1024*1024UL)
  
  #define WIL6210_RX_RING_SIZE  (128)
 -#define WIL6210_TX_RING_SIZE  (128)
 +#define WIL6210_TX_RING_SIZE  (512)
  #define WIL6210_MAX_TX_RINGS  (24) /* HW limit */
  #define WIL6210_MAX_CID               (8) /* HW limit */
  #define WIL6210_NAPI_BUDGET   (16) /* arbitrary */
@@@ -301,7 -301,6 +301,7 @@@ struct wil_tid_ampdu_rx 
        u16 buf_size;
        u16 timeout;
        u8 dialog_token;
 +      bool first_time; /* is it 1-st time this buffer used? */
  };
  
  struct wil6210_stats {
@@@ -508,7 -507,7 +508,7 @@@ void wil_wdev_free(struct wil6210_priv 
  int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
  int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan);
  int wmi_pcp_stop(struct wil6210_priv *wil);
- void wil6210_disconnect(struct wil6210_priv *wil, void *bssid);
+ void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid);
  
  int wil_rx_init(struct wil6210_priv *wil);
  void wil_rx_fini(struct wil6210_priv *wil);
index 70bc2542061a0d4c03796dc2eb7581bd3712f860,befa9c04166d658f436166aa521f8a19d1a1ab45..92cb29a2003fe1c7c27d59c99ccc44c6b4eae91d
@@@ -221,9 -221,9 +221,9 @@@ static const struct ieee80211_regdomai
                 */
                REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
                /* IEEE 802.11a, channel 36..64 */
 -              REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
 +              REG_RULE(5150-10, 5350+10, 80, 6, 20, 0),
                /* IEEE 802.11a, channel 100..165 */
 -              REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
 +              REG_RULE(5470-10, 5850+10, 80, 6, 20, 0), }
  };
  
  static const u32 __wl_cipher_suites[] = {
@@@ -341,60 -341,6 +341,60 @@@ static u8 brcmf_mw_to_qdbm(u16 mw
        return qdbm;
  }
  
 +u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
 +                      struct cfg80211_chan_def *ch)
 +{
 +      struct brcmu_chan ch_inf;
 +      s32 primary_offset;
 +
 +      brcmf_dbg(TRACE, "chandef: control %d center %d width %d\n",
 +                ch->chan->center_freq, ch->center_freq1, ch->width);
 +      ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq1);
 +      primary_offset = ch->center_freq1 - ch->chan->center_freq;
 +      switch (ch->width) {
 +      case NL80211_CHAN_WIDTH_20:
 +              ch_inf.bw = BRCMU_CHAN_BW_20;
 +              WARN_ON(primary_offset != 0);
 +              break;
 +      case NL80211_CHAN_WIDTH_40:
 +              ch_inf.bw = BRCMU_CHAN_BW_40;
 +              if (primary_offset < 0)
 +                      ch_inf.sb = BRCMU_CHAN_SB_U;
 +              else
 +                      ch_inf.sb = BRCMU_CHAN_SB_L;
 +              break;
 +      case NL80211_CHAN_WIDTH_80:
 +              ch_inf.bw = BRCMU_CHAN_BW_80;
 +              if (primary_offset < 0) {
 +                      if (primary_offset < -CH_10MHZ_APART)
 +                              ch_inf.sb = BRCMU_CHAN_SB_UU;
 +                      else
 +                              ch_inf.sb = BRCMU_CHAN_SB_UL;
 +              } else {
 +                      if (primary_offset > CH_10MHZ_APART)
 +                              ch_inf.sb = BRCMU_CHAN_SB_LL;
 +                      else
 +                              ch_inf.sb = BRCMU_CHAN_SB_LU;
 +              }
 +              break;
 +      default:
 +              WARN_ON_ONCE(1);
 +      }
 +      switch (ch->chan->band) {
 +      case IEEE80211_BAND_2GHZ:
 +              ch_inf.band = BRCMU_CHAN_BAND_2G;
 +              break;
 +      case IEEE80211_BAND_5GHZ:
 +              ch_inf.band = BRCMU_CHAN_BAND_5G;
 +              break;
 +      default:
 +              WARN_ON_ONCE(1);
 +      }
 +      d11inf->encchspec(&ch_inf);
 +
 +      return ch_inf.chspec;
 +}
 +
  u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
                        struct ieee80211_channel *ch)
  {
@@@ -1290,8 -1236,8 +1290,8 @@@ brcmf_cfg80211_join_ibss(struct wiphy *
                                params->chandef.chan->center_freq);
                if (params->channel_fixed) {
                        /* adding chanspec */
 -                      chanspec = channel_to_chanspec(&cfg->d11inf,
 -                                                     params->chandef.chan);
 +                      chanspec = chandef_to_chanspec(&cfg->d11inf,
 +                                                     &params->chandef);
                        join_params.params_le.chanspec_list[0] =
                                cpu_to_le16(chanspec);
                        join_params.params_le.chanspec_num = cpu_to_le32(1);
@@@ -2236,7 -2182,7 +2236,7 @@@ brcmf_cfg80211_config_default_mgmt_key(
  
  static s32
  brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
-                          u8 *mac, struct station_info *sinfo)
+                          const u8 *mac, struct station_info *sinfo)
  {
        struct brcmf_if *ifp = netdev_priv(ndev);
        struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
@@@ -3787,6 -3733,23 +3787,6 @@@ brcmf_config_ap_mgmt_ie(struct brcmf_cf
        return err;
  }
  
 -static s32
 -brcmf_cfg80211_set_channel(struct brcmf_cfg80211_info *cfg,
 -                         struct brcmf_if *ifp,
 -                         struct ieee80211_channel *channel)
 -{
 -      u16 chanspec;
 -      s32 err;
 -
 -      brcmf_dbg(TRACE, "band=%d, center_freq=%d\n", channel->band,
 -                channel->center_freq);
 -
 -      chanspec = channel_to_chanspec(&cfg->d11inf, channel);
 -      err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
 -
 -      return err;
 -}
 -
  static s32
  brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
                        struct cfg80211_ap_settings *settings)
        struct brcmf_join_params join_params;
        enum nl80211_iftype dev_role;
        struct brcmf_fil_bss_enable_le bss_enable;
 +      u16 chanspec;
  
 -      brcmf_dbg(TRACE, "channel_type=%d, beacon_interval=%d, dtim_period=%d,\n",
 -                cfg80211_get_chandef_type(&settings->chandef),
 -                settings->beacon_interval,
 -                settings->dtim_period);
 +      brcmf_dbg(TRACE, "ctrlchn=%d, center=%d, bw=%d, beacon_interval=%d, dtim_period=%d,\n",
 +                settings->chandef.chan->hw_value,
 +                settings->chandef.center_freq1, settings->chandef.width,
 +                settings->beacon_interval, settings->dtim_period);
        brcmf_dbg(TRACE, "ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n",
                  settings->ssid, settings->ssid_len, settings->auth_type,
                  settings->inactivity_timeout);
  
        brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
  
 -      err = brcmf_cfg80211_set_channel(cfg, ifp, settings->chandef.chan);
 +      chanspec = chandef_to_chanspec(&cfg->d11inf, &settings->chandef);
 +      err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
        if (err < 0) {
 -              brcmf_err("Set Channel failed, %d\n", err);
 +              brcmf_err("Set Channel failed: chspec=%d, %d\n", chanspec, err);
                goto exit;
        }
  
@@@ -4014,7 -3975,7 +4014,7 @@@ brcmf_cfg80211_change_beacon(struct wip
  
  static int
  brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
-                          u8 *mac)
+                          const u8 *mac)
  {
        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
        struct brcmf_scb_val_le scbval;
@@@ -4242,7 -4203,7 +4242,7 @@@ static int brcmf_convert_nl80211_tdls_o
  }
  
  static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy,
-                                   struct net_device *ndev, u8 *peer,
+                                   struct net_device *ndev, const u8 *peer,
                                    enum nl80211_tdls_operation oper)
  {
        struct brcmf_if *ifp;
@@@ -4403,8 -4364,6 +4403,8 @@@ static struct wiphy *brcmf_setup_wiphy(
                        WIPHY_FLAG_OFFCHAN_TX |
                        WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
                        WIPHY_FLAG_SUPPORTS_TDLS;
 +      if (!brcmf_roamoff)
 +              wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
        wiphy->mgmt_stypes = brcmf_txrx_stypes;
        wiphy->max_remain_on_channel_duration = 5000;
        brcmf_wiphy_pno_params(wiphy);
@@@ -4726,6 -4685,7 +4726,6 @@@ brcmf_notify_connect_status(struct brcm
        struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
        struct ieee80211_channel *chan;
        s32 err = 0;
 -      u16 reason;
  
        if (brcmf_is_apmode(ifp->vif)) {
                err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);
                brcmf_dbg(CONN, "Linkdown\n");
                if (!brcmf_is_ibssmode(ifp->vif)) {
                        brcmf_bss_connect_done(cfg, ndev, e, false);
 -                      if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED,
 -                                             &ifp->vif->sme_state)) {
 -                              reason = 0;
 -                              if (((e->event_code == BRCMF_E_DEAUTH_IND) ||
 -                                   (e->event_code == BRCMF_E_DISASSOC_IND)) &&
 -                                  (e->reason != WLAN_REASON_UNSPECIFIED))
 -                                      reason = e->reason;
 -                              cfg80211_disconnected(ndev, reason, NULL, 0,
 -                                                    GFP_KERNEL);
 -                      }
                }
                brcmf_link_down(ifp->vif);
                brcmf_init_prof(ndev_to_prof(ndev));
@@@ -4978,7 -4948,7 +4978,7 @@@ static int brcmf_enable_bw40_2g(struct 
        if (!err) {
                /* only set 2G bandwidth using bw_cap command */
                band_bwcap.band = cpu_to_le32(WLC_BAND_2G);
 -              band_bwcap.bw_cap = cpu_to_le32(WLC_BW_40MHZ_BIT);
 +              band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ);
                err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap,
                                               sizeof(band_bwcap));
        } else {
@@@ -5245,9 -5215,6 +5245,9 @@@ static s32 brcmf_construct_reginfo(stru
                if (!(bw_cap[band] & WLC_BW_40MHZ_BIT) &&
                    ch.bw == BRCMU_CHAN_BW_40)
                        continue;
 +              if (!(bw_cap[band] & WLC_BW_80MHZ_BIT) &&
 +                  ch.bw == BRCMU_CHAN_BW_80)
 +                      continue;
                update = false;
                for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
                        if (band_chan_arr[j].hw_value == ch.chnum) {
                                ieee80211_channel_to_frequency(ch.chnum, band);
                        band_chan_arr[index].hw_value = ch.chnum;
  
 -                      if (ch.bw == BRCMU_CHAN_BW_40) {
 -                              /* assuming the order is HT20, HT40 Upper,
 -                               * HT40 lower from chanspecs
 -                               */
 +                      /* assuming the chanspecs order is HT20,
 +                       * HT40 upper, HT40 lower, and VHT80.
 +                       */
 +                      if (ch.bw == BRCMU_CHAN_BW_80) {
 +                              band_chan_arr[index].flags &=
 +                                      ~IEEE80211_CHAN_NO_80MHZ;
 +                      } else if (ch.bw == BRCMU_CHAN_BW_40) {
                                ht40_flag = band_chan_arr[index].flags &
                                            IEEE80211_CHAN_NO_HT40;
                                if (ch.sb == BRCMU_CHAN_SB_U) {
                                                    IEEE80211_CHAN_NO_HT40MINUS;
                                }
                        } else {
 +                              /* disable other bandwidths for now as mentioned
 +                               * order assure they are enabled for subsequent
 +                               * chanspecs.
 +                               */
                                band_chan_arr[index].flags =
 -                                                      IEEE80211_CHAN_NO_HT40;
 +                                              IEEE80211_CHAN_NO_HT40 |
 +                                              IEEE80211_CHAN_NO_80MHZ;
                                ch.bw = BRCMU_CHAN_BW_20;
                                cfg->d11inf.encchspec(&ch);
                                channel = ch.chspec;
@@@ -5364,63 -5323,13 +5364,63 @@@ static void brcmf_get_bwcap(struct brcm
        }
  }
  
 +static void brcmf_update_ht_cap(struct ieee80211_supported_band *band,
 +                              u32 bw_cap[2], u32 nchain)
 +{
 +      band->ht_cap.ht_supported = true;
 +      if (bw_cap[band->band] & WLC_BW_40MHZ_BIT) {
 +              band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
 +              band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 +      }
 +      band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
 +      band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
 +      band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
 +      band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
 +      memset(band->ht_cap.mcs.rx_mask, 0xff, nchain);
 +      band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
 +}
 +
 +static __le16 brcmf_get_mcs_map(u32 nchain, enum ieee80211_vht_mcs_support supp)
 +{
 +      u16 mcs_map;
 +      int i;
 +
 +      for (i = 0, mcs_map = 0xFFFF; i < nchain; i++)
 +              mcs_map = (mcs_map << 2) | supp;
 +
 +      return cpu_to_le16(mcs_map);
 +}
 +
 +static void brcmf_update_vht_cap(struct ieee80211_supported_band *band,
 +                               u32 bw_cap[2], u32 nchain)
 +{
 +      __le16 mcs_map;
 +
 +      /* not allowed in 2.4G band */
 +      if (band->band == IEEE80211_BAND_2GHZ)
 +              return;
 +
 +      band->vht_cap.vht_supported = true;
 +      /* 80MHz is mandatory */
 +      band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
 +      if (bw_cap[band->band] & WLC_BW_160MHZ_BIT) {
 +              band->vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
 +              band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
 +      }
 +      /* all support 256-QAM */
 +      mcs_map = brcmf_get_mcs_map(nchain, IEEE80211_VHT_MCS_SUPPORT_0_9);
 +      band->vht_cap.vht_mcs.rx_mcs_map = mcs_map;
 +      band->vht_cap.vht_mcs.tx_mcs_map = mcs_map;
 +}
 +
  static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
  {
        struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
        struct wiphy *wiphy;
        s32 phy_list;
        u32 band_list[3];
 -      u32 nmode;
 +      u32 nmode = 0;
 +      u32 vhtmode = 0;
        u32 bw_cap[2] = { 0, 0 };
        u32 rxchain;
        u32 nchain;
        brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n",
                  band_list[0], band_list[1], band_list[2]);
  
 +      (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode);
        err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
        if (err) {
                brcmf_err("nmode error (%d)\n", err);
        } else {
                brcmf_get_bwcap(ifp, bw_cap);
        }
 -      brcmf_dbg(INFO, "nmode=%d, bw_cap=(%d, %d)\n", nmode,
 -                bw_cap[IEEE80211_BAND_2GHZ], bw_cap[IEEE80211_BAND_5GHZ]);
 +      brcmf_dbg(INFO, "nmode=%d, vhtmode=%d, bw_cap=(%d, %d)\n",
 +                nmode, vhtmode, bw_cap[IEEE80211_BAND_2GHZ],
 +                bw_cap[IEEE80211_BAND_5GHZ]);
  
        err = brcmf_fil_iovar_int_get(ifp, "rxchain", &rxchain);
        if (err) {
                else
                        continue;
  
 -              if (bw_cap[band->band] & WLC_BW_40MHZ_BIT) {
 -                      band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
 -                      band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 -              }
 -              band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
 -              band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
 -              band->ht_cap.ht_supported = true;
 -              band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
 -              band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
 -              memset(band->ht_cap.mcs.rx_mask, 0xff, nchain);
 -              band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
 +              if (nmode)
 +                      brcmf_update_ht_cap(band, bw_cap, nchain);
 +              if (vhtmode)
 +                      brcmf_update_vht_cap(band, bw_cap, nchain);
                bands[band->band] = band;
        }
  
index 43889d9e3b35d42766394b15247f798f8d56a6ad,0a46aab242149027905a9ba33f459d0f13a0baa5..0b73fa08f5d466b98d5292d0a5b16e1011c30be3
@@@ -63,7 -63,6 +63,7 @@@ int mwifiex_cmd_amsdu_aggr_ctrl(struct 
                                int cmd_action,
                                struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl);
  void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra);
 +u8 mwifiex_get_sec_chan_offset(int chan);
  
  static inline u8
  mwifiex_is_station_ampdu_allowed(struct mwifiex_private *priv,
@@@ -200,7 -199,7 +200,7 @@@ static inline int mwifiex_is_sta_11n_en
  }
  
  static inline u8
- mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, u8 *ra)
+ mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, const u8 *ra)
  {
        struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ra);
        if (node)
index 34181192a666b71a759cfd65c6e3c30c2eb1ca38,86c6b8cdec22f4af3e5a75c9202ffc339ee11135..3f25feb1508ef52fc704b3779988a1dbb6d4304e
@@@ -672,7 -672,6 +672,7 @@@ struct mwifiex_if_ops 
        int (*init_fw_port) (struct mwifiex_adapter *);
        int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *);
        void (*card_reset) (struct mwifiex_adapter *);
 +      void (*fw_dump)(struct mwifiex_adapter *);
        int (*clean_pcie_ring) (struct mwifiex_adapter *adapter);
  };
  
@@@ -788,6 -787,7 +788,6 @@@ struct mwifiex_adapter 
        struct mwifiex_wait_queue cmd_wait_q;
        u8 scan_wait_q_woken;
        spinlock_t queue_lock;          /* lock for tx queues */
 -      struct completion fw_load;
        u8 country_code[IEEE80211_COUNTRY_STRING_LEN];
        u16 max_mgmt_ie_index;
        u8 scan_delay_cnt;
@@@ -910,8 -910,6 +910,6 @@@ int mwifiex_handle_uap_rx_forward(struc
                                  struct sk_buff *skb);
  int mwifiex_process_sta_event(struct mwifiex_private *);
  int mwifiex_process_uap_event(struct mwifiex_private *);
- struct mwifiex_sta_node *
- mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac);
  void mwifiex_delete_all_station_list(struct mwifiex_private *priv);
  void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
  void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb);
@@@ -1220,26 -1218,26 +1218,26 @@@ void mwifiex_dnld_txpwr_table(struct mw
  extern const struct ethtool_ops mwifiex_ethtool_ops;
  
  void mwifiex_del_all_sta_list(struct mwifiex_private *priv);
- void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac);
+ void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac);
  void
  mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
                       int ies_len, struct mwifiex_sta_node *node);
  struct mwifiex_sta_node *
- mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac);
+ mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac);
  struct mwifiex_sta_node *
- mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac);
- int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, u8 *peer,
+ mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac);
+ int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
                                 u8 action_code, u8 dialog_token,
                                 u16 status_code, const u8 *extra_ies,
                                 size_t extra_ies_len);
- int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv,
-                                u8 *peer, u8 action_code, u8 dialog_token,
-                                u16 status_code, const u8 *extra_ies,
-                                size_t extra_ies_len);
+ int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
+                                  u8 action_code, u8 dialog_token,
+                                  u16 status_code, const u8 *extra_ies,
+                                  size_t extra_ies_len);
  void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
                                       u8 *buf, int len);
- int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action);
- int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac);
+ int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action);
+ int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac);
  void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv);
  bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv);
  u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band,
index 6bef47c2a70de61e73ae9dfa6346e566d39cf6e3,49c8a2c64eeb035886ab8011e402b638eb47825a..e14fbb5de49b6a6b3c3ed45de78c9311d55668fd
@@@ -25,8 -25,8 +25,8 @@@
  #define TDLS_RESP_FIX_LEN     8
  #define TDLS_CONFIRM_FIX_LEN  6
  
- static void
mwifiex_restore_tdls_packets(struct mwifiex_private *priv, u8 *mac, u8 status)
+ static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv,
                                       const u8 *mac, u8 status)
  {
        struct mwifiex_ra_list_tbl *ra_list;
        struct list_head *tid_list;
@@@ -84,7 -84,8 +84,8 @@@
        return;
  }
  
- static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv, u8 *mac)
+ static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv,
+                                     const u8 *mac)
  {
        struct mwifiex_ra_list_tbl *ra_list;
        struct list_head *ra_list_head;
@@@ -185,50 -186,8 +186,50 @@@ static int mwifiex_tdls_add_vht_capab(s
        return 0;
  }
  
 +static int
 +mwifiex_tdls_add_ht_oper(struct mwifiex_private *priv, u8 *mac,
 +                       u8 vht_enabled, struct sk_buff *skb)
 +{
 +      struct ieee80211_ht_operation *ht_oper;
 +      struct mwifiex_sta_node *sta_ptr;
 +      struct mwifiex_bssdescriptor *bss_desc =
 +                                      &priv->curr_bss_params.bss_descriptor;
 +      u8 *pos;
 +
 +      sta_ptr = mwifiex_get_sta_entry(priv, mac);
 +      if (unlikely(!sta_ptr)) {
 +              dev_warn(priv->adapter->dev,
 +                       "TDLS peer station not found in list\n");
 +              return -1;
 +      }
 +
 +      pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_operation) + 2);
 +      *pos++ = WLAN_EID_HT_OPERATION;
 +      *pos++ = sizeof(struct ieee80211_ht_operation);
 +      ht_oper = (void *)pos;
 +
 +      ht_oper->primary_chan = bss_desc->channel;
 +
 +      /* follow AP's channel bandwidth */
 +      if (ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) &&
 +          bss_desc->bcn_ht_cap &&
 +          ISALLOWED_CHANWIDTH40(bss_desc->bcn_ht_oper->ht_param))
 +              ht_oper->ht_param = bss_desc->bcn_ht_oper->ht_param;
 +
 +      if (vht_enabled) {
 +              ht_oper->ht_param =
 +                        mwifiex_get_sec_chan_offset(bss_desc->channel);
 +              ht_oper->ht_param |= BIT(2);
 +      }
 +
 +      memcpy(&sta_ptr->tdls_cap.ht_oper, ht_oper,
 +             sizeof(struct ieee80211_ht_operation));
 +
 +      return 0;
 +}
 +
  static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv,
-                                    u8 *mac, struct sk_buff *skb)
+                                    const u8 *mac, struct sk_buff *skb)
  {
        struct mwifiex_bssdescriptor *bss_desc;
        struct ieee80211_vht_operation *vht_oper;
@@@ -367,8 -326,9 +368,9 @@@ static void mwifiex_tdls_add_qos_capab(
  }
  
  static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
-                            u8 *peer, u8 action_code, u8 dialog_token,
-                            u16 status_code, struct sk_buff *skb)
+                                       const u8 *peer, u8 action_code,
+                                       u8 dialog_token,
+                                       u16 status_code, struct sk_buff *skb)
  {
        struct ieee80211_tdls_data *tf;
        int ret;
                        ret = mwifiex_tdls_add_vht_oper(priv, peer, skb);
                        if (ret) {
                                dev_kfree_skb_any(skb);
 +                              return ret;
 +                      }
 +                      ret = mwifiex_tdls_add_ht_oper(priv, peer, 1, skb);
 +                      if (ret) {
 +                              dev_kfree_skb_any(skb);
 +                              return ret;
 +                      }
 +              } else {
 +                      ret = mwifiex_tdls_add_ht_oper(priv, peer, 0, skb);
 +                      if (ret) {
 +                              dev_kfree_skb_any(skb);
                                return ret;
                        }
                }
  }
  
  static void
- mwifiex_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, u8 *peer, u8 *bssid)
+ mwifiex_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,
+                        const u8 *peer, const u8 *bssid)
  {
        struct ieee80211_tdls_lnkie *lnkid;
  
        memcpy(lnkid->resp_sta, peer, ETH_ALEN);
  }
  
- int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv,
-                                u8 *peer, u8 action_code, u8 dialog_token,
+ int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer,
+                                u8 action_code, u8 dialog_token,
                                 u16 status_code, const u8 *extra_ies,
                                 size_t extra_ies_len)
  {
  }
  
  static int
- mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, u8 *peer,
+ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv,
+                                   const u8 *peer,
                                    u8 action_code, u8 dialog_token,
                                    u16 status_code, struct sk_buff *skb)
  {
        return 0;
  }
  
- int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv,
-                                u8 *peer, u8 action_code, u8 dialog_token,
-                                u16 status_code, const u8 *extra_ies,
-                                size_t extra_ies_len)
+ int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer,
+                                  u8 action_code, u8 dialog_token,
+                                  u16 status_code, const u8 *extra_ies,
+                                  size_t extra_ies_len)
  {
        struct sk_buff *skb;
        struct mwifiex_txinfo *tx_info;
@@@ -901,7 -852,7 +905,7 @@@ void mwifiex_process_tdls_action_frame(
  }
  
  static int
- mwifiex_tdls_process_config_link(struct mwifiex_private *priv, u8 *peer)
+ mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer)
  {
        struct mwifiex_sta_node *sta_ptr;
        struct mwifiex_ds_tdls_oper tdls_oper;
  }
  
  static int
- mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer)
+ mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer)
  {
        struct mwifiex_sta_node *sta_ptr;
        struct mwifiex_ds_tdls_oper tdls_oper;
  }
  
  static int
- mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer)
+ mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer)
  {
        struct mwifiex_sta_node *sta_ptr;
        struct mwifiex_ds_tdls_oper tdls_oper;
  }
  
  static int
- mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, u8 *peer)
+ mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
  {
        struct mwifiex_sta_node *sta_ptr;
        struct ieee80211_mcs_info mcs;
        return 0;
  }
  
- int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action)
+ int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action)
  {
        switch (action) {
        case MWIFIEX_TDLS_ENABLE_LINK:
        return 0;
  }
  
- int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac)
+ int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac)
  {
        struct mwifiex_sta_node *sta_ptr;
  
index 94b6c74ba727eed15bc3affaf435444fcec53feb,c6bc5b3191d68d99b01e424468a74bb3358f64f7..789b86f805940fc7077ff9858c2f6fa75f135726
@@@ -92,7 -92,7 +92,7 @@@ mwifiex_wmm_ac_debug_print(const struc
   * The function also initializes the list with the provided RA.
   */
  static struct mwifiex_ra_list_tbl *
- mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, u8 *ra)
+ mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, const u8 *ra)
  {
        struct mwifiex_ra_list_tbl *ra_list;
  
@@@ -139,8 -139,7 +139,7 @@@ static u8 mwifiex_get_random_ba_thresho
   * This function allocates and adds a RA list for all TIDs
   * with the given RA.
   */
- void
- mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
+ void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
  {
        int i;
        struct mwifiex_ra_list_tbl *ra_list;
@@@ -426,6 -425,15 +425,6 @@@ mwifiex_wmm_init(struct mwifiex_adapte
                                                        priv->tos_to_tid_inv[i];
                }
  
 -              priv->aggr_prio_tbl[6].amsdu
 -                                      = priv->aggr_prio_tbl[6].ampdu_ap
 -                                      = priv->aggr_prio_tbl[6].ampdu_user
 -                                      = BA_STREAM_NOT_ALLOWED;
 -
 -              priv->aggr_prio_tbl[7].amsdu = priv->aggr_prio_tbl[7].ampdu_ap
 -                                      = priv->aggr_prio_tbl[7].ampdu_user
 -                                      = BA_STREAM_NOT_ALLOWED;
 -
                mwifiex_set_ba_params(priv);
                mwifiex_reset_11n_rx_seq_num(priv);
  
@@@ -566,7 -574,7 +565,7 @@@ mwifiex_clean_txrx(struct mwifiex_priva
   */
  static struct mwifiex_ra_list_tbl *
  mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid,
-                           u8 *ra_addr)
+                           const u8 *ra_addr)
  {
        struct mwifiex_ra_list_tbl *ra_list;
  
   * retrieved.
   */
  struct mwifiex_ra_list_tbl *
- mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr)
+ mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid,
+                           const u8 *ra_addr)
  {
        struct mwifiex_ra_list_tbl *ra_list;
  
diff --combined include/net/cfg80211.h
index f2c3186555192cf7ee57f9ace0399bf1adfd1a6f,920ec8c1ce541305bb2d1da9d9c8f178b14bd23d..e46c437944f73e66cb275f4adc345a1f869923c8
@@@ -341,8 -341,8 +341,8 @@@ struct vif_params 
   * @seq_len: length of @seq.
   */
  struct key_params {
-       u8 *key;
-       u8 *seq;
+       const u8 *key;
+       const u8 *seq;
        int key_len;
        int seq_len;
        u32 cipher;
@@@ -458,7 -458,7 +458,7 @@@ bool cfg80211_chandef_usable(struct wip
   */
  int cfg80211_chandef_dfs_required(struct wiphy *wiphy,
                                  const struct cfg80211_chan_def *chandef,
-                                 enum nl80211_iftype);
+                                 enum nl80211_iftype iftype);
  
  /**
   * ieee80211_chandef_rate_flags - returns rate flags for a channel
@@@ -694,8 -694,10 +694,10 @@@ struct cfg80211_ap_settings 
   *
   * @chandef: defines the channel to use after the switch
   * @beacon_csa: beacon data while performing the switch
-  * @counter_offset_beacon: offset for the counter within the beacon (tail)
-  * @counter_offset_presp: offset for the counter within the probe response
+  * @counter_offsets_beacon: offsets of the counters within the beacon (tail)
+  * @counter_offsets_presp: offsets of the counters within the probe response
+  * @n_counter_offsets_beacon: number of csa counters the beacon (tail)
+  * @n_counter_offsets_presp: number of csa counters in the probe response
   * @beacon_after: beacon data to be used on the new channel
   * @radar_required: whether radar detection is required on the new channel
   * @block_tx: whether transmissions should be blocked while changing
  struct cfg80211_csa_settings {
        struct cfg80211_chan_def chandef;
        struct cfg80211_beacon_data beacon_csa;
-       u16 counter_offset_beacon, counter_offset_presp;
+       const u16 *counter_offsets_beacon;
+       const u16 *counter_offsets_presp;
+       unsigned int n_counter_offsets_beacon;
+       unsigned int n_counter_offsets_presp;
        struct cfg80211_beacon_data beacon_after;
        bool radar_required;
        bool block_tx;
@@@ -868,36 -873,38 +873,38 @@@ int cfg80211_check_station_change(struc
   * @STATION_INFO_NONPEER_PM: @nonpeer_pm filled
   * @STATION_INFO_CHAIN_SIGNAL: @chain_signal filled
   * @STATION_INFO_CHAIN_SIGNAL_AVG: @chain_signal_avg filled
+  * @STATION_INFO_EXPECTED_THROUGHPUT: @expected_throughput filled
   */
  enum station_info_flags {
-       STATION_INFO_INACTIVE_TIME      = 1<<0,
-       STATION_INFO_RX_BYTES           = 1<<1,
-       STATION_INFO_TX_BYTES           = 1<<2,
-       STATION_INFO_LLID               = 1<<3,
-       STATION_INFO_PLID               = 1<<4,
-       STATION_INFO_PLINK_STATE        = 1<<5,
-       STATION_INFO_SIGNAL             = 1<<6,
-       STATION_INFO_TX_BITRATE         = 1<<7,
-       STATION_INFO_RX_PACKETS         = 1<<8,
-       STATION_INFO_TX_PACKETS         = 1<<9,
-       STATION_INFO_TX_RETRIES         = 1<<10,
-       STATION_INFO_TX_FAILED          = 1<<11,
-       STATION_INFO_RX_DROP_MISC       = 1<<12,
-       STATION_INFO_SIGNAL_AVG         = 1<<13,
-       STATION_INFO_RX_BITRATE         = 1<<14,
-       STATION_INFO_BSS_PARAM          = 1<<15,
-       STATION_INFO_CONNECTED_TIME     = 1<<16,
-       STATION_INFO_ASSOC_REQ_IES      = 1<<17,
-       STATION_INFO_STA_FLAGS          = 1<<18,
-       STATION_INFO_BEACON_LOSS_COUNT  = 1<<19,
-       STATION_INFO_T_OFFSET           = 1<<20,
-       STATION_INFO_LOCAL_PM           = 1<<21,
-       STATION_INFO_PEER_PM            = 1<<22,
-       STATION_INFO_NONPEER_PM         = 1<<23,
-       STATION_INFO_RX_BYTES64         = 1<<24,
-       STATION_INFO_TX_BYTES64         = 1<<25,
-       STATION_INFO_CHAIN_SIGNAL       = 1<<26,
-       STATION_INFO_CHAIN_SIGNAL_AVG   = 1<<27,
+       STATION_INFO_INACTIVE_TIME              = BIT(0),
+       STATION_INFO_RX_BYTES                   = BIT(1),
+       STATION_INFO_TX_BYTES                   = BIT(2),
+       STATION_INFO_LLID                       = BIT(3),
+       STATION_INFO_PLID                       = BIT(4),
+       STATION_INFO_PLINK_STATE                = BIT(5),
+       STATION_INFO_SIGNAL                     = BIT(6),
+       STATION_INFO_TX_BITRATE                 = BIT(7),
+       STATION_INFO_RX_PACKETS                 = BIT(8),
+       STATION_INFO_TX_PACKETS                 = BIT(9),
+       STATION_INFO_TX_RETRIES                 = BIT(10),
+       STATION_INFO_TX_FAILED                  = BIT(11),
+       STATION_INFO_RX_DROP_MISC               = BIT(12),
+       STATION_INFO_SIGNAL_AVG                 = BIT(13),
+       STATION_INFO_RX_BITRATE                 = BIT(14),
+       STATION_INFO_BSS_PARAM                  = BIT(15),
+       STATION_INFO_CONNECTED_TIME             = BIT(16),
+       STATION_INFO_ASSOC_REQ_IES              = BIT(17),
+       STATION_INFO_STA_FLAGS                  = BIT(18),
+       STATION_INFO_BEACON_LOSS_COUNT          = BIT(19),
+       STATION_INFO_T_OFFSET                   = BIT(20),
+       STATION_INFO_LOCAL_PM                   = BIT(21),
+       STATION_INFO_PEER_PM                    = BIT(22),
+       STATION_INFO_NONPEER_PM                 = BIT(23),
+       STATION_INFO_RX_BYTES64                 = BIT(24),
+       STATION_INFO_TX_BYTES64                 = BIT(25),
+       STATION_INFO_CHAIN_SIGNAL               = BIT(26),
+       STATION_INFO_CHAIN_SIGNAL_AVG           = BIT(27),
+       STATION_INFO_EXPECTED_THROUGHPUT        = BIT(28),
  };
  
  /**
@@@ -1019,6 -1026,8 +1026,8 @@@ struct sta_bss_parameters 
   * @local_pm: local mesh STA power save mode
   * @peer_pm: peer mesh STA power save mode
   * @nonpeer_pm: non-peer mesh STA power save mode
+  * @expected_throughput: expected throughput in kbps (including 802.11 headers)
+  *    towards this station.
   */
  struct station_info {
        u32 filled;
        enum nl80211_mesh_power_mode peer_pm;
        enum nl80211_mesh_power_mode nonpeer_pm;
  
+       u32 expected_throughput;
        /*
         * Note: Add a new enum station_info_flags value for each new field and
         * use it to check which fields are initialized.
         */
  };
  
+ /**
+  * cfg80211_get_station - retrieve information about a given station
+  * @dev: the device where the station is supposed to be connected to
+  * @mac_addr: the mac address of the station of interest
+  * @sinfo: pointer to the structure to fill with the information
+  *
+  * Returns 0 on success and sinfo is filled with the available information
+  * otherwise returns a negative error code and the content of sinfo has to be
+  * considered undefined.
+  */
+ int cfg80211_get_station(struct net_device *dev, const u8 *mac_addr,
+                        struct station_info *sinfo);
  /**
   * enum monitor_flags - monitor flags
   *
@@@ -1164,7 -1188,7 +1188,7 @@@ struct bss_parameters 
        int use_cts_prot;
        int use_short_preamble;
        int use_short_slot_time;
-       u8 *basic_rates;
+       const u8 *basic_rates;
        u8 basic_rates_len;
        int ap_isolate;
        int ht_opmode;
@@@ -1694,10 -1718,10 +1718,10 @@@ struct cfg80211_disassoc_request 
   * @ht_capa_mask:  The bits of ht_capa which are to be used.
   */
  struct cfg80211_ibss_params {
-       u8 *ssid;
-       u8 *bssid;
+       const u8 *ssid;
+       const u8 *bssid;
        struct cfg80211_chan_def chandef;
-       u8 *ie;
+       const u8 *ie;
        u8 ssid_len, ie_len;
        u16 beacon_interval;
        u32 basic_rates;
@@@ -1806,8 -1830,8 +1830,8 @@@ struct cfg80211_bitrate_mask 
   * @pmkid: The PMK material itself.
   */
  struct cfg80211_pmksa {
-       u8 *bssid;
-       u8 *pmkid;
+       const u8 *bssid;
+       const u8 *pmkid;
  };
  
  /**
   * memory, free @mask only!
   */
  struct cfg80211_pkt_pattern {
-       u8 *mask, *pattern;
+       const u8 *mask, *pattern;
        int pattern_len;
        int pkt_offset;
  };
@@@ -1986,6 -2010,8 +2010,8 @@@ struct cfg80211_update_ft_ies_params 
   * @len: buffer length
   * @no_cck: don't use cck rates for this frame
   * @dont_wait_for_ack: tells the low level not to wait for an ack
+  * @n_csa_offsets: length of csa_offsets array
+  * @csa_offsets: array of all the csa offsets in the frame
   */
  struct cfg80211_mgmt_tx_params {
        struct ieee80211_channel *chan;
        size_t len;
        bool no_cck;
        bool dont_wait_for_ack;
+       int n_csa_offsets;
+       const u16 *csa_offsets;
  };
  
  /**
@@@ -2336,28 -2364,29 +2364,29 @@@ struct cfg80211_ops 
  
  
        int     (*add_station)(struct wiphy *wiphy, struct net_device *dev,
-                              u8 *mac, struct station_parameters *params);
+                              const u8 *mac,
+                              struct station_parameters *params);
        int     (*del_station)(struct wiphy *wiphy, struct net_device *dev,
-                              u8 *mac);
+                              const u8 *mac);
        int     (*change_station)(struct wiphy *wiphy, struct net_device *dev,
-                                 u8 *mac, struct station_parameters *params);
+                                 const u8 *mac,
+                                 struct station_parameters *params);
        int     (*get_station)(struct wiphy *wiphy, struct net_device *dev,
-                              u8 *mac, struct station_info *sinfo);
+                              const u8 *mac, struct station_info *sinfo);
        int     (*dump_station)(struct wiphy *wiphy, struct net_device *dev,
-                              int idx, u8 *mac, struct station_info *sinfo);
+                               int idx, u8 *mac, struct station_info *sinfo);
  
        int     (*add_mpath)(struct wiphy *wiphy, struct net_device *dev,
-                              u8 *dst, u8 *next_hop);
+                              const u8 *dst, const u8 *next_hop);
        int     (*del_mpath)(struct wiphy *wiphy, struct net_device *dev,
-                              u8 *dst);
+                              const u8 *dst);
        int     (*change_mpath)(struct wiphy *wiphy, struct net_device *dev,
-                                 u8 *dst, u8 *next_hop);
+                                 const u8 *dst, const u8 *next_hop);
        int     (*get_mpath)(struct wiphy *wiphy, struct net_device *dev,
-                              u8 *dst, u8 *next_hop,
-                              struct mpath_info *pinfo);
+                            u8 *dst, u8 *next_hop, struct mpath_info *pinfo);
        int     (*dump_mpath)(struct wiphy *wiphy, struct net_device *dev,
-                              int idx, u8 *dst, u8 *next_hop,
-                              struct mpath_info *pinfo);
+                             int idx, u8 *dst, u8 *next_hop,
+                             struct mpath_info *pinfo);
        int     (*get_mesh_config)(struct wiphy *wiphy,
                                struct net_device *dev,
                                struct mesh_config *conf);
                                  struct cfg80211_gtk_rekey_data *data);
  
        int     (*tdls_mgmt)(struct wiphy *wiphy, struct net_device *dev,
-                            u8 *peer, u8 action_code,  u8 dialog_token,
+                            const u8 *peer, u8 action_code,  u8 dialog_token,
                             u16 status_code, u32 peer_capability,
                             const u8 *buf, size_t len);
        int     (*tdls_oper)(struct wiphy *wiphy, struct net_device *dev,
-                            u8 *peer, enum nl80211_tdls_operation oper);
+                            const u8 *peer, enum nl80211_tdls_operation oper);
  
        int     (*probe_client)(struct wiphy *wiphy, struct net_device *dev,
                                const u8 *peer, u64 *cookie);
@@@ -2638,6 -2667,7 +2667,7 @@@ struct ieee80211_iface_limit 
   *    between infrastructure and AP types must match. This is required
   *    only in special cases.
   * @radar_detect_widths: bitmap of channel widths supported for radar detection
+  * @radar_detect_regions: bitmap of regions supported for radar detection
   *
   * With this structure the driver can describe which interface
   * combinations it supports concurrently.
@@@ -2695,6 -2725,7 +2725,7 @@@ struct ieee80211_iface_combination 
        u8 n_limits;
        bool beacon_int_infra_match;
        u8 radar_detect_widths;
+       u8 radar_detect_regions;
  };
  
  struct ieee80211_txrx_stypes {
@@@ -2925,6 -2956,17 +2956,17 @@@ struct wiphy_vendor_command 
   *    (including P2P GO) or 0 to indicate no such limit is advertised. The
   *    driver is allowed to advertise a theoretical limit that it can reach in
   *    some cases, but may not always reach.
+  *
+  * @max_num_csa_counters: Number of supported csa_counters in beacons
+  *    and probe responses.  This value should be set if the driver
+  *    wishes to limit the number of csa counters. Default (0) means
+  *    infinite.
+  * @max_adj_channel_rssi_comp: max offset of between the channel on which the
+  *    frame was sent and the channel on which the frame was heard for which
+  *    the reported rssi is still valid. If a driver is able to compensate the
+  *    low rssi when a frame is heard on different channel, then it should set
+  *    this variable to the maximal offset for which it can compensate.
+  *    This value should be set in MHz.
   */
  struct wiphy {
        /* assign these fields before you register the wiphy */
  
        u16 max_ap_assoc_sta;
  
+       u8 max_num_csa_counters;
+       u8 max_adj_channel_rssi_comp;
        char priv[0] __aligned(NETDEV_ALIGN);
  };
  
@@@ -3270,7 -3315,7 +3315,7 @@@ struct wireless_dev 
                struct cfg80211_ibss_params ibss;
                struct cfg80211_connect_params connect;
                struct cfg80211_cached_keys *keys;
-               u8 *ie;
+               const u8 *ie;
                size_t ie_len;
                u8 bssid[ETH_ALEN], prev_bssid[ETH_ALEN];
                u8 ssid[IEEE80211_MAX_SSID_LEN];
@@@ -3511,7 -3556,8 +3556,8 @@@ int ieee80211_data_to_8023(struct sk_bu
   * Return: 0 on success, or a negative error code.
   */
  int ieee80211_data_from_8023(struct sk_buff *skb, const u8 *addr,
-                            enum nl80211_iftype iftype, u8 *bssid, bool qos);
+                            enum nl80211_iftype iftype, const u8 *bssid,
+                            bool qos);
  
  /**
   * ieee80211_amsdu_to_8023s - decode an IEEE 802.11n A-MSDU frame
@@@ -3691,18 -3737,6 +3737,18 @@@ void cfg80211_sched_scan_results(struc
   */
  void cfg80211_sched_scan_stopped(struct wiphy *wiphy);
  
 +/**
 + * cfg80211_sched_scan_stopped_rtnl - notify that the scheduled scan has stopped
 + *
 + * @wiphy: the wiphy on which the scheduled scan stopped
 + *
 + * The driver can call this function to inform cfg80211 that the
 + * scheduled scan had to be stopped, for whatever reason.  The driver
 + * is then called back via the sched_scan_stop operation when done.
 + * This function should be called with rtnl locked.
 + */
 +void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy);
 +
  /**
   * cfg80211_inform_bss_width_frame - inform cfg80211 of a received BSS frame
   *
@@@ -4312,7 -4346,7 +4358,7 @@@ void cfg80211_roamed_bss(struct net_dev
   * and not try to connect to any AP any more.
   */
  void cfg80211_disconnected(struct net_device *dev, u16 reason,
-                          u8 *ie, size_t ie_len, gfp_t gfp);
+                          const u8 *ie, size_t ie_len, gfp_t gfp);
  
  /**
   * cfg80211_ready_on_channel - notification of remain_on_channel start
@@@ -4768,6 -4802,35 +4814,35 @@@ int cfg80211_iter_combinations(struct w
                                            void *data),
                               void *data);
  
+ /*
+  * cfg80211_stop_iface - trigger interface disconnection
+  *
+  * @wiphy: the wiphy
+  * @wdev: wireless device
+  * @gfp: context flags
+  *
+  * Trigger interface to be stopped as if AP was stopped, IBSS/mesh left, STA
+  * disconnected.
+  *
+  * Note: This doesn't need any locks and is asynchronous.
+  */
+ void cfg80211_stop_iface(struct wiphy *wiphy, struct wireless_dev *wdev,
+                        gfp_t gfp);
+ /**
+  * cfg80211_shutdown_all_interfaces - shut down all interfaces for a wiphy
+  * @wiphy: the wiphy to shut down
+  *
+  * This function shuts down all interfaces belonging to this wiphy by
+  * calling dev_close() (and treating non-netdev interfaces as needed).
+  * It shouldn't really be used unless there are some fatal device errors
+  * that really can't be recovered in any other way.
+  *
+  * Callers must hold the RTNL and be able to deal with callbacks into
+  * the driver while the function is running.
+  */
+ void cfg80211_shutdown_all_interfaces(struct wiphy *wiphy);
  /* Logging, debugging and troubleshooting/diagnostic helpers. */
  
  /* wiphy_printk helpers, similar to dev_printk */
diff --combined net/mac80211/chan.c
index 48e6d6f010cd0f26acd379fea0c601bf8d67e33f,3702d642cd8f77bad58e23863efcfc4275db0418..a310e33972de8881bf4dd71bdff36d55fa966226
@@@ -429,7 -429,7 +429,7 @@@ static int ieee80211_add_chanctx(struc
  
        if (!local->use_chanctx) {
                local->_oper_chandef = ctx->conf.def;
 -              ieee80211_hw_config(local, 0);
 +              ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
        } else {
                err = drv_add_chanctx(local, ctx);
                if (err) {
@@@ -485,7 -485,7 +485,7 @@@ static void ieee80211_del_chanctx(struc
  
                local->hw.conf.radar_enabled = false;
  
 -              ieee80211_hw_config(local, 0);
 +              ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
        } else {
                drv_remove_chanctx(local, ctx);
        }
@@@ -702,13 -702,6 +702,13 @@@ void ieee80211_recalc_smps_chanctx(stru
                rx_chains_static = max(rx_chains_static, needed_static);
                rx_chains_dynamic = max(rx_chains_dynamic, needed_dynamic);
        }
 +
 +      /* Disable SMPS for the monitor interface */
 +      sdata = rcu_dereference(local->monitor_sdata);
 +      if (sdata &&
 +          rcu_access_pointer(sdata->vif.chanctx_conf) == &chanctx->conf)
 +              rx_chains_dynamic = rx_chains_static = local->rx_chains;
 +
        rcu_read_unlock();
  
        if (!local->use_chanctx) {
@@@ -855,7 -848,7 +855,7 @@@ static voi
  __ieee80211_vif_copy_chanctx_to_vlans(struct ieee80211_sub_if_data *sdata,
                                      bool clear)
  {
-       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_local *local __maybe_unused = sdata->local;
        struct ieee80211_sub_if_data *vlan;
        struct ieee80211_chanctx_conf *conf;
  
         * to a channel context that has already been freed.
         */
        conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
-                               lockdep_is_held(&local->chanctx_mtx));
+                                        lockdep_is_held(&local->chanctx_mtx));
        WARN_ON(!conf);
  
        if (clear)
diff --combined net/mac80211/main.c
index 27b9364cdf177d8f28e410bf50eff708bc40e424,767335f0ca2f6aa65a8888847e02e03f60aee905..d17c26d6e369f8db71061f3c73f4f27196ed9e3d
@@@ -148,8 -148,6 +148,8 @@@ static u32 ieee80211_hw_conf_chan(struc
        list_for_each_entry_rcu(sdata, &local->interfaces, list) {
                if (!rcu_access_pointer(sdata->vif.chanctx_conf))
                        continue;
 +              if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
 +                      continue;
                power = min(power, sdata->vif.bss_conf.txpower);
        }
        rcu_read_unlock();
@@@ -201,7 -199,7 +201,7 @@@ void ieee80211_bss_info_change_notify(s
  {
        struct ieee80211_local *local = sdata->local;
  
 -      if (!changed)
 +      if (!changed || sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
                return;
  
        drv_bss_info_changed(local, sdata, &sdata->vif.bss_conf, changed);
@@@ -956,6 -954,8 +956,8 @@@ int ieee80211_register_hw(struct ieee80
        if (local->hw.wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)
                local->hw.wiphy->flags |= WIPHY_FLAG_TDLS_EXTERNAL_SETUP;
  
+       local->hw.wiphy->max_num_csa_counters = IEEE80211_MAX_CSA_COUNTERS_NUM;
        result = wiphy_register(local->hw.wiphy);
        if (result < 0)
                goto fail_wiphy_register;
diff --combined net/mac80211/trace.h
index cec5b60487a4032e2b805df374616ea9ad038669,942f64b8ce0ef270a89e58ee2d9c845959516ab1..762e4cd163869e58baedae86751534020ebc0d5c
  
  #define VIF_ENTRY     __field(enum nl80211_iftype, vif_type) __field(void *, sdata)   \
                        __field(bool, p2p)                                              \
 -                      __string(vif_name, sdata->dev ? sdata->dev->name : "<nodev>")
 +                      __string(vif_name, sdata->name)
  #define VIF_ASSIGN    __entry->vif_type = sdata->vif.type; __entry->sdata = sdata;    \
                        __entry->p2p = sdata->vif.p2p;                                  \
 -                      __assign_str(vif_name, sdata->dev ? sdata->dev->name : sdata->name)
 +                      __assign_str(vif_name, sdata->name)
  #define VIF_PR_FMT    " vif:%s(%d%s)"
  #define VIF_PR_ARG    __get_str(vif_name), __entry->vif_type, __entry->p2p ? "/p2p" : ""
  
@@@ -184,6 -184,20 +184,20 @@@ TRACE_EVENT(drv_return_bool
                  "true" : "false")
  );
  
+ TRACE_EVENT(drv_return_u32,
+       TP_PROTO(struct ieee80211_local *local, u32 ret),
+       TP_ARGS(local, ret),
+       TP_STRUCT__entry(
+               LOCAL_ENTRY
+               __field(u32, ret)
+       ),
+       TP_fast_assign(
+               LOCAL_ASSIGN;
+               __entry->ret = ret;
+       ),
+       TP_printk(LOCAL_PR_FMT " - %u", LOCAL_PR_ARG, __entry->ret)
+ );
  TRACE_EVENT(drv_return_u64,
        TP_PROTO(struct ieee80211_local *local, u64 ret),
        TP_ARGS(local, ret),
@@@ -1499,6 -1513,24 +1513,24 @@@ DEFINE_EVENT(local_sdata_evt, drv_leave
        TP_ARGS(local, sdata)
  );
  
+ TRACE_EVENT(drv_get_expected_throughput,
+       TP_PROTO(struct ieee80211_sta *sta),
+       TP_ARGS(sta),
+       TP_STRUCT__entry(
+               STA_ENTRY
+       ),
+       TP_fast_assign(
+               STA_ASSIGN;
+       ),
+       TP_printk(
+               STA_PR_FMT, STA_PR_ARG
+       )
+ );
  /*
   * Tracing for API calls that drivers call.
   */
diff --combined net/mac80211/util.c
index c08bd4aca6bb8b5c1e1e0c57abd356081610f711,7e0dd4be80970bff8b1fffe23755a34dc1330bab..6886601afe1c731c3cc7b5409745307b2f48e67c
@@@ -1457,6 -1457,44 +1457,44 @@@ void ieee80211_stop_device(struct ieee8
        drv_stop(local);
  }
  
+ static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)
+ {
+       struct ieee80211_sub_if_data *sdata;
+       struct ieee80211_chanctx *ctx;
+       /*
+        * We get here if during resume the device can't be restarted properly.
+        * We might also get here if this happens during HW reset, which is a
+        * slightly different situation and we need to drop all connections in
+        * the latter case.
+        *
+        * Ask cfg80211 to turn off all interfaces, this will result in more
+        * warnings but at least we'll then get into a clean stopped state.
+        */
+       local->resuming = false;
+       local->suspended = false;
+       local->started = false;
+       /* scheduled scan clearly can't be running any more, but tell
+        * cfg80211 and clear local state
+        */
+       ieee80211_sched_scan_end(local);
+       list_for_each_entry(sdata, &local->interfaces, list)
+               sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER;
+       /* Mark channel contexts as not being in the driver any more to avoid
+        * removing them from the driver during the shutdown process...
+        */
+       mutex_lock(&local->chanctx_mtx);
+       list_for_each_entry(ctx, &local->chanctx_list, list)
+               ctx->driver_present = false;
+       mutex_unlock(&local->chanctx_mtx);
+       cfg80211_shutdown_all_interfaces(local->hw.wiphy);
+ }
  static void ieee80211_assign_chanctx(struct ieee80211_local *local,
                                     struct ieee80211_sub_if_data *sdata)
  {
@@@ -1520,9 -1558,11 +1558,11 @@@ int ieee80211_reconfig(struct ieee80211
         */
        res = drv_start(local);
        if (res) {
-               WARN(local->suspended, "Hardware became unavailable "
-                    "upon resume. This could be a software issue "
-                    "prior to suspend or a hardware issue.\n");
+               if (local->suspended)
+                       WARN(1, "Hardware became unavailable upon resume. This could be a software issue prior to suspend or a hardware issue.\n");
+               else
+                       WARN(1, "Hardware became unavailable during restart.\n");
+               ieee80211_handle_reconfig_failure(local);
                return res;
        }
  
        mutex_unlock(&local->mtx);
  
        if (sched_scan_stopped)
 -              cfg80211_sched_scan_stopped(local->hw.wiphy);
 +              cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy);
  
        /*
         * If this is for hw restart things are still running.
diff --combined net/rfkill/rfkill-gpio.c
index 9c4a5eb91cbfd6cb806bee19b3a269abc406d6c1,1cb42d040669aa1ba3c03373303e59be58a062bc..14c98e48f261ee49656eabb198d62648890b63b3
@@@ -36,6 -36,8 +36,6 @@@ struct rfkill_gpio_data 
        struct gpio_desc        *shutdown_gpio;
  
        struct rfkill           *rfkill_dev;
 -      char                    *reset_name;
 -      char                    *shutdown_name;
        struct clk              *clk;
  
        bool                    clk_enabled;
@@@ -45,17 -47,14 +45,14 @@@ static int rfkill_gpio_set_power(void *
  {
        struct rfkill_gpio_data *rfkill = data;
  
-       if (blocked) {
-               gpiod_set_value(rfkill->shutdown_gpio, 0);
-               gpiod_set_value(rfkill->reset_gpio, 0);
-               if (!IS_ERR(rfkill->clk) && rfkill->clk_enabled)
-                       clk_disable(rfkill->clk);
-       } else {
-               if (!IS_ERR(rfkill->clk) && !rfkill->clk_enabled)
-                       clk_enable(rfkill->clk);
-               gpiod_set_value(rfkill->reset_gpio, 1);
-               gpiod_set_value(rfkill->shutdown_gpio, 1);
-       }
+       if (!blocked && !IS_ERR(rfkill->clk) && !rfkill->clk_enabled)
+               clk_enable(rfkill->clk);
+       gpiod_set_value_cansleep(rfkill->shutdown_gpio, !blocked);
+       gpiod_set_value_cansleep(rfkill->reset_gpio, !blocked);
+       if (blocked && !IS_ERR(rfkill->clk) && rfkill->clk_enabled)
+               clk_disable(rfkill->clk);
  
        rfkill->clk_enabled = blocked;
  
@@@ -85,8 -84,10 +82,8 @@@ static int rfkill_gpio_probe(struct pla
  {
        struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data;
        struct rfkill_gpio_data *rfkill;
 -      const char *clk_name = NULL;
        struct gpio_desc *gpio;
        int ret;
 -      int len;
  
        rfkill = devm_kzalloc(&pdev->dev, sizeof(*rfkill), GFP_KERNEL);
        if (!rfkill)
                if (ret)
                        return ret;
        } else if (pdata) {
 -              clk_name = pdata->power_clk_name;
                rfkill->name = pdata->name;
                rfkill->type = pdata->type;
        } else {
                return -ENODEV;
        }
  
 -      len = strlen(rfkill->name);
 -      rfkill->reset_name = devm_kzalloc(&pdev->dev, len + 7, GFP_KERNEL);
 -      if (!rfkill->reset_name)
 -              return -ENOMEM;
 -
 -      rfkill->shutdown_name = devm_kzalloc(&pdev->dev, len + 10, GFP_KERNEL);
 -      if (!rfkill->shutdown_name)
 -              return -ENOMEM;
 -
 -      snprintf(rfkill->reset_name, len + 6 , "%s_reset", rfkill->name);
 -      snprintf(rfkill->shutdown_name, len + 9, "%s_shutdown", rfkill->name);
 -
 -      rfkill->clk = devm_clk_get(&pdev->dev, clk_name);
 +      rfkill->clk = devm_clk_get(&pdev->dev, NULL);
  
 -      gpio = devm_gpiod_get_index(&pdev->dev, rfkill->reset_name, 0);
 +      gpio = devm_gpiod_get_index(&pdev->dev, "reset", 0);
        if (!IS_ERR(gpio)) {
                ret = gpiod_direction_output(gpio, 0);
                if (ret)
                rfkill->reset_gpio = gpio;
        }
  
 -      gpio = devm_gpiod_get_index(&pdev->dev, rfkill->shutdown_name, 1);
 +      gpio = devm_gpiod_get_index(&pdev->dev, "shutdown", 1);
        if (!IS_ERR(gpio)) {
                ret = gpiod_direction_output(gpio, 0);
                if (ret)
                return -EINVAL;
        }
  
 -      if (pdata && pdata->gpio_runtime_setup) {
 -              ret = pdata->gpio_runtime_setup(pdev);
 -              if (ret) {
 -                      dev_err(&pdev->dev, "can't set up gpio\n");
 -                      return ret;
 -              }
 -      }
 -
        rfkill->rfkill_dev = rfkill_alloc(rfkill->name, &pdev->dev,
                                          rfkill->type, &rfkill_gpio_ops,
                                          rfkill);
  static int rfkill_gpio_remove(struct platform_device *pdev)
  {
        struct rfkill_gpio_data *rfkill = platform_get_drvdata(pdev);
 -      struct rfkill_gpio_platform_data *pdata = pdev->dev.platform_data;
  
 -      if (pdata && pdata->gpio_runtime_close)
 -              pdata->gpio_runtime_close(pdev);
        rfkill_unregister(rfkill->rfkill_dev);
        rfkill_destroy(rfkill->rfkill_dev);
  
        return 0;
  }
  
 +#ifdef CONFIG_ACPI
  static const struct acpi_device_id rfkill_acpi_match[] = {
 +      { "BCM2E1A", RFKILL_TYPE_BLUETOOTH },
 +      { "BCM2E39", RFKILL_TYPE_BLUETOOTH },
 +      { "BCM2E3D", RFKILL_TYPE_BLUETOOTH },
        { "BCM4752", RFKILL_TYPE_GPS },
 +      { "LNV4752", RFKILL_TYPE_GPS },
        { },
  };
 +#endif
  
  static struct platform_driver rfkill_gpio_driver = {
        .probe = rfkill_gpio_probe,
diff --combined net/wireless/scan.c
index e7329bb6a323c95d0a3297f9fc928780f9bc7f66,77c56eef0574874cb135545938f6cf247cacfa6e..0798c62e60858cb81d1df3d4829414665808268b
@@@ -284,22 -284,14 +284,22 @@@ void cfg80211_sched_scan_results(struc
  }
  EXPORT_SYMBOL(cfg80211_sched_scan_results);
  
 -void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
 +void cfg80211_sched_scan_stopped_rtnl(struct wiphy *wiphy)
  {
        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wiphy);
  
 +      ASSERT_RTNL();
 +
        trace_cfg80211_sched_scan_stopped(wiphy);
  
 -      rtnl_lock();
        __cfg80211_stop_sched_scan(rdev, true);
 +}
 +EXPORT_SYMBOL(cfg80211_sched_scan_stopped_rtnl);
 +
 +void cfg80211_sched_scan_stopped(struct wiphy *wiphy)
 +{
 +      rtnl_lock();
 +      cfg80211_sched_scan_stopped_rtnl(wiphy);
        rtnl_unlock();
  }
  EXPORT_SYMBOL(cfg80211_sched_scan_stopped);
@@@ -891,6 -883,7 +891,7 @@@ cfg80211_inform_bss_width(struct wiphy 
        struct cfg80211_bss_ies *ies;
        struct ieee80211_channel *channel;
        struct cfg80211_internal_bss tmp = {}, *res;
+       bool signal_valid;
  
        if (WARN_ON(!wiphy))
                return NULL;
        rcu_assign_pointer(tmp.pub.beacon_ies, ies);
        rcu_assign_pointer(tmp.pub.ies, ies);
  
-       res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp,
-                                 rx_channel == channel);
+       signal_valid = abs(rx_channel->center_freq - channel->center_freq) <=
+               wiphy->max_adj_channel_rssi_comp;
+       res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid);
        if (!res)
                return NULL;
  
@@@ -952,6 -946,7 +954,7 @@@ cfg80211_inform_bss_width_frame(struct 
        struct cfg80211_internal_bss tmp = {}, *res;
        struct cfg80211_bss_ies *ies;
        struct ieee80211_channel *channel;
+       bool signal_valid;
        size_t ielen = len - offsetof(struct ieee80211_mgmt,
                                      u.probe_resp.variable);
  
        tmp.pub.beacon_interval = le16_to_cpu(mgmt->u.probe_resp.beacon_int);
        tmp.pub.capability = le16_to_cpu(mgmt->u.probe_resp.capab_info);
  
-       res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp,
-                                 rx_channel == channel);
+       signal_valid = abs(rx_channel->center_freq - channel->center_freq) <=
+               wiphy->max_adj_channel_rssi_comp;
+       res = cfg80211_bss_update(wiphy_to_rdev(wiphy), &tmp, signal_valid);
        if (!res)
                return NULL;
  
diff --combined net/wireless/sme.c
index 0c0844b585d1e833a39a132b4339479d35a517cd,ea701bbacc6add3f339517d08e0ff5681aca2783..8bbeeb302216223a260085634bf6b5627c209783
@@@ -149,7 -149,8 +149,8 @@@ static int cfg80211_conn_do_work(struc
        case CFG80211_CONN_SCAN_AGAIN:
                return cfg80211_conn_scan(wdev);
        case CFG80211_CONN_AUTHENTICATE_NEXT:
-               BUG_ON(!rdev->ops->auth);
+               if (WARN_ON(!rdev->ops->auth))
+                       return -EOPNOTSUPP;
                wdev->conn->state = CFG80211_CONN_AUTHENTICATING;
                return cfg80211_mlme_auth(rdev, wdev->netdev,
                                          params->channel, params->auth_type,
        case CFG80211_CONN_AUTH_FAILED:
                return -ENOTCONN;
        case CFG80211_CONN_ASSOCIATE_NEXT:
-               BUG_ON(!rdev->ops->assoc);
+               if (WARN_ON(!rdev->ops->assoc))
+                       return -EOPNOTSUPP;
                wdev->conn->state = CFG80211_CONN_ASSOCIATING;
                if (wdev->conn->prev_bssid_valid)
                        req.prev_bssid = wdev->conn->prev_bssid;
@@@ -234,6 -236,7 +236,6 @@@ void cfg80211_conn_work(struct work_str
                                        NULL, 0, NULL, 0,
                                        WLAN_STATUS_UNSPECIFIED_FAILURE,
                                        false, NULL);
 -                      cfg80211_sme_free(wdev);
                }
                wdev_unlock(wdev);
        }
@@@ -646,7 -649,6 +648,7 @@@ void __cfg80211_connect_result(struct n
                        cfg80211_unhold_bss(bss_from_pub(bss));
                        cfg80211_put_bss(wdev->wiphy, bss);
                }
 +              cfg80211_sme_free(wdev);
                return;
        }
  
@@@ -877,7 -879,7 +879,7 @@@ void __cfg80211_disconnected(struct net
  }
  
  void cfg80211_disconnected(struct net_device *dev, u16 reason,
-                          u8 *ie, size_t ie_len, gfp_t gfp)
+                          const u8 *ie, size_t ie_len, gfp_t gfp)
  {
        struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);