Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac802...
authorJohn W. Linville <linville@tuxdriver.com>
Mon, 2 Dec 2013 19:25:38 +0000 (14:25 -0500)
committerJohn W. Linville <linville@tuxdriver.com>
Mon, 2 Dec 2013 19:25:38 +0000 (14:25 -0500)
1  2 
drivers/net/wireless/ath/ath10k/mac.c
drivers/net/wireless/ath/regd.c
drivers/net/wireless/brcm80211/brcmfmac/p2p.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/ipw2x00/ipw2200.c
drivers/net/wireless/mac80211_hwsim.c
drivers/net/wireless/mwifiex/cfg80211.c
net/mac80211/rate.h
net/mac80211/trace.h
net/wireless/core.h
net/wireless/nl80211.c

@@@ -92,7 -92,7 +92,7 @@@ static int ath10k_install_key(struct at
  
        lockdep_assert_held(&ar->conf_mutex);
  
 -      INIT_COMPLETION(ar->install_key_done);
 +      reinit_completion(&ar->install_key_done);
  
        ret = ath10k_send_key(arvif, key, cmd, macaddr);
        if (ret)
@@@ -438,7 -438,7 +438,7 @@@ static int ath10k_vdev_start(struct ath
  
        lockdep_assert_held(&ar->conf_mutex);
  
 -      INIT_COMPLETION(ar->vdev_setup_done);
 +      reinit_completion(&ar->vdev_setup_done);
  
        arg.vdev_id = arvif->vdev_id;
        arg.dtim_period = arvif->dtim_period;
@@@ -491,7 -491,7 +491,7 @@@ static int ath10k_vdev_stop(struct ath1
  
        lockdep_assert_held(&ar->conf_mutex);
  
 -      INIT_COMPLETION(ar->vdev_setup_done);
 +      reinit_completion(&ar->vdev_setup_done);
  
        ret = ath10k_wmi_vdev_stop(ar, arvif->vdev_id);
        if (ret) {
@@@ -1351,12 -1351,12 +1351,12 @@@ static int ath10k_update_channel_list(s
                        ch->allow_vht = true;
  
                        ch->allow_ibss =
-                               !(channel->flags & IEEE80211_CHAN_NO_IBSS);
+                               !(channel->flags & IEEE80211_CHAN_NO_IR);
  
                        ch->ht40plus =
                                !(channel->flags & IEEE80211_CHAN_NO_HT40PLUS);
  
-                       passive = channel->flags & IEEE80211_CHAN_PASSIVE_SCAN;
+                       passive = channel->flags & IEEE80211_CHAN_NO_IR;
                        ch->passive = passive;
  
                        ch->freq = channel->center_freq;
@@@ -1666,7 -1666,7 +1666,7 @@@ void ath10k_offchan_tx_work(struct work
                }
  
                spin_lock_bh(&ar->data_lock);
 -              INIT_COMPLETION(ar->offchan_tx_completed);
 +              reinit_completion(&ar->offchan_tx_completed);
                ar->offchan_tx_skb = skb;
                spin_unlock_bh(&ar->data_lock);
  
@@@ -2476,8 -2476,8 +2476,8 @@@ static int ath10k_hw_scan(struct ieee80
                goto exit;
        }
  
 -      INIT_COMPLETION(ar->scan.started);
 -      INIT_COMPLETION(ar->scan.completed);
 +      reinit_completion(&ar->scan.started);
 +      reinit_completion(&ar->scan.completed);
        ar->scan.in_progress = true;
        ar->scan.aborting = false;
        ar->scan.is_roc = false;
@@@ -2832,9 -2832,9 +2832,9 @@@ static int ath10k_remain_on_channel(str
                goto exit;
        }
  
 -      INIT_COMPLETION(ar->scan.started);
 -      INIT_COMPLETION(ar->scan.completed);
 -      INIT_COMPLETION(ar->scan.on_channel);
 +      reinit_completion(&ar->scan.started);
 +      reinit_completion(&ar->scan.completed);
 +      reinit_completion(&ar->scan.on_channel);
        ar->scan.in_progress = true;
        ar->scan.aborting = false;
        ar->scan.is_roc = true;
@@@ -37,17 -37,18 +37,18 @@@ static int __ath_regd_init(struct ath_r
  
  /* We enable active scan on these a case by case basis by regulatory domain */
  #define ATH9K_2GHZ_CH12_13    REG_RULE(2467-10, 2472+10, 40, 0, 20,\
-                                       NL80211_RRF_PASSIVE_SCAN)
+                                        NL80211_RRF_NO_IR)
  #define ATH9K_2GHZ_CH14               REG_RULE(2484-10, 2484+10, 40, 0, 20,\
-                               NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_OFDM)
+                                        NL80211_RRF_NO_IR | \
+                                        NL80211_RRF_NO_OFDM)
  
  /* We allow IBSS on these on a case by case basis by regulatory domain */
  #define ATH9K_5GHZ_5150_5350  REG_RULE(5150-10, 5350+10, 80, 0, 30,\
-                               NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+                                        NL80211_RRF_NO_IR)
  #define ATH9K_5GHZ_5470_5850  REG_RULE(5470-10, 5850+10, 80, 0, 30,\
-                               NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+                                        NL80211_RRF_NO_IR)
  #define ATH9K_5GHZ_5725_5850  REG_RULE(5725-10, 5850+10, 80, 0, 30,\
-                               NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS)
+                                        NL80211_RRF_NO_IR)
  
  #define ATH9K_2GHZ_ALL                ATH9K_2GHZ_CH01_11, \
                                ATH9K_2GHZ_CH12_13, \
@@@ -223,18 -224,11 +224,11 @@@ ath_reg_apply_beaconing_flags(struct wi
                                 * default during init, prior to calling our
                                 * regulatory_hint().
                                 */
-                               if (!(reg_rule->flags &
-                                   NL80211_RRF_NO_IBSS))
-                                       ch->flags &=
-                                         ~IEEE80211_CHAN_NO_IBSS;
-                               if (!(reg_rule->flags &
-                                   NL80211_RRF_PASSIVE_SCAN))
-                                       ch->flags &=
-                                         ~IEEE80211_CHAN_PASSIVE_SCAN;
+                               if (!(reg_rule->flags & NL80211_RRF_NO_IR))
+                                       ch->flags &= ~IEEE80211_CHAN_NO_IR;
                        } else {
                                if (ch->beacon_found)
-                                       ch->flags &= ~(IEEE80211_CHAN_NO_IBSS |
-                                         IEEE80211_CHAN_PASSIVE_SCAN);
+                                       ch->flags &= ~IEEE80211_CHAN_NO_IR;
                        }
                }
        }
@@@ -260,11 -254,11 +254,11 @@@ ath_reg_apply_active_scan_flags(struct 
         */
        if (initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE) {
                ch = &sband->channels[11]; /* CH 12 */
-               if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-                       ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+               if (ch->flags & IEEE80211_CHAN_NO_IR)
+                       ch->flags &= ~IEEE80211_CHAN_NO_IR;
                ch = &sband->channels[12]; /* CH 13 */
-               if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-                       ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+               if (ch->flags & IEEE80211_CHAN_NO_IR)
+                       ch->flags &= ~IEEE80211_CHAN_NO_IR;
                return;
        }
  
        ch = &sband->channels[11]; /* CH 12 */
        reg_rule = freq_reg_info(wiphy, ch->center_freq);
        if (!IS_ERR(reg_rule)) {
-               if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
-                       if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-                               ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+               if (!(reg_rule->flags & NL80211_RRF_NO_IR))
+                       if (ch->flags & IEEE80211_CHAN_NO_IR)
+                               ch->flags &= ~IEEE80211_CHAN_NO_IR;
        }
  
        ch = &sband->channels[12]; /* CH 13 */
        reg_rule = freq_reg_info(wiphy, ch->center_freq);
        if (!IS_ERR(reg_rule)) {
-               if (!(reg_rule->flags & NL80211_RRF_PASSIVE_SCAN))
-                       if (ch->flags & IEEE80211_CHAN_PASSIVE_SCAN)
-                               ch->flags &= ~IEEE80211_CHAN_PASSIVE_SCAN;
+               if (!(reg_rule->flags & NL80211_RRF_NO_IR))
+                       if (ch->flags & IEEE80211_CHAN_NO_IR)
+                               ch->flags &= ~IEEE80211_CHAN_NO_IR;
        }
  }
  
@@@ -320,8 -314,7 +314,7 @@@ static void ath_reg_apply_radar_flags(s
                 */
                if (!(ch->flags & IEEE80211_CHAN_DISABLED))
                        ch->flags |= IEEE80211_CHAN_RADAR |
-                                    IEEE80211_CHAN_NO_IBSS |
-                                    IEEE80211_CHAN_PASSIVE_SCAN;
+                                    IEEE80211_CHAN_NO_IR;
        }
  }
  
@@@ -362,8 -355,7 +355,8 @@@ static int __ath_reg_dyn_country(struc
  {
        u16 country_code;
  
 -      if (!ath_is_world_regd(reg))
 +      if (request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE &&
 +          !ath_is_world_regd(reg))
                return -EINVAL;
  
        country_code = ath_regd_find_country_by_name(request->alpha2);
@@@ -609,7 -601,7 +602,7 @@@ ath_regd_init_wiphy(struct ath_regulato
        const struct ieee80211_regdomain *regd;
  
        wiphy->reg_notifier = reg_notifier;
-       wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
+       wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
  
        if (ath_is_world_regd(reg)) {
                /*
                 * saved on the wiphy orig_* parameters
                 */
                regd = ath_world_regdomain(reg);
-               wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+               wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG |
+                                          REGULATORY_COUNTRY_IE_FOLLOW_POWER;
        } else {
                /*
                 * This gets applied in the case of the absence of CRDA,
@@@ -812,7 -812,7 +812,7 @@@ static s32 brcmf_p2p_run_escan(struct b
                        struct ieee80211_channel *chan = request->channels[i];
  
                        if (chan->flags & (IEEE80211_CHAN_RADAR |
-                                          IEEE80211_CHAN_PASSIVE_SCAN))
+                                          IEEE80211_CHAN_NO_IR))
                                continue;
  
                        chanspecs[i] = channel_to_chanspec(&p2p->cfg->d11inf,
                }
                err = brcmf_p2p_escan(p2p, num_nodfs, chanspecs, search_state,
                                      action, P2PAPI_BSSCFG_DEVICE);
 +              kfree(chanspecs);
        }
  exit:
        if (err)
@@@ -1149,7 -1148,7 +1149,7 @@@ static s32 brcmf_p2p_af_searching_chann
  
        pri_vif = p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif;
  
 -      INIT_COMPLETION(afx_hdl->act_frm_scan);
 +      reinit_completion(&afx_hdl->act_frm_scan);
        set_bit(BRCMF_P2P_STATUS_FINDING_COMMON_CHANNEL, &p2p->status);
        afx_hdl->is_active = true;
        afx_hdl->peer_chan = P2P_INVALID_CHANNEL;
@@@ -1502,7 -1501,7 +1502,7 @@@ static s32 brcmf_p2p_tx_action_frame(st
  
        brcmf_dbg(TRACE, "Enter\n");
  
 -      INIT_COMPLETION(p2p->send_af_done);
 +      reinit_completion(&p2p->send_af_done);
        clear_bit(BRCMF_P2P_STATUS_ACTION_TX_COMPLETED, &p2p->status);
        clear_bit(BRCMF_P2P_STATUS_ACTION_TX_NOACK, &p2p->status);
  
@@@ -202,9 -202,9 +202,9 @@@ static struct ieee80211_supported_band 
  
  /* This is to override regulatory domains defined in cfg80211 module (reg.c)
   * By default world regulatory domain defined in reg.c puts the flags
-  * NL80211_RRF_PASSIVE_SCAN and NL80211_RRF_NO_IBSS for 5GHz channels (for
-  * 36..48 and 149..165). With respect to these flags, wpa_supplicant doesn't
-  * start p2p operations on 5GHz channels. All the changes in world regulatory
+  * NL80211_RRF_NO_IR for 5GHz channels (for * 36..48 and 149..165).
+  * With respect to these flags, wpa_supplicant doesn't * start p2p
+  * operations on 5GHz channels. All the changes in world regulatory
   * domain are to be done here.
   */
  static const struct ieee80211_regdomain brcmf_regdom = {
@@@ -2556,8 -2556,8 +2556,8 @@@ brcmf_compare_update_same_bss(struct br
                ch_bss.band == ch_bss_info_le.band &&
                bss_info_le->SSID_len == bss->SSID_len &&
                !memcmp(bss_info_le->SSID, bss->SSID, bss_info_le->SSID_len)) {
 -              if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) ==
 -                      (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL)) {
 +              if ((bss->flags & BRCMF_BSS_RSSI_ON_CHANNEL) ==
 +                      (bss_info_le->flags & BRCMF_BSS_RSSI_ON_CHANNEL)) {
                        s16 bss_rssi = le16_to_cpu(bss->RSSI);
                        s16 bss_info_rssi = le16_to_cpu(bss_info_le->RSSI);
  
                        */
                        if (bss_info_rssi > bss_rssi)
                                bss->RSSI = bss_info_le->RSSI;
 -              } else if ((bss->flags & WLC_BSS_RSSI_ON_CHANNEL) &&
 -                      (bss_info_le->flags & WLC_BSS_RSSI_ON_CHANNEL) == 0) {
 +              } else if ((bss->flags & BRCMF_BSS_RSSI_ON_CHANNEL) &&
 +                      (bss_info_le->flags & BRCMF_BSS_RSSI_ON_CHANNEL) == 0) {
                        /* preserve the on-channel rssi measurement
                        * if the new measurement is off channel
                        */
                        bss->RSSI = bss_info_le->RSSI;
 -                      bss->flags |= WLC_BSS_RSSI_ON_CHANNEL;
 +                      bss->flags |= BRCMF_BSS_RSSI_ON_CHANNEL;
                }
                return 1;
        }
@@@ -3973,11 -3973,12 +3973,12 @@@ brcmf_cfg80211_mgmt_frame_register(stru
  
  static int
  brcmf_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
-                      struct ieee80211_channel *chan, bool offchan,
-                      unsigned int wait, const u8 *buf, size_t len,
-                      bool no_cck, bool dont_wait_for_ack, u64 *cookie)
+                      struct cfg80211_mgmt_tx_params *params, u64 *cookie)
  {
        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
+       struct ieee80211_channel *chan = params->chan;
+       const u8 *buf = params->buf;
+       size_t len = params->len;
        const struct ieee80211_mgmt *mgmt;
        struct brcmf_cfg80211_vif *vif;
        s32 err = 0;
@@@ -4341,7 -4342,7 +4342,7 @@@ static struct wiphy *brcmf_setup_wiphy(
        wiphy->max_remain_on_channel_duration = 5000;
        brcmf_wiphy_pno_params(wiphy);
        brcmf_dbg(INFO, "Registering custom regulatory\n");
-       wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+       wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
        wiphy_apply_custom_regulatory(wiphy, &brcmf_regdom);
        err = wiphy_register(wiphy);
        if (err < 0) {
@@@ -5197,10 -5198,10 +5198,10 @@@ static s32 brcmf_construct_reginfo(stru
                                        if (channel & WL_CHAN_RADAR)
                                                band_chan_arr[index].flags |=
                                                        (IEEE80211_CHAN_RADAR |
-                                                       IEEE80211_CHAN_NO_IBSS);
+                                                       IEEE80211_CHAN_NO_IR);
                                        if (channel & WL_CHAN_PASSIVE)
                                                band_chan_arr[index].flags |=
-                                                   IEEE80211_CHAN_PASSIVE_SCAN;
+                                                   IEEE80211_CHAN_NO_IR;
                                }
                        }
                        if (!update)
@@@ -2698,7 -2698,7 +2698,7 @@@ static u16 eeprom_read_u16(struct ipw_p
  /* data's copy of the eeprom data                                 */
  static void eeprom_parse_mac(struct ipw_priv *priv, u8 * mac)
  {
 -      memcpy(mac, &priv->eeprom[EEPROM_MAC_ADDRESS], 6);
 +      memcpy(mac, &priv->eeprom[EEPROM_MAC_ADDRESS], ETH_ALEN);
  }
  
  static void ipw_read_eeprom(struct ipw_priv *priv)
@@@ -11472,10 -11472,10 +11472,10 @@@ static int ipw_wdev_init(struct net_dev
                        bg_band->channels[i].max_power = geo->bg[i].max_power;
                        if (geo->bg[i].flags & LIBIPW_CH_PASSIVE_ONLY)
                                bg_band->channels[i].flags |=
-                                       IEEE80211_CHAN_PASSIVE_SCAN;
+                                       IEEE80211_CHAN_NO_IR;
                        if (geo->bg[i].flags & LIBIPW_CH_NO_IBSS)
                                bg_band->channels[i].flags |=
-                                       IEEE80211_CHAN_NO_IBSS;
+                                       IEEE80211_CHAN_NO_IR;
                        if (geo->bg[i].flags & LIBIPW_CH_RADAR_DETECT)
                                bg_band->channels[i].flags |=
                                        IEEE80211_CHAN_RADAR;
                        a_band->channels[i].max_power = geo->a[i].max_power;
                        if (geo->a[i].flags & LIBIPW_CH_PASSIVE_ONLY)
                                a_band->channels[i].flags |=
-                                       IEEE80211_CHAN_PASSIVE_SCAN;
+                                       IEEE80211_CHAN_NO_IR;
                        if (geo->a[i].flags & LIBIPW_CH_NO_IBSS)
                                a_band->channels[i].flags |=
-                                       IEEE80211_CHAN_NO_IBSS;
+                                       IEEE80211_CHAN_NO_IR;
                        if (geo->a[i].flags & LIBIPW_CH_RADAR_DETECT)
                                a_band->channels[i].flags |=
                                        IEEE80211_CHAN_RADAR;
@@@ -159,7 -159,7 +159,7 @@@ static const struct ieee80211_regdomai
        .reg_rules = {
                REG_RULE(2412-10, 2462+10, 40, 0, 20, 0),
                REG_RULE(5725-10, 5850+10, 40, 0, 30,
-                       NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
+                        NL80211_RRF_NO_IR),
        }
  };
  
@@@ -353,7 -353,6 +353,6 @@@ struct mac80211_hwsim_data 
        } ps;
        bool ps_poll_pending;
        struct dentry *debugfs;
-       struct dentry *debugfs_ps;
  
        struct sk_buff_head pending;    /* packets pending */
        /*
         * radio can be in more then one group.
         */
        u64 group;
-       struct dentry *debugfs_group;
  
        int power_level;
  
@@@ -1485,7 -1483,7 +1483,7 @@@ static void hw_scan_work(struct work_st
                    req->channels[hwsim->scan_chan_idx]->center_freq);
  
        hwsim->tmp_chan = req->channels[hwsim->scan_chan_idx];
-       if (hwsim->tmp_chan->flags & IEEE80211_CHAN_PASSIVE_SCAN ||
+       if (hwsim->tmp_chan->flags & IEEE80211_CHAN_NO_IR ||
            !req->n_ssids) {
                dwell = 120;
        } else {
@@@ -1734,9 -1732,7 +1732,7 @@@ static void mac80211_hwsim_free(void
        spin_unlock_bh(&hwsim_radio_lock);
  
        list_for_each_entry_safe(data, tmpdata, &tmplist, list) {
-               debugfs_remove(data->debugfs_group);
-               debugfs_remove(data->debugfs_ps);
-               debugfs_remove(data->debugfs);
+               debugfs_remove_recursive(data->debugfs);
                ieee80211_unregister_hw(data->hw);
                device_release_driver(data->dev);
                device_unregister(data->dev);
@@@ -1893,6 -1889,17 +1889,17 @@@ static int hwsim_fops_ps_write(void *da
  DEFINE_SIMPLE_ATTRIBUTE(hwsim_fops_ps, hwsim_fops_ps_read, hwsim_fops_ps_write,
                        "%llu\n");
  
+ static int hwsim_write_simulate_radar(void *dat, u64 val)
+ {
+       struct mac80211_hwsim_data *data = dat;
+       ieee80211_radar_detected(data->hw);
+       return 0;
+ }
+ DEFINE_SIMPLE_ATTRIBUTE(hwsim_simulate_radar, NULL,
+                       hwsim_write_simulate_radar, "%llu\n");
  
  static int hwsim_fops_group_read(void *dat, u64 *val)
  {
@@@ -2097,7 -2104,7 +2104,7 @@@ out
  }
  
  /* Generic Netlink operations array */
 -static struct genl_ops hwsim_ops[] = {
 +static const struct genl_ops hwsim_ops[] = {
        {
                .cmd = HWSIM_CMD_REGISTER,
                .policy = hwsim_genl_policy,
@@@ -2148,7 -2155,8 +2155,7 @@@ static int hwsim_init_netlink(void
  
        printk(KERN_INFO "mac80211_hwsim: initializing netlink\n");
  
 -      rc = genl_register_family_with_ops(&hwsim_genl_family,
 -              hwsim_ops, ARRAY_SIZE(hwsim_ops));
 +      rc = genl_register_family_with_ops(&hwsim_genl_family, hwsim_ops);
        if (rc)
                goto failure;
  
@@@ -2193,11 -2201,28 +2200,28 @@@ static const struct ieee80211_iface_lim
        { .max = 1, .types = BIT(NL80211_IFTYPE_P2P_DEVICE) },
  };
  
- static struct ieee80211_iface_combination hwsim_if_comb = {
-       .limits = hwsim_if_limits,
-       .n_limits = ARRAY_SIZE(hwsim_if_limits),
-       .max_interfaces = 2048,
-       .num_different_channels = 1,
+ static const struct ieee80211_iface_limit hwsim_if_dfs_limits[] = {
+       { .max = 8, .types = BIT(NL80211_IFTYPE_AP) },
+ };
+ static struct ieee80211_iface_combination hwsim_if_comb[] = {
+       {
+               .limits = hwsim_if_limits,
+               .n_limits = ARRAY_SIZE(hwsim_if_limits),
+               .max_interfaces = 2048,
+               .num_different_channels = 1,
+       },
+       {
+               .limits = hwsim_if_dfs_limits,
+               .n_limits = ARRAY_SIZE(hwsim_if_dfs_limits),
+               .max_interfaces = 8,
+               .num_different_channels = 1,
+               .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+                                      BIT(NL80211_CHAN_WIDTH_20) |
+                                      BIT(NL80211_CHAN_WIDTH_40) |
+                                      BIT(NL80211_CHAN_WIDTH_80) |
+                                      BIT(NL80211_CHAN_WIDTH_160),
+       }
  };
  
  static int __init init_mac80211_hwsim(void)
                return -EINVAL;
  
        if (channels > 1) {
-               hwsim_if_comb.num_different_channels = channels;
+               hwsim_if_comb[0].num_different_channels = channels;
                mac80211_hwsim_ops.hw_scan = mac80211_hwsim_hw_scan;
                mac80211_hwsim_ops.cancel_hw_scan =
                        mac80211_hwsim_cancel_hw_scan;
                hw->wiphy->n_addresses = 2;
                hw->wiphy->addresses = data->addresses;
  
-               hw->wiphy->iface_combinations = &hwsim_if_comb;
-               hw->wiphy->n_iface_combinations = 1;
+               hw->wiphy->iface_combinations = hwsim_if_comb;
+               hw->wiphy->n_iface_combinations = ARRAY_SIZE(hwsim_if_comb);
  
                if (channels > 1) {
                        hw->wiphy->max_scan_ssids = 255;
                        hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN;
                        hw->wiphy->max_remain_on_channel_duration = 1000;
+                       /* For channels > 1 DFS is not allowed */
+                       hw->wiphy->n_iface_combinations = 1;
                }
  
                INIT_DELAYED_WORK(&data->roc_done, hw_roc_done);
                            IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
                            IEEE80211_HW_AMPDU_AGGREGATION |
                            IEEE80211_HW_WANT_MONITOR_VIF |
-                           IEEE80211_HW_QUEUE_CONTROL;
+                           IEEE80211_HW_QUEUE_CONTROL |
+                           IEEE80211_HW_SUPPORTS_HT_CCK_RATES;
                if (rctbl)
                        hw->flags |= IEEE80211_HW_SUPPORTS_RC_TABLE;
  
                        sband->vht_cap.cap =
                                IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_11454 |
                                IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ |
+                               IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ |
                                IEEE80211_VHT_CAP_RXLDPC |
                                IEEE80211_VHT_CAP_SHORT_GI_80 |
                                IEEE80211_VHT_CAP_SHORT_GI_160 |
                        break;
                case HWSIM_REGTEST_WORLD_ROAM:
                        if (i == 0) {
-                               hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+                               hw->wiphy->regulatory_flags |=
+                                       REGULATORY_CUSTOM_REG;
                                wiphy_apply_custom_regulatory(hw->wiphy,
                                        &hwsim_world_regdom_custom_01);
                        }
                        break;
                case HWSIM_REGTEST_CUSTOM_WORLD:
-                       hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+                       hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG;
                        wiphy_apply_custom_regulatory(hw->wiphy,
                                &hwsim_world_regdom_custom_01);
                        break;
                case HWSIM_REGTEST_CUSTOM_WORLD_2:
                        if (i == 0) {
-                               hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+                               hw->wiphy->regulatory_flags |=
+                                       REGULATORY_CUSTOM_REG;
                                wiphy_apply_custom_regulatory(hw->wiphy,
                                        &hwsim_world_regdom_custom_01);
                        } else if (i == 1) {
-                               hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+                               hw->wiphy->regulatory_flags |=
+                                       REGULATORY_CUSTOM_REG;
                                wiphy_apply_custom_regulatory(hw->wiphy,
                                        &hwsim_world_regdom_custom_02);
                        }
                        break;
                case HWSIM_REGTEST_STRICT_ALL:
-                       hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
+                       hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG;
                        break;
                case HWSIM_REGTEST_STRICT_FOLLOW:
                case HWSIM_REGTEST_STRICT_AND_DRIVER_REG:
                        if (i == 0)
-                               hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
+                               hw->wiphy->regulatory_flags |=
+                                       REGULATORY_STRICT_REG;
                        break;
                case HWSIM_REGTEST_ALL:
                        if (i == 0) {
-                               hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+                               hw->wiphy->regulatory_flags |=
+                                       REGULATORY_CUSTOM_REG;
                                wiphy_apply_custom_regulatory(hw->wiphy,
                                        &hwsim_world_regdom_custom_01);
                        } else if (i == 1) {
-                               hw->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY;
+                               hw->wiphy->regulatory_flags |=
+                                       REGULATORY_CUSTOM_REG;
                                wiphy_apply_custom_regulatory(hw->wiphy,
                                        &hwsim_world_regdom_custom_02);
                        } else if (i == 4)
-                               hw->wiphy->flags |= WIPHY_FLAG_STRICT_REGULATORY;
+                               hw->wiphy->regulatory_flags |=
+                                       REGULATORY_STRICT_REG;
                        break;
                default:
                        break;
  
                data->debugfs = debugfs_create_dir("hwsim",
                                                   hw->wiphy->debugfsdir);
-               data->debugfs_ps = debugfs_create_file("ps", 0666,
-                                                      data->debugfs, data,
-                                                      &hwsim_fops_ps);
-               data->debugfs_group = debugfs_create_file("group", 0666,
-                                                       data->debugfs, data,
-                                                       &hwsim_fops_group);
+               debugfs_create_file("ps", 0666, data->debugfs, data,
+                                   &hwsim_fops_ps);
+               debugfs_create_file("group", 0666, data->debugfs, data,
+                                   &hwsim_fops_group);
+               if (channels == 1)
+                       debugfs_create_file("dfs_simulate_radar", 0222,
+                                           data->debugfs,
+                                           data, &hwsim_simulate_radar);
  
                tasklet_hrtimer_init(&data->beacon_timer,
                                     mac80211_hwsim_beacon,
-                                    CLOCK_REALTIME, HRTIMER_MODE_ABS);
+                                    CLOCK_MONOTONIC_RAW, HRTIMER_MODE_ABS);
  
                list_add_tail(&data->list, &hwsim_radios);
        }
@@@ -50,24 -50,24 +50,24 @@@ static const struct ieee80211_regdomai
                REG_RULE(2412-10, 2462+10, 40, 3, 20, 0),
                /* Channel 12 - 13 */
                REG_RULE(2467-10, 2472+10, 20, 3, 20,
-                        NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
+                        NL80211_RRF_NO_IR),
                /* Channel 14 */
                REG_RULE(2484-10, 2484+10, 20, 3, 20,
-                        NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS |
+                        NL80211_RRF_NO_IR |
                         NL80211_RRF_NO_OFDM),
                /* Channel 36 - 48 */
                REG_RULE(5180-10, 5240+10, 40, 3, 20,
-                        NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
+                        NL80211_RRF_NO_IR),
                /* Channel 149 - 165 */
                REG_RULE(5745-10, 5825+10, 40, 3, 20,
-                        NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS),
+                        NL80211_RRF_NO_IR),
                /* Channel 52 - 64 */
                REG_RULE(5260-10, 5320+10, 40, 3, 30,
-                        NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS |
+                        NL80211_RRF_NO_IR |
                         NL80211_RRF_DFS),
                /* Channel 100 - 140 */
                REG_RULE(5500-10, 5700+10, 40, 3, 30,
-                        NL80211_RRF_PASSIVE_SCAN | NL80211_RRF_NO_IBSS |
+                        NL80211_RRF_NO_IR |
                         NL80211_RRF_DFS),
        }
  };
@@@ -184,10 -184,10 +184,10 @@@ mwifiex_form_mgmt_frame(struct sk_buff 
   */
  static int
  mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
-                        struct ieee80211_channel *chan, bool offchan,
-                        unsigned int wait, const u8 *buf, size_t len,
-                        bool no_cck, bool dont_wait_for_ack, u64 *cookie)
+                        struct cfg80211_mgmt_tx_params *params, u64 *cookie)
  {
+       const u8 *buf = params->buf;
+       size_t len = params->len;
        struct sk_buff *skb;
        u16 pkt_len;
        const struct ieee80211_mgmt *mgmt;
@@@ -1968,7 -1968,7 +1968,7 @@@ mwifiex_cfg80211_scan(struct wiphy *wip
                user_scan_cfg->chan_list[i].chan_number = chan->hw_value;
                user_scan_cfg->chan_list[i].radio_type = chan->band;
  
-               if (chan->flags & IEEE80211_CHAN_PASSIVE_SCAN)
+               if (chan->flags & IEEE80211_CHAN_NO_IR)
                        user_scan_cfg->chan_list[i].scan_type =
                                                MWIFIEX_SCAN_TYPE_PASSIVE;
                else
@@@ -2210,10 -2210,8 +2210,10 @@@ struct wireless_dev *mwifiex_add_virtua
                priv->bss_started = 0;
                priv->bss_num = 0;
  
 -              if (mwifiex_cfg80211_init_p2p_client(priv))
 -                      return ERR_PTR(-EFAULT);
 +              if (mwifiex_cfg80211_init_p2p_client(priv)) {
 +                      wdev = ERR_PTR(-EFAULT);
 +                      goto done;
 +              }
  
                break;
        default:
        if (!dev) {
                wiphy_err(wiphy, "no memory available for netdevice\n");
                priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
 -              return ERR_PTR(-ENOMEM);
 +              wdev = ERR_PTR(-ENOMEM);
 +              goto done;
        }
  
        mwifiex_init_priv_params(priv, dev);
                wiphy_err(wiphy, "cannot register virtual network device\n");
                free_netdev(dev);
                priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED;
 -              return ERR_PTR(-EFAULT);
 +              priv->netdev = NULL;
 +              wdev = ERR_PTR(-EFAULT);
 +              goto done;
        }
  
        sema_init(&priv->async_sem, 1);
  #ifdef CONFIG_DEBUG_FS
        mwifiex_dev_debugfs_init(priv);
  #endif
 +
 +done:
 +      if (IS_ERR(wdev)) {
 +              kfree(priv->wdev);
 +              priv->wdev = NULL;
 +      }
 +
        return wdev;
  }
  EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf);
@@@ -2310,10 -2298,7 +2310,10 @@@ int mwifiex_del_virtual_intf(struct wip
                unregister_netdevice(wdev->netdev);
  
        /* Clear the priv in adapter */
 +      priv->netdev->ieee80211_ptr = NULL;
        priv->netdev = NULL;
 +      kfree(wdev);
 +      priv->wdev = NULL;
  
        priv->media_connected = false;
  
@@@ -2702,9 -2687,10 +2702,10 @@@ int mwifiex_register_cfg80211(struct mw
        wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
                        WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD |
                        WIPHY_FLAG_AP_UAPSD |
-                       WIPHY_FLAG_CUSTOM_REGULATORY |
-                       WIPHY_FLAG_STRICT_REGULATORY |
                        WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
+       wiphy->regulatory_flags |=
+                       REGULATORY_CUSTOM_REG |
+                       REGULATORY_STRICT_REG;
  
        wiphy_apply_custom_regulatory(wiphy, &mwifiex_world_regdom_custom);
  
diff --combined net/mac80211/rate.h
@@@ -54,6 -54,8 +54,8 @@@ static inline void rate_control_rate_in
        struct ieee80211_supported_band *sband;
        struct ieee80211_chanctx_conf *chanctx_conf;
  
+       ieee80211_sta_set_rx_nss(sta);
        if (!ref)
                return;
  
@@@ -67,8 -69,6 +69,6 @@@
  
        sband = local->hw.wiphy->bands[chanctx_conf->def.chan->band];
  
-       ieee80211_sta_set_rx_nss(sta);
        ref->ops->rate_init(ref->priv, sband, &chanctx_conf->def, ista,
                            priv_sta);
        rcu_read_unlock();
@@@ -144,8 -144,8 +144,8 @@@ void rate_control_deinitialize(struct i
  
  /* Rate control algorithms */
  #ifdef CONFIG_MAC80211_RC_PID
 -extern int rc80211_pid_init(void);
 -extern void rc80211_pid_exit(void);
 +int rc80211_pid_init(void);
 +void rc80211_pid_exit(void);
  #else
  static inline int rc80211_pid_init(void)
  {
@@@ -157,8 -157,8 +157,8 @@@ static inline void rc80211_pid_exit(voi
  #endif
  
  #ifdef CONFIG_MAC80211_RC_MINSTREL
 -extern int rc80211_minstrel_init(void);
 -extern void rc80211_minstrel_exit(void);
 +int rc80211_minstrel_init(void);
 +void rc80211_minstrel_exit(void);
  #else
  static inline int rc80211_minstrel_init(void)
  {
@@@ -170,8 -170,8 +170,8 @@@ static inline void rc80211_minstrel_exi
  #endif
  
  #ifdef CONFIG_MAC80211_RC_MINSTREL_HT
 -extern int rc80211_minstrel_ht_init(void);
 -extern void rc80211_minstrel_ht_exit(void);
 +int rc80211_minstrel_ht_init(void);
 +void rc80211_minstrel_ht_exit(void);
  #else
  static inline int rc80211_minstrel_ht_init(void)
  {
diff --combined net/mac80211/trace.h
  #define CHANDEF_PR_ARG        __entry->control_freq, __entry->chan_width,                     \
                        __entry->center_freq1, __entry->center_freq2
  
+ #define MIN_CHANDEF_ENTRY                                                             \
+                       __field(u32, min_control_freq)                                  \
+                       __field(u32, min_chan_width)                                    \
+                       __field(u32, min_center_freq1)                                  \
+                       __field(u32, min_center_freq2)
+ #define MIN_CHANDEF_ASSIGN(c)                                                         \
+                       __entry->min_control_freq = (c)->chan ? (c)->chan->center_freq : 0;     \
+                       __entry->min_chan_width = (c)->width;                           \
+                       __entry->min_center_freq1 = (c)->center_freq1;                  \
+                       __entry->min_center_freq2 = (c)->center_freq2;
+ #define MIN_CHANDEF_PR_FMT    " min_control:%d MHz min_width:%d min_center: %d/%d MHz"
+ #define MIN_CHANDEF_PR_ARG    __entry->min_control_freq, __entry->min_chan_width,     \
+                       __entry->min_center_freq1, __entry->min_center_freq2
  #define CHANCTX_ENTRY CHANDEF_ENTRY                                                   \
+                       MIN_CHANDEF_ENTRY                                               \
                        __field(u8, rx_chains_static)                                   \
                        __field(u8, rx_chains_dynamic)
  #define CHANCTX_ASSIGN        CHANDEF_ASSIGN(&ctx->conf.def)                                  \
+                       MIN_CHANDEF_ASSIGN(&ctx->conf.min_def)                          \
                        __entry->rx_chains_static = ctx->conf.rx_chains_static;         \
                        __entry->rx_chains_dynamic = ctx->conf.rx_chains_dynamic
- #define CHANCTX_PR_FMT        CHANDEF_PR_FMT " chains:%d/%d"
- #define CHANCTX_PR_ARG        CHANDEF_PR_ARG,                                                 \
+ #define CHANCTX_PR_FMT        CHANDEF_PR_FMT MIN_CHANDEF_PR_FMT " chains:%d/%d"
+ #define CHANCTX_PR_ARG        CHANDEF_PR_ARG, MIN_CHANDEF_PR_ARG,                             \
                        __entry->rx_chains_static, __entry->rx_chains_dynamic
  
  
@@@ -77,13 -94,13 +94,13 @@@ DECLARE_EVENT_CLASS(local_sdata_addr_ev
        TP_STRUCT__entry(
                LOCAL_ENTRY
                VIF_ENTRY
 -              __array(char, addr, 6)
 +              __array(char, addr, ETH_ALEN)
        ),
  
        TP_fast_assign(
                LOCAL_ASSIGN;
                VIF_ASSIGN;
 -              memcpy(__entry->addr, sdata->vif.addr, 6);
 +              memcpy(__entry->addr, sdata->vif.addr, ETH_ALEN);
        ),
  
        TP_printk(
diff --combined net/wireless/core.h
@@@ -234,10 -234,10 +234,10 @@@ struct cfg80211_beacon_registration 
  };
  
  /* free object */
 -extern void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
 +void cfg80211_dev_free(struct cfg80211_registered_device *rdev);
  
 -extern int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
 -                             char *newname);
 +int cfg80211_dev_rename(struct cfg80211_registered_device *rdev,
 +                      char *newname);
  
  void ieee80211_set_bitrate_flags(struct wiphy *wiphy);
  
@@@ -317,9 -317,8 +317,8 @@@ void cfg80211_mlme_unregister_socket(st
  void cfg80211_mlme_purge_registrations(struct wireless_dev *wdev);
  int cfg80211_mlme_mgmt_tx(struct cfg80211_registered_device *rdev,
                          struct wireless_dev *wdev,
-                         struct ieee80211_channel *chan, bool offchan,
-                         unsigned int wait, const u8 *buf, size_t len,
-                         bool no_cck, bool dont_wait_for_ack, u64 *cookie);
+                         struct cfg80211_mgmt_tx_params *params,
+                         u64 *cookie);
  void cfg80211_oper_and_ht_capa(struct ieee80211_ht_cap *ht_capa,
                               const struct ieee80211_ht_cap *ht_capa_mask);
  void cfg80211_oper_and_vht_capa(struct ieee80211_vht_cap *vht_capa,
@@@ -382,6 -381,19 +381,19 @@@ int cfg80211_can_use_iftype_chan(struc
                                 enum cfg80211_chan_mode chanmode,
                                 u8 radar_detect);
  
+ /**
+  * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable
+  * @wiphy: the wiphy to validate against
+  * @chandef: the channel definition to check
+  *
+  * Checks if chandef is usable and we can/need start CAC on such channel.
+  *
+  * Return: Return true if all channels available and at least
+  *       one channel require CAC (NL80211_DFS_USABLE)
+  */
+ bool cfg80211_chandef_dfs_usable(struct wiphy *wiphy,
+                                const struct cfg80211_chan_def *chandef);
  void cfg80211_set_dfs_state(struct wiphy *wiphy,
                            const struct cfg80211_chan_def *chandef,
                            enum nl80211_dfs_state dfs_state);
diff --combined net/wireless/nl80211.c
@@@ -30,9 -30,9 +30,9 @@@ static int nl80211_crypto_settings(stru
                                   struct cfg80211_crypto_settings *settings,
                                   int cipher_limit);
  
 -static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
 +static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
                            struct genl_info *info);
 -static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
 +static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
                              struct genl_info *info);
  
  /* the netlink family */
@@@ -47,25 -47,6 +47,25 @@@ static struct genl_family nl80211_fam 
        .post_doit = nl80211_post_doit,
  };
  
 +/* multicast groups */
 +enum nl80211_multicast_groups {
 +      NL80211_MCGRP_CONFIG,
 +      NL80211_MCGRP_SCAN,
 +      NL80211_MCGRP_REGULATORY,
 +      NL80211_MCGRP_MLME,
 +      NL80211_MCGRP_TESTMODE /* keep last - ifdef! */
 +};
 +
 +static const struct genl_multicast_group nl80211_mcgrps[] = {
 +      [NL80211_MCGRP_CONFIG] = { .name = "config", },
 +      [NL80211_MCGRP_SCAN] = { .name = "scan", },
 +      [NL80211_MCGRP_REGULATORY] = { .name = "regulatory", },
 +      [NL80211_MCGRP_MLME] = { .name = "mlme", },
 +#ifdef CONFIG_NL80211_TESTMODE
 +      [NL80211_MCGRP_TESTMODE] = { .name = "testmode", }
 +#endif
 +};
 +
  /* returns ERR_PTR values */
  static struct wireless_dev *
  __cfg80211_wdev_from_attrs(struct net *netns, struct nlattr **attrs)
@@@ -564,12 -545,12 +564,12 @@@ static int nl80211_msg_put_channel(stru
        if ((chan->flags & IEEE80211_CHAN_DISABLED) &&
            nla_put_flag(msg, NL80211_FREQUENCY_ATTR_DISABLED))
                goto nla_put_failure;
-       if ((chan->flags & IEEE80211_CHAN_PASSIVE_SCAN) &&
-           nla_put_flag(msg, NL80211_FREQUENCY_ATTR_PASSIVE_SCAN))
-               goto nla_put_failure;
-       if ((chan->flags & IEEE80211_CHAN_NO_IBSS) &&
-           nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IBSS))
-               goto nla_put_failure;
+       if (chan->flags & IEEE80211_CHAN_NO_IR) {
+               if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_NO_IR))
+                       goto nla_put_failure;
+               if (nla_put_flag(msg, __NL80211_FREQUENCY_ATTR_NO_IBSS))
+                       goto nla_put_failure;
+       }
        if (chan->flags & IEEE80211_CHAN_RADAR) {
                if (nla_put_flag(msg, NL80211_FREQUENCY_ATTR_RADAR))
                        goto nla_put_failure;
@@@ -1247,10 -1228,6 +1247,6 @@@ static int nl80211_send_wiphy(struct cf
                if ((dev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP) &&
                    nla_put_flag(msg, NL80211_ATTR_TDLS_EXTERNAL_SETUP))
                        goto nla_put_failure;
-               if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
-                   nla_put_flag(msg, WIPHY_FLAG_SUPPORTS_5_10_MHZ))
-                       goto nla_put_failure;
                state->split_start++;
                if (state->split)
                        break;
                if (nl80211_send_coalesce(msg, dev))
                        goto nla_put_failure;
  
+               if ((dev->wiphy.flags & WIPHY_FLAG_SUPPORTS_5_10_MHZ) &&
+                   (nla_put_flag(msg, NL80211_ATTR_SUPPORT_5_MHZ) ||
+                    nla_put_flag(msg, NL80211_ATTR_SUPPORT_10_MHZ)))
+                       goto nla_put_failure;
                /* done */
                state->split_start = 0;
                break;
@@@ -2187,7 -2169,7 +2188,7 @@@ static inline u64 wdev_id(struct wirele
  }
  
  static int nl80211_send_chandef(struct sk_buff *msg,
-                                struct cfg80211_chan_def *chandef)
+                               const struct cfg80211_chan_def *chandef)
  {
        WARN_ON(!cfg80211_chandef_valid(chandef));
  
@@@ -3236,6 -3218,7 +3237,7 @@@ static int nl80211_start_ap(struct sk_b
                        return PTR_ERR(params.acl);
        }
  
+       wdev_lock(wdev);
        err = rdev_start_ap(rdev, dev, &params);
        if (!err) {
                wdev->preset_chandef = params.chandef;
                wdev->ssid_len = params.ssid_len;
                memcpy(wdev->ssid, params.ssid, wdev->ssid_len);
        }
+       wdev_unlock(wdev);
  
        kfree(params.acl);
  
@@@ -3272,7 -3256,11 +3275,11 @@@ static int nl80211_set_beacon(struct sk
        if (err)
                return err;
  
-       return rdev_change_beacon(rdev, dev, &params);
+       wdev_lock(wdev);
+       err = rdev_change_beacon(rdev, dev, &params);
+       wdev_unlock(wdev);
+       return err;
  }
  
  static int nl80211_stop_ap(struct sk_buff *skb, struct genl_info *info)
@@@ -4478,7 -4466,9 +4485,9 @@@ static int nl80211_set_bss(struct sk_bu
  {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
        struct net_device *dev = info->user_ptr[1];
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
        struct bss_parameters params;
+       int err;
  
        memset(&params, 0, sizeof(params));
        /* default to not changing parameters */
            dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
                return -EOPNOTSUPP;
  
-       return rdev_change_bss(rdev, dev, &params);
+       wdev_lock(wdev);
+       err = rdev_change_bss(rdev, dev, &params);
+       wdev_unlock(wdev);
+       return err;
  }
  
  static const struct nla_policy reg_rule_policy[NL80211_REG_RULE_ATTR_MAX + 1] = {
@@@ -5098,7 -5092,7 +5111,7 @@@ static int nl80211_set_reg(struct sk_bu
        char *alpha2 = NULL;
        int rem_reg_rules = 0, r = 0;
        u32 num_rules = 0, rule_idx = 0, size_of_regd;
-       u8 dfs_region = 0;
+       enum nl80211_dfs_regions dfs_region = NL80211_DFS_UNSET;
        struct ieee80211_regdomain *rd = NULL;
  
        if (!info->attrs[NL80211_ATTR_REG_ALPHA2])
                        return -EINVAL;
        }
  
+       if (!reg_is_valid_request(alpha2))
+               return -EINVAL;
        size_of_regd = sizeof(struct ieee80211_regdomain) +
                       num_rules * sizeof(struct ieee80211_reg_rule);
  
@@@ -5361,10 -5358,8 +5377,8 @@@ static int nl80211_trigger_scan(struct 
        if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
                request->flags = nla_get_u32(
                        info->attrs[NL80211_ATTR_SCAN_FLAGS]);
-               if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
-                    !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
-                   ((request->flags & NL80211_SCAN_FLAG_FLUSH) &&
-                    !(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) {
+               if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
+                   !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
                        err = -EOPNOTSUPP;
                        goto out_free;
                }
@@@ -5604,10 -5599,8 +5618,8 @@@ static int nl80211_start_sched_scan(str
        if (info->attrs[NL80211_ATTR_SCAN_FLAGS]) {
                request->flags = nla_get_u32(
                        info->attrs[NL80211_ATTR_SCAN_FLAGS]);
-               if (((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
-                    !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) ||
-                   ((request->flags & NL80211_SCAN_FLAG_FLUSH) &&
-                    !(wiphy->features & NL80211_FEATURE_SCAN_FLUSH))) {
+               if ((request->flags & NL80211_SCAN_FLAG_LOW_PRIORITY) &&
+                   !(wiphy->features & NL80211_FEATURE_LOW_PRIORITY_SCAN)) {
                        err = -EOPNOTSUPP;
                        goto out_free;
                }
@@@ -5670,7 -5663,7 +5682,7 @@@ static int nl80211_start_radar_detectio
        if (err == 0)
                return -EINVAL;
  
-       if (chandef.chan->dfs_state != NL80211_DFS_USABLE)
+       if (!cfg80211_chandef_dfs_usable(wdev->wiphy, &chandef))
                return -EINVAL;
  
        if (!rdev->ops->start_radar_detection)
@@@ -5810,7 -5803,11 +5822,11 @@@ skip_beacons
        if (info->attrs[NL80211_ATTR_CH_SWITCH_BLOCK_TX])
                params.block_tx = true;
  
-       return rdev_channel_switch(rdev, dev, &params);
+       wdev_lock(wdev);
+       err = rdev_channel_switch(rdev, dev, &params);
+       wdev_unlock(wdev);
+       return err;
  }
  
  static int nl80211_send_bss(struct sk_buff *msg, struct netlink_callback *cb,
@@@ -6675,6 -6672,10 +6691,6 @@@ static int nl80211_set_mcast_rate(struc
  
  
  #ifdef CONFIG_NL80211_TESTMODE
 -static struct genl_multicast_group nl80211_testmode_mcgrp = {
 -      .name = "testmode",
 -};
 -
  static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
  {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
@@@ -6883,8 -6884,8 +6899,8 @@@ void cfg80211_testmode_event(struct sk_
  
        nla_nest_end(skb, data);
        genlmsg_end(skb, hdr);
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), skb, 0,
 -                              nl80211_testmode_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), skb, 0,
 +                              NL80211_MCGRP_TESTMODE, gfp);
  }
  EXPORT_SYMBOL(cfg80211_testmode_event);
  #endif
@@@ -7443,10 -7444,10 +7459,10 @@@ static int nl80211_tx_mgmt(struct sk_bu
        void *hdr = NULL;
        u64 cookie;
        struct sk_buff *msg = NULL;
-       unsigned int wait = 0;
-       bool offchan, no_cck, dont_wait_for_ack;
-       dont_wait_for_ack = info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK];
+       struct cfg80211_mgmt_tx_params params = {
+               .dont_wait_for_ack =
+                       info->attrs[NL80211_ATTR_DONT_WAIT_FOR_ACK],
+       };
  
        if (!info->attrs[NL80211_ATTR_FRAME])
                return -EINVAL;
        if (info->attrs[NL80211_ATTR_DURATION]) {
                if (!(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
                        return -EINVAL;
-               wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
+               params.wait = nla_get_u32(info->attrs[NL80211_ATTR_DURATION]);
  
                /*
                 * We should wait on the channel for at least a minimum amount
                 * of time (10ms) but no longer than the driver supports.
                 */
-               if (wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
-                   wait > rdev->wiphy.max_remain_on_channel_duration)
+               if (params.wait < NL80211_MIN_REMAIN_ON_CHANNEL_TIME ||
+                   params.wait > rdev->wiphy.max_remain_on_channel_duration)
                        return -EINVAL;
  
        }
  
-       offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
+       params.offchan = info->attrs[NL80211_ATTR_OFFCHANNEL_TX_OK];
  
-       if (offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
+       if (params.offchan && !(rdev->wiphy.flags & WIPHY_FLAG_OFFCHAN_TX))
                return -EINVAL;
  
-       no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
+       params.no_cck = nla_get_flag(info->attrs[NL80211_ATTR_TX_NO_CCK_RATE]);
  
        /* get the channel if any has been specified, otherwise pass NULL to
         * the driver. The latter will use the current one
                        return err;
        }
  
-       if (!chandef.chan && offchan)
+       if (!chandef.chan && params.offchan)
                return -EINVAL;
  
-       if (!dont_wait_for_ack) {
+       if (!params.dont_wait_for_ack) {
                msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
                if (!msg)
                        return -ENOMEM;
                }
        }
  
-       err = cfg80211_mlme_mgmt_tx(rdev, wdev, chandef.chan, offchan, wait,
-                                   nla_data(info->attrs[NL80211_ATTR_FRAME]),
-                                   nla_len(info->attrs[NL80211_ATTR_FRAME]),
-                                   no_cck, dont_wait_for_ack, &cookie);
+       params.buf = nla_data(info->attrs[NL80211_ATTR_FRAME]);
+       params.len = nla_len(info->attrs[NL80211_ATTR_FRAME]);
+       params.chan = chandef.chan;
+       err = cfg80211_mlme_mgmt_tx(rdev, wdev, &params, &cookie);
        if (err)
                goto free_msg;
  
@@@ -8866,7 -8867,7 +8882,7 @@@ static int nl80211_crit_protocol_stop(s
  #define NL80211_FLAG_NEED_WDEV_UP     (NL80211_FLAG_NEED_WDEV |\
                                         NL80211_FLAG_CHECK_NETDEV_UP)
  
 -static int nl80211_pre_doit(struct genl_ops *ops, struct sk_buff *skb,
 +static int nl80211_pre_doit(const struct genl_ops *ops, struct sk_buff *skb,
                            struct genl_info *info)
  {
        struct cfg80211_registered_device *rdev;
        return 0;
  }
  
 -static void nl80211_post_doit(struct genl_ops *ops, struct sk_buff *skb,
 +static void nl80211_post_doit(const struct genl_ops *ops, struct sk_buff *skb,
                              struct genl_info *info)
  {
        if (info->user_ptr[1]) {
                rtnl_unlock();
  }
  
 -static struct genl_ops nl80211_ops[] = {
 +static const struct genl_ops nl80211_ops[] = {
        {
                .cmd = NL80211_CMD_GET_WIPHY,
                .doit = nl80211_get_wiphy,
        },
  };
  
 -static struct genl_multicast_group nl80211_mlme_mcgrp = {
 -      .name = "mlme",
 -};
 -
 -/* multicast groups */
 -static struct genl_multicast_group nl80211_config_mcgrp = {
 -      .name = "config",
 -};
 -static struct genl_multicast_group nl80211_scan_mcgrp = {
 -      .name = "scan",
 -};
 -static struct genl_multicast_group nl80211_regulatory_mcgrp = {
 -      .name = "regulatory",
 -};
 -
  /* notification functions */
  
  void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev)
                return;
        }
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_config_mcgrp.id, GFP_KERNEL);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_CONFIG, GFP_KERNEL);
  }
  
  static int nl80211_add_scan_req(struct sk_buff *msg,
@@@ -9707,8 -9723,8 +9723,8 @@@ void nl80211_send_scan_start(struct cfg
                return;
        }
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_scan_mcgrp.id, GFP_KERNEL);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_SCAN, GFP_KERNEL);
  }
  
  void nl80211_send_scan_done(struct cfg80211_registered_device *rdev,
                return;
        }
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_scan_mcgrp.id, GFP_KERNEL);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_SCAN, GFP_KERNEL);
  }
  
  void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev,
                return;
        }
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_scan_mcgrp.id, GFP_KERNEL);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_SCAN, GFP_KERNEL);
  }
  
  void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev,
                return;
        }
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_scan_mcgrp.id, GFP_KERNEL);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_SCAN, GFP_KERNEL);
  }
  
  void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev,
                return;
        }
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_scan_mcgrp.id, GFP_KERNEL);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_SCAN, GFP_KERNEL);
  }
  
  /*
@@@ -9837,8 -9853,8 +9853,8 @@@ void nl80211_send_reg_change_event(stru
        genlmsg_end(msg, hdr);
  
        rcu_read_lock();
 -      genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id,
 -                              GFP_ATOMIC);
 +      genlmsg_multicast_allns(&nl80211_fam, msg, 0,
 +                              NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
        rcu_read_unlock();
  
        return;
@@@ -9873,8 -9889,8 +9889,8 @@@ static void nl80211_send_mlme_event(str
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -9961,8 -9977,8 +9977,8 @@@ static void nl80211_send_mlme_timeout(s
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10017,8 -10033,8 +10033,8 @@@ void nl80211_send_connect_result(struc
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10056,8 -10072,8 +10072,8 @@@ void nl80211_send_roamed(struct cfg8021
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10094,8 -10110,8 +10110,8 @@@ void nl80211_send_disconnected(struct c
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, GFP_KERNEL);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, GFP_KERNEL);
        return;
  
   nla_put_failure:
@@@ -10128,8 -10144,8 +10144,8 @@@ void nl80211_send_ibss_bssid(struct cfg
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10169,8 -10185,8 +10185,8 @@@ void cfg80211_notify_new_peer_candidate
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10208,8 -10224,8 +10224,8 @@@ void nl80211_michael_mic_failure(struc
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10261,8 -10277,8 +10277,8 @@@ void nl80211_send_beacon_hint_event(str
        genlmsg_end(msg, hdr);
  
        rcu_read_lock();
 -      genlmsg_multicast_allns(msg, 0, nl80211_regulatory_mcgrp.id,
 -                              GFP_ATOMIC);
 +      genlmsg_multicast_allns(&nl80211_fam, msg, 0,
 +                              NL80211_MCGRP_REGULATORY, GFP_ATOMIC);
        rcu_read_unlock();
  
        return;
@@@ -10307,8 -10323,8 +10323,8 @@@ static void nl80211_send_remain_on_chan
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10362,8 -10378,8 +10378,8 @@@ void cfg80211_new_sta(struct net_devic
                return;
        }
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
  }
  EXPORT_SYMBOL(cfg80211_new_sta);
  
@@@ -10392,8 -10408,8 +10408,8 @@@ void cfg80211_del_sta(struct net_devic
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10428,8 -10444,8 +10444,8 @@@ void cfg80211_conn_failed(struct net_de
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10590,8 -10606,8 +10606,8 @@@ void cfg80211_mgmt_tx_status(struct wir
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10639,8 -10655,8 +10655,8 @@@ void cfg80211_cqm_rssi_notify(struct ne
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10684,8 -10700,8 +10700,8 @@@ static void nl80211_gtk_rekey_notify(st
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10742,8 -10758,8 +10758,8 @@@ nl80211_pmksa_candidate_notify(struct c
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10789,8 -10805,8 +10805,8 @@@ static void nl80211_ch_switch_notify(st
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10805,21 -10821,18 +10821,18 @@@ void cfg80211_ch_switch_notify(struct n
        struct wiphy *wiphy = wdev->wiphy;
        struct cfg80211_registered_device *rdev = wiphy_to_dev(wiphy);
  
-       trace_cfg80211_ch_switch_notify(dev, chandef);
+       ASSERT_WDEV_LOCK(wdev);
  
-       wdev_lock(wdev);
+       trace_cfg80211_ch_switch_notify(dev, chandef);
  
        if (WARN_ON(wdev->iftype != NL80211_IFTYPE_AP &&
                    wdev->iftype != NL80211_IFTYPE_P2P_GO &&
                    wdev->iftype != NL80211_IFTYPE_ADHOC &&
                    wdev->iftype != NL80211_IFTYPE_MESH_POINT))
-               goto out;
+               return;
  
        wdev->channel = chandef->chan;
        nl80211_ch_switch_notify(rdev, dev, chandef, GFP_KERNEL);
- out:
-       wdev_unlock(wdev);
-       return;
  }
  EXPORT_SYMBOL(cfg80211_ch_switch_notify);
  
@@@ -10866,8 -10879,8 +10879,8 @@@ void cfg80211_cqm_txe_notify(struct net
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10878,7 -10891,7 +10891,7 @@@ EXPORT_SYMBOL(cfg80211_cqm_txe_notify)
  
  void
  nl80211_radar_notify(struct cfg80211_registered_device *rdev,
-                    struct cfg80211_chan_def *chandef,
+                    const struct cfg80211_chan_def *chandef,
                     enum nl80211_radar_event event,
                     struct net_device *netdev, gfp_t gfp)
  {
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -10962,8 -10975,8 +10975,8 @@@ void cfg80211_cqm_pktloss_notify(struc
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -11002,8 -11015,8 +11015,8 @@@ void cfg80211_probe_status(struct net_d
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -11154,8 -11167,8 +11167,8 @@@ void cfg80211_report_wowlan_wakeup(stru
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   free_msg:
@@@ -11196,8 -11209,8 +11209,8 @@@ void cfg80211_tdls_oper_request(struct 
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, gfp);
        return;
  
   nla_put_failure:
@@@ -11279,8 -11292,8 +11292,8 @@@ void cfg80211_ft_event(struct net_devic
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 -                              nl80211_mlme_mcgrp.id, GFP_KERNEL);
 +      genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0,
 +                              NL80211_MCGRP_MLME, GFP_KERNEL);
  }
  EXPORT_SYMBOL(cfg80211_ft_event);
  
@@@ -11329,11 -11342,33 +11342,11 @@@ int nl80211_init(void
  {
        int err;
  
 -      err = genl_register_family_with_ops(&nl80211_fam,
 -              nl80211_ops, ARRAY_SIZE(nl80211_ops));
 +      err = genl_register_family_with_ops_groups(&nl80211_fam, nl80211_ops,
 +                                                 nl80211_mcgrps);
        if (err)
                return err;
  
 -      err = genl_register_mc_group(&nl80211_fam, &nl80211_config_mcgrp);
 -      if (err)
 -              goto err_out;
 -
 -      err = genl_register_mc_group(&nl80211_fam, &nl80211_scan_mcgrp);
 -      if (err)
 -              goto err_out;
 -
 -      err = genl_register_mc_group(&nl80211_fam, &nl80211_regulatory_mcgrp);
 -      if (err)
 -              goto err_out;
 -
 -      err = genl_register_mc_group(&nl80211_fam, &nl80211_mlme_mcgrp);
 -      if (err)
 -              goto err_out;
 -
 -#ifdef CONFIG_NL80211_TESTMODE
 -      err = genl_register_mc_group(&nl80211_fam, &nl80211_testmode_mcgrp);
 -      if (err)
 -              goto err_out;
 -#endif
 -
        err = netlink_register_notifier(&nl80211_netlink_notifier);
        if (err)
                goto err_out;