Merge branch 'for-john' of git://git.kernel.org/pub/scm/linux/kernel/git/jberg/mac802...
authorJohn W. Linville <linville@tuxdriver.com>
Fri, 16 Aug 2013 18:24:51 +0000 (14:24 -0400)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 16 Aug 2013 18:24:51 +0000 (14:24 -0400)
1  2 
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/iwlwifi/dvm/tx.c
drivers/net/wireless/iwlwifi/mvm/tx.c
net/mac80211/cfg.c
net/mac80211/mlme.c
net/mac80211/rc80211_minstrel_ht.c
net/mac80211/rx.c
net/wireless/nl80211.c

@@@ -1093,11 -1093,8 +1093,11 @@@ static void brcmf_link_down(struct brcm
                brcmf_dbg(INFO, "Call WLC_DISASSOC to stop excess roaming\n ");
                err = brcmf_fil_cmd_data_set(vif->ifp,
                                             BRCMF_C_DISASSOC, NULL, 0);
 -              if (err)
 +              if (err) {
                        brcmf_err("WLC_DISASSOC failed (%d)\n", err);
 +                      cfg80211_disconnected(vif->wdev.netdev, 0,
 +                                            NULL, 0, GFP_KERNEL);
 +              }
                clear_bit(BRCMF_VIF_STATUS_CONNECTED, &vif->sme_state);
        }
        clear_bit(BRCMF_VIF_STATUS_CONNECTING, &vif->sme_state);
@@@ -3155,7 -3152,9 +3155,9 @@@ static int brcmf_cfg80211_sched_scan_st
  }
  
  #ifdef CONFIG_NL80211_TESTMODE
- static int brcmf_cfg80211_testmode(struct wiphy *wiphy, void *data, int len)
+ static int brcmf_cfg80211_testmode(struct wiphy *wiphy,
+                                  struct wireless_dev *wdev,
+                                  void *data, int len)
  {
        struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
        struct net_device *ndev = cfg_to_ndev(cfg);
@@@ -4126,53 -4125,6 +4128,53 @@@ static void brcmf_cfg80211_crit_proto_s
        clear_bit(BRCMF_SCAN_STATUS_SUPPRESS, &cfg->scan_status);
  }
  
 +static int brcmf_convert_nl80211_tdls_oper(enum nl80211_tdls_operation oper)
 +{
 +      int ret;
 +
 +      switch (oper) {
 +      case NL80211_TDLS_DISCOVERY_REQ:
 +              ret = BRCMF_TDLS_MANUAL_EP_DISCOVERY;
 +              break;
 +      case NL80211_TDLS_SETUP:
 +              ret = BRCMF_TDLS_MANUAL_EP_CREATE;
 +              break;
 +      case NL80211_TDLS_TEARDOWN:
 +              ret = BRCMF_TDLS_MANUAL_EP_DELETE;
 +              break;
 +      default:
 +              brcmf_err("unsupported operation: %d\n", oper);
 +              ret = -EOPNOTSUPP;
 +      }
 +      return ret;
 +}
 +
 +static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy,
 +                                  struct net_device *ndev, u8 *peer,
 +                                  enum nl80211_tdls_operation oper)
 +{
 +      struct brcmf_if *ifp;
 +      struct brcmf_tdls_iovar_le info;
 +      int ret = 0;
 +
 +      ret = brcmf_convert_nl80211_tdls_oper(oper);
 +      if (ret < 0)
 +              return ret;
 +
 +      ifp = netdev_priv(ndev);
 +      memset(&info, 0, sizeof(info));
 +      info.mode = (u8)ret;
 +      if (peer)
 +              memcpy(info.ea, peer, ETH_ALEN);
 +
 +      ret = brcmf_fil_iovar_data_set(ifp, "tdls_endpoint",
 +                                     &info, sizeof(info));
 +      if (ret < 0)
 +              brcmf_err("tdls_endpoint iovar failed: ret=%d\n", ret);
 +
 +      return ret;
 +}
 +
  static struct cfg80211_ops wl_cfg80211_ops = {
        .add_virtual_intf = brcmf_cfg80211_add_iface,
        .del_virtual_intf = brcmf_cfg80211_del_iface,
        .stop_p2p_device = brcmf_p2p_stop_device,
        .crit_proto_start = brcmf_cfg80211_crit_proto_start,
        .crit_proto_stop = brcmf_cfg80211_crit_proto_stop,
 -#ifdef CONFIG_NL80211_TESTMODE
 -      .testmode_cmd = brcmf_cfg80211_testmode
 -#endif
 +      .tdls_oper = brcmf_cfg80211_tdls_oper,
 +      CFG80211_TESTMODE_CMD(brcmf_cfg80211_testmode)
  };
  
  static s32 brcmf_nl80211_iftype_to_mode(enum nl80211_iftype type)
@@@ -4333,8 -4286,7 +4335,8 @@@ static struct wiphy *brcmf_setup_wiphy(
        wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
        wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT |
                        WIPHY_FLAG_OFFCHAN_TX |
 -                      WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
 +                      WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
 +                      WIPHY_FLAG_SUPPORTS_TDLS;
        wiphy->mgmt_stypes = brcmf_txrx_stypes;
        wiphy->max_remain_on_channel_duration = 5000;
        brcmf_wiphy_pno_params(wiphy);
@@@ -4955,12 -4907,6 +4957,12 @@@ struct brcmf_cfg80211_info *brcmf_cfg80
                goto cfg80211_p2p_attach_out;
        }
  
 +      err = brcmf_fil_iovar_int_set(ifp, "tdls_enable", 1);
 +      if (err) {
 +              brcmf_dbg(INFO, "TDLS not enabled (%d)\n", err);
 +              wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_TDLS;
 +      }
 +
        err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_VERSION,
                                    &io_type);
        if (err) {
@@@ -87,7 -87,7 +87,7 @@@ static void iwlagn_tx_cmd_build_basic(s
                 priv->lib->bt_params->advanced_bt_coexist &&
                 (ieee80211_is_auth(fc) || ieee80211_is_assoc_req(fc) ||
                 ieee80211_is_reassoc_req(fc) ||
-                skb->protocol == cpu_to_be16(ETH_P_PAE)))
+                info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO))
                tx_flags |= TX_CMD_FLG_IGNORE_BT;
  
  
@@@ -478,6 -478,9 +478,6 @@@ int iwlagn_tx_skb(struct iwl_priv *priv
        if (sta_priv && sta_priv->client && !is_agg)
                atomic_inc(&sta_priv->pending_frames);
  
 -      if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
 -              iwl_scan_offchannel_skb(priv);
 -
        return 0;
  
  drop_unlock_sta:
@@@ -1155,6 -1158,7 +1155,6 @@@ int iwlagn_rx_reply_tx(struct iwl_priv 
        struct sk_buff *skb;
        struct iwl_rxon_context *ctx;
        bool is_agg = (txq_id >= IWLAGN_FIRST_AMPDU_QUEUE);
 -      bool is_offchannel_skb;
  
        tid = (tx_resp->ra_tid & IWLAGN_TX_RES_TID_MSK) >>
                IWLAGN_TX_RES_TID_POS;
  
        __skb_queue_head_init(&skbs);
  
 -      is_offchannel_skb = false;
 -
        if (tx_resp->frame_count == 1) {
                u16 next_reclaimed = le16_to_cpu(tx_resp->seq_ctl);
                next_reclaimed = IEEE80211_SEQ_TO_SN(next_reclaimed + 0x10);
                        if (!is_agg)
                                iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1);
  
 -                      is_offchannel_skb =
 -                              (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN);
                        freed++;
                }
  
                if (!is_agg && freed != 1)
                        IWL_ERR(priv, "Q: %d, freed %d\n", txq_id, freed);
  
 -              /*
 -               * An offchannel frame can be send only on the AUX queue, where
 -               * there is no aggregation (and reordering) so it only is single
 -               * skb is expected to be processed.
 -               */
 -              if (is_offchannel_skb && freed != 1)
 -                      IWL_ERR(priv, "OFFCHANNEL SKB freed %d\n", freed);
 -
                IWL_DEBUG_TX_REPLY(priv, "TXQ %d status %s (0x%08x)\n", txq_id,
                                   iwl_get_tx_fail_reason(status), status);
  
                ieee80211_tx_status_ni(priv->hw, skb);
        }
  
 -      if (is_offchannel_skb)
 -              iwl_scan_offchannel_skb_status(priv);
 -
        return 0;
  }
  
@@@ -91,11 -91,10 +91,10 @@@ static void iwl_mvm_set_tx_cmd(struct i
                tx_flags |= TX_CMD_FLG_ACK | TX_CMD_FLG_BAR;
  
        /* High prio packet (wrt. BT coex) if it is EAPOL, MCAST or MGMT */
-       if (info->band == IEEE80211_BAND_2GHZ        &&
-           (skb->protocol == cpu_to_be16(ETH_P_PAE)  ||
-            is_multicast_ether_addr(hdr->addr1)      ||
-            ieee80211_is_back_req(fc)                ||
-            ieee80211_is_mgmt(fc)))
+       if (info->band == IEEE80211_BAND_2GHZ &&
+           (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO ||
+            is_multicast_ether_addr(hdr->addr1) ||
+            ieee80211_is_back_req(fc) || ieee80211_is_mgmt(fc)))
                tx_flags |= TX_CMD_FLG_BT_DIS;
  
        if (ieee80211_has_morefrags(fc))
                 * it
                 */
                WARN_ON_ONCE(info->flags & IEEE80211_TX_CTL_AMPDU);
 +      } else if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
 +              tx_cmd->pm_frame_timeout = cpu_to_le16(2);
        } else {
                tx_cmd->pm_frame_timeout = 0;
        }
@@@ -173,7 -170,7 +172,7 @@@ static void iwl_mvm_set_tx_cmd_rate(str
        }
  
        /*
 -       * for data packets, rate info comes from the table inside he fw. This
 +       * for data packets, rate info comes from the table inside the fw. This
         * table is controlled by LINK_QUALITY commands
         */
  
diff --combined net/mac80211/cfg.c
@@@ -672,8 -672,6 +672,8 @@@ static void ieee80211_get_et_stats(stru
                        if (sta->sdata->dev != dev)
                                continue;
  
 +                      sinfo.filled = 0;
 +                      sta_set_sinfo(sta, &sinfo);
                        i = 0;
                        ADD_STA_STATS(sta);
                }
@@@ -2302,14 -2300,25 +2302,25 @@@ static void ieee80211_rfkill_poll(struc
  }
  
  #ifdef CONFIG_NL80211_TESTMODE
- static int ieee80211_testmode_cmd(struct wiphy *wiphy, void *data, int len)
+ static int ieee80211_testmode_cmd(struct wiphy *wiphy,
+                                 struct wireless_dev *wdev,
+                                 void *data, int len)
  {
        struct ieee80211_local *local = wiphy_priv(wiphy);
+       struct ieee80211_vif *vif = NULL;
  
        if (!local->ops->testmode_cmd)
                return -EOPNOTSUPP;
  
-       return local->ops->testmode_cmd(&local->hw, data, len);
+       if (wdev) {
+               struct ieee80211_sub_if_data *sdata;
+               sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+               if (sdata->flags & IEEE80211_SDATA_IN_DRIVER)
+                       vif = &sdata->vif;
+       }
+       return local->ops->testmode_cmd(&local->hw, vif, data, len);
  }
  
  static int ieee80211_testmode_dump(struct wiphy *wiphy,
diff --combined net/mac80211/mlme.c
  #include "led.h"
  
  #define IEEE80211_AUTH_TIMEOUT                (HZ / 5)
 +#define IEEE80211_AUTH_TIMEOUT_LONG   (HZ / 2)
  #define IEEE80211_AUTH_TIMEOUT_SHORT  (HZ / 10)
  #define IEEE80211_AUTH_MAX_TRIES      3
  #define IEEE80211_AUTH_WAIT_ASSOC     (HZ * 5)
  #define IEEE80211_ASSOC_TIMEOUT               (HZ / 5)
 +#define IEEE80211_ASSOC_TIMEOUT_LONG  (HZ / 2)
  #define IEEE80211_ASSOC_TIMEOUT_SHORT (HZ / 10)
  #define IEEE80211_ASSOC_MAX_TRIES     3
  
@@@ -211,9 -209,8 +211,9 @@@ ieee80211_determine_chantype(struct iee
                             struct ieee80211_channel *channel,
                             const struct ieee80211_ht_operation *ht_oper,
                             const struct ieee80211_vht_operation *vht_oper,
 -                           struct cfg80211_chan_def *chandef, bool verbose)
 +                           struct cfg80211_chan_def *chandef, bool tracking)
  {
 +      struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct cfg80211_chan_def vht_chandef;
        u32 ht_cfreq, ret;
  
        ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan,
                                                  channel->band);
        /* check that channel matches the right operating channel */
 -      if (channel->center_freq != ht_cfreq) {
 +      if (!tracking && channel->center_freq != ht_cfreq) {
                /*
                 * It's possible that some APs are confused here;
                 * Netgear WNDR3700 sometimes reports 4 higher than
                 * since we look at probe response/beacon data here
                 * it should be OK.
                 */
 -              if (verbose)
 -                      sdata_info(sdata,
 -                                 "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
 -                                 channel->center_freq, ht_cfreq,
 -                                 ht_oper->primary_chan, channel->band);
 +              sdata_info(sdata,
 +                         "Wrong control channel: center-freq: %d ht-cfreq: %d ht->primary_chan: %d band: %d - Disabling HT\n",
 +                         channel->center_freq, ht_cfreq,
 +                         ht_oper->primary_chan, channel->band);
                ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
                goto out;
        }
                                channel->band);
                break;
        default:
 -              if (verbose)
 +              if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
                        sdata_info(sdata,
                                   "AP VHT operation IE has invalid channel width (%d), disable VHT\n",
                                   vht_oper->chan_width);
        }
  
        if (!cfg80211_chandef_valid(&vht_chandef)) {
 -              if (verbose)
 +              if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
                        sdata_info(sdata,
                                   "AP VHT information is invalid, disable VHT\n");
                ret = IEEE80211_STA_DISABLE_VHT;
        }
  
        if (!cfg80211_chandef_compatible(chandef, &vht_chandef)) {
 -              if (verbose)
 +              if (!(ifmgd->flags & IEEE80211_STA_DISABLE_VHT))
                        sdata_info(sdata,
                                   "AP VHT information doesn't match HT, disable VHT\n");
                ret = IEEE80211_STA_DISABLE_VHT;
@@@ -335,27 -333,18 +335,27 @@@ out
        if (ret & IEEE80211_STA_DISABLE_VHT)
                vht_chandef = *chandef;
  
 +      /*
 +       * Ignore the DISABLED flag when we're already connected and only
 +       * tracking the APs beacon for bandwidth changes - otherwise we
 +       * might get disconnected here if we connect to an AP, update our
 +       * regulatory information based on the AP's country IE and the
 +       * information we have is wrong/outdated and disables the channel
 +       * that we're actually using for the connection to the AP.
 +       */
        while (!cfg80211_chandef_usable(sdata->local->hw.wiphy, chandef,
 -                                      IEEE80211_CHAN_DISABLED)) {
 +                                      tracking ? 0 :
 +                                                 IEEE80211_CHAN_DISABLED)) {
                if (WARN_ON(chandef->width == NL80211_CHAN_WIDTH_20_NOHT)) {
                        ret = IEEE80211_STA_DISABLE_HT |
                              IEEE80211_STA_DISABLE_VHT;
 -                      goto out;
 +                      break;
                }
  
                ret |= chandef_downgrade(chandef);
        }
  
 -      if (chandef->width != vht_chandef.width && verbose)
 +      if (chandef->width != vht_chandef.width && !tracking)
                sdata_info(sdata,
                           "capabilities/regulatory prevented using AP HT/VHT configuration, downgraded\n");
  
@@@ -395,7 -384,7 +395,7 @@@ static int ieee80211_config_bw(struct i
  
        /* calculate new channel (type) based on HT/VHT operation IEs */
        flags = ieee80211_determine_chantype(sdata, sband, chan, ht_oper,
 -                                           vht_oper, &chandef, false);
 +                                           vht_oper, &chandef, true);
  
        /*
         * Downgrade the new channel if we associated with restricted
@@@ -1113,6 -1102,15 +1113,15 @@@ ieee80211_sta_process_chanswitch(struc
        case -1:
                cfg80211_chandef_create(&new_chandef, new_chan,
                                        NL80211_CHAN_NO_HT);
+               /* keep width for 5/10 MHz channels */
+               switch (sdata->vif.bss_conf.chandef.width) {
+               case NL80211_CHAN_WIDTH_5:
+               case NL80211_CHAN_WIDTH_10:
+                       new_chandef.width = sdata->vif.bss_conf.chandef.width;
+                       break;
+               default:
+                       break;
+               }
                break;
        }
  
@@@ -3406,13 -3404,10 +3415,13 @@@ static int ieee80211_probe_auth(struct 
  
        if (tx_flags == 0) {
                auth_data->timeout = jiffies + IEEE80211_AUTH_TIMEOUT;
 -              ifmgd->auth_data->timeout_started = true;
 +              auth_data->timeout_started = true;
                run_again(sdata, auth_data->timeout);
        } else {
 -              auth_data->timeout_started = false;
 +              auth_data->timeout =
 +                      round_jiffies_up(jiffies + IEEE80211_AUTH_TIMEOUT_LONG);
 +              auth_data->timeout_started = true;
 +              run_again(sdata, auth_data->timeout);
        }
  
        return 0;
@@@ -3449,11 -3444,7 +3458,11 @@@ static int ieee80211_do_assoc(struct ie
                assoc_data->timeout_started = true;
                run_again(sdata, assoc_data->timeout);
        } else {
 -              assoc_data->timeout_started = false;
 +              assoc_data->timeout =
 +                      round_jiffies_up(jiffies +
 +                                       IEEE80211_ASSOC_TIMEOUT_LONG);
 +              assoc_data->timeout_started = true;
 +              run_again(sdata, assoc_data->timeout);
        }
  
        return 0;
@@@ -3848,7 -3839,7 +3857,7 @@@ static int ieee80211_prep_channel(struc
        ifmgd->flags |= ieee80211_determine_chantype(sdata, sband,
                                                     cbss->channel,
                                                     ht_oper, vht_oper,
 -                                                   &chandef, true);
 +                                                   &chandef, false);
  
        sdata->needed_rx_chains = min(ieee80211_ht_vht_rx_chains(sdata, cbss),
                                      local->rx_chains);
@@@ -439,12 -439,13 +439,13 @@@ minstrel_aggr_check(struct ieee80211_st
  {
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
        struct sta_info *sta = container_of(pubsta, struct sta_info, sta);
+       struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
        u16 tid;
  
        if (unlikely(!ieee80211_is_data_qos(hdr->frame_control)))
                return;
  
-       if (unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE)))
+       if (unlikely(info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO))
                return;
  
        tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
@@@ -776,7 -777,7 +777,7 @@@ minstrel_ht_get_rate(void *priv, struc
  
        /* Don't use EAPOL frames for sampling on non-mrr hw */
        if (mp->hw->max_rates == 1 &&
-           txrc->skb->protocol == cpu_to_be16(ETH_P_PAE))
+           (info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO))
                sample_idx = -1;
        else
                sample_idx = minstrel_get_sample_rate(mp, mi);
  
        sample_group = &minstrel_mcs_groups[sample_idx / MCS_GROUP_RATES];
        info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
 +      rate->count = 1;
 +
 +      if (sample_idx / MCS_GROUP_RATES == MINSTREL_CCK_GROUP) {
 +              int idx = sample_idx % ARRAY_SIZE(mp->cck_rates);
 +              rate->idx = mp->cck_rates[idx];
 +              rate->flags = 0;
 +              return;
 +      }
 +
        rate->idx = sample_idx % MCS_GROUP_RATES +
                    (sample_group->streams - 1) * MCS_GROUP_RATES;
        rate->flags = IEEE80211_TX_RC_MCS | sample_group->flags;
 -      rate->count = 1;
  }
  
  static void
diff --combined net/mac80211/rx.c
@@@ -979,14 -979,8 +979,14 @@@ ieee80211_rx_h_check(struct ieee80211_r
        struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)rx->skb->data;
        struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(rx->skb);
  
 -      /* Drop duplicate 802.11 retransmissions (IEEE 802.11 Chap. 9.2.9) */
 -      if (rx->sta && !is_multicast_ether_addr(hdr->addr1)) {
 +      /*
 +       * Drop duplicate 802.11 retransmissions
 +       * (IEEE 802.11-2012: 9.3.2.10 "Duplicate detection and recovery")
 +       */
 +      if (rx->skb->len >= 24 && rx->sta &&
 +          !ieee80211_is_ctl(hdr->frame_control) &&
 +          !ieee80211_is_qos_nullfunc(hdr->frame_control) &&
 +          !is_multicast_ether_addr(hdr->addr1)) {
                if (unlikely(ieee80211_has_retry(hdr->frame_control) &&
                             rx->sta->last_seq_ctrl[rx->seqno_idx] ==
                             hdr->seq_ctrl)) {
  
  
  static ieee80211_rx_result debug_noinline
- ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
- {
-       struct sk_buff *skb = rx->skb;
-       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
-       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
-       int keyidx;
-       int hdrlen;
-       ieee80211_rx_result result = RX_DROP_UNUSABLE;
-       struct ieee80211_key *sta_ptk = NULL;
-       int mmie_keyidx = -1;
-       __le16 fc;
-       /*
-        * Key selection 101
-        *
-        * There are four types of keys:
-        *  - GTK (group keys)
-        *  - IGTK (group keys for management frames)
-        *  - PTK (pairwise keys)
-        *  - STK (station-to-station pairwise keys)
-        *
-        * When selecting a key, we have to distinguish between multicast
-        * (including broadcast) and unicast frames, the latter can only
-        * use PTKs and STKs while the former always use GTKs and IGTKs.
-        * Unless, of course, actual WEP keys ("pre-RSNA") are used, then
-        * unicast frames can also use key indices like GTKs. Hence, if we
-        * don't have a PTK/STK we check the key index for a WEP key.
-        *
-        * Note that in a regular BSS, multicast frames are sent by the
-        * AP only, associated stations unicast the frame to the AP first
-        * which then multicasts it on their behalf.
-        *
-        * There is also a slight problem in IBSS mode: GTKs are negotiated
-        * with each station, that is something we don't currently handle.
-        * The spec seems to expect that one negotiates the same key with
-        * every station but there's no such requirement; VLANs could be
-        * possible.
-        */
-       /*
-        * No point in finding a key and decrypting if the frame is neither
-        * addressed to us nor a multicast frame.
-        */
-       if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
-               return RX_CONTINUE;
-       /* start without a key */
-       rx->key = NULL;
-       if (rx->sta)
-               sta_ptk = rcu_dereference(rx->sta->ptk);
-       fc = hdr->frame_control;
-       if (!ieee80211_has_protected(fc))
-               mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
-       if (!is_multicast_ether_addr(hdr->addr1) && sta_ptk) {
-               rx->key = sta_ptk;
-               if ((status->flag & RX_FLAG_DECRYPTED) &&
-                   (status->flag & RX_FLAG_IV_STRIPPED))
-                       return RX_CONTINUE;
-               /* Skip decryption if the frame is not protected. */
-               if (!ieee80211_has_protected(fc))
-                       return RX_CONTINUE;
-       } else if (mmie_keyidx >= 0) {
-               /* Broadcast/multicast robust management frame / BIP */
-               if ((status->flag & RX_FLAG_DECRYPTED) &&
-                   (status->flag & RX_FLAG_IV_STRIPPED))
-                       return RX_CONTINUE;
-               if (mmie_keyidx < NUM_DEFAULT_KEYS ||
-                   mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
-                       return RX_DROP_MONITOR; /* unexpected BIP keyidx */
-               if (rx->sta)
-                       rx->key = rcu_dereference(rx->sta->gtk[mmie_keyidx]);
-               if (!rx->key)
-                       rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]);
-       } else if (!ieee80211_has_protected(fc)) {
-               /*
-                * The frame was not protected, so skip decryption. However, we
-                * need to set rx->key if there is a key that could have been
-                * used so that the frame may be dropped if encryption would
-                * have been expected.
-                */
-               struct ieee80211_key *key = NULL;
-               struct ieee80211_sub_if_data *sdata = rx->sdata;
-               int i;
-               if (ieee80211_is_mgmt(fc) &&
-                   is_multicast_ether_addr(hdr->addr1) &&
-                   (key = rcu_dereference(rx->sdata->default_mgmt_key)))
-                       rx->key = key;
-               else {
-                       if (rx->sta) {
-                               for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-                                       key = rcu_dereference(rx->sta->gtk[i]);
-                                       if (key)
-                                               break;
-                               }
-                       }
-                       if (!key) {
-                               for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
-                                       key = rcu_dereference(sdata->keys[i]);
-                                       if (key)
-                                               break;
-                               }
-                       }
-                       if (key)
-                               rx->key = key;
-               }
-               return RX_CONTINUE;
-       } else {
-               u8 keyid;
-               /*
-                * The device doesn't give us the IV so we won't be
-                * able to look up the key. That's ok though, we
-                * don't need to decrypt the frame, we just won't
-                * be able to keep statistics accurate.
-                * Except for key threshold notifications, should
-                * we somehow allow the driver to tell us which key
-                * the hardware used if this flag is set?
-                */
-               if ((status->flag & RX_FLAG_DECRYPTED) &&
-                   (status->flag & RX_FLAG_IV_STRIPPED))
-                       return RX_CONTINUE;
-               hdrlen = ieee80211_hdrlen(fc);
-               if (rx->skb->len < 8 + hdrlen)
-                       return RX_DROP_UNUSABLE; /* TODO: count this? */
-               /*
-                * no need to call ieee80211_wep_get_keyidx,
-                * it verifies a bunch of things we've done already
-                */
-               skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1);
-               keyidx = keyid >> 6;
-               /* check per-station GTK first, if multicast packet */
-               if (is_multicast_ether_addr(hdr->addr1) && rx->sta)
-                       rx->key = rcu_dereference(rx->sta->gtk[keyidx]);
-               /* if not found, try default key */
-               if (!rx->key) {
-                       rx->key = rcu_dereference(rx->sdata->keys[keyidx]);
-                       /*
-                        * RSNA-protected unicast frames should always be
-                        * sent with pairwise or station-to-station keys,
-                        * but for WEP we allow using a key index as well.
-                        */
-                       if (rx->key &&
-                           rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 &&
-                           rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 &&
-                           !is_multicast_ether_addr(hdr->addr1))
-                               rx->key = NULL;
-               }
-       }
-       if (rx->key) {
-               if (unlikely(rx->key->flags & KEY_FLAG_TAINTED))
-                       return RX_DROP_MONITOR;
-               rx->key->tx_rx_count++;
-               /* TODO: add threshold stuff again */
-       } else {
-               return RX_DROP_MONITOR;
-       }
-       switch (rx->key->conf.cipher) {
-       case WLAN_CIPHER_SUITE_WEP40:
-       case WLAN_CIPHER_SUITE_WEP104:
-               result = ieee80211_crypto_wep_decrypt(rx);
-               break;
-       case WLAN_CIPHER_SUITE_TKIP:
-               result = ieee80211_crypto_tkip_decrypt(rx);
-               break;
-       case WLAN_CIPHER_SUITE_CCMP:
-               result = ieee80211_crypto_ccmp_decrypt(rx);
-               break;
-       case WLAN_CIPHER_SUITE_AES_CMAC:
-               result = ieee80211_crypto_aes_cmac_decrypt(rx);
-               break;
-       default:
-               /*
-                * We can reach here only with HW-only algorithms
-                * but why didn't it decrypt the frame?!
-                */
-               return RX_DROP_UNUSABLE;
-       }
-       /* the hdr variable is invalid after the decrypt handlers */
-       /* either the frame has been decrypted or will be dropped */
-       status->flag |= RX_FLAG_DECRYPTED;
-       return result;
- }
- static ieee80211_rx_result debug_noinline
  ieee80211_rx_h_check_more_data(struct ieee80211_rx_data *rx)
  {
        struct ieee80211_local *local;
@@@ -1556,6 -1349,207 +1355,207 @@@ ieee80211_rx_h_sta_process(struct ieee8
        return RX_CONTINUE;
  } /* ieee80211_rx_h_sta_process */
  
+ static ieee80211_rx_result debug_noinline
+ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
+ {
+       struct sk_buff *skb = rx->skb;
+       struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
+       struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+       int keyidx;
+       int hdrlen;
+       ieee80211_rx_result result = RX_DROP_UNUSABLE;
+       struct ieee80211_key *sta_ptk = NULL;
+       int mmie_keyidx = -1;
+       __le16 fc;
+       /*
+        * Key selection 101
+        *
+        * There are four types of keys:
+        *  - GTK (group keys)
+        *  - IGTK (group keys for management frames)
+        *  - PTK (pairwise keys)
+        *  - STK (station-to-station pairwise keys)
+        *
+        * When selecting a key, we have to distinguish between multicast
+        * (including broadcast) and unicast frames, the latter can only
+        * use PTKs and STKs while the former always use GTKs and IGTKs.
+        * Unless, of course, actual WEP keys ("pre-RSNA") are used, then
+        * unicast frames can also use key indices like GTKs. Hence, if we
+        * don't have a PTK/STK we check the key index for a WEP key.
+        *
+        * Note that in a regular BSS, multicast frames are sent by the
+        * AP only, associated stations unicast the frame to the AP first
+        * which then multicasts it on their behalf.
+        *
+        * There is also a slight problem in IBSS mode: GTKs are negotiated
+        * with each station, that is something we don't currently handle.
+        * The spec seems to expect that one negotiates the same key with
+        * every station but there's no such requirement; VLANs could be
+        * possible.
+        */
+       /*
+        * No point in finding a key and decrypting if the frame is neither
+        * addressed to us nor a multicast frame.
+        */
+       if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
+               return RX_CONTINUE;
+       /* start without a key */
+       rx->key = NULL;
+       if (rx->sta)
+               sta_ptk = rcu_dereference(rx->sta->ptk);
+       fc = hdr->frame_control;
+       if (!ieee80211_has_protected(fc))
+               mmie_keyidx = ieee80211_get_mmie_keyidx(rx->skb);
+       if (!is_multicast_ether_addr(hdr->addr1) && sta_ptk) {
+               rx->key = sta_ptk;
+               if ((status->flag & RX_FLAG_DECRYPTED) &&
+                   (status->flag & RX_FLAG_IV_STRIPPED))
+                       return RX_CONTINUE;
+               /* Skip decryption if the frame is not protected. */
+               if (!ieee80211_has_protected(fc))
+                       return RX_CONTINUE;
+       } else if (mmie_keyidx >= 0) {
+               /* Broadcast/multicast robust management frame / BIP */
+               if ((status->flag & RX_FLAG_DECRYPTED) &&
+                   (status->flag & RX_FLAG_IV_STRIPPED))
+                       return RX_CONTINUE;
+               if (mmie_keyidx < NUM_DEFAULT_KEYS ||
+                   mmie_keyidx >= NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
+                       return RX_DROP_MONITOR; /* unexpected BIP keyidx */
+               if (rx->sta)
+                       rx->key = rcu_dereference(rx->sta->gtk[mmie_keyidx]);
+               if (!rx->key)
+                       rx->key = rcu_dereference(rx->sdata->keys[mmie_keyidx]);
+       } else if (!ieee80211_has_protected(fc)) {
+               /*
+                * The frame was not protected, so skip decryption. However, we
+                * need to set rx->key if there is a key that could have been
+                * used so that the frame may be dropped if encryption would
+                * have been expected.
+                */
+               struct ieee80211_key *key = NULL;
+               struct ieee80211_sub_if_data *sdata = rx->sdata;
+               int i;
+               if (ieee80211_is_mgmt(fc) &&
+                   is_multicast_ether_addr(hdr->addr1) &&
+                   (key = rcu_dereference(rx->sdata->default_mgmt_key)))
+                       rx->key = key;
+               else {
+                       if (rx->sta) {
+                               for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+                                       key = rcu_dereference(rx->sta->gtk[i]);
+                                       if (key)
+                                               break;
+                               }
+                       }
+                       if (!key) {
+                               for (i = 0; i < NUM_DEFAULT_KEYS; i++) {
+                                       key = rcu_dereference(sdata->keys[i]);
+                                       if (key)
+                                               break;
+                               }
+                       }
+                       if (key)
+                               rx->key = key;
+               }
+               return RX_CONTINUE;
+       } else {
+               u8 keyid;
+               /*
+                * The device doesn't give us the IV so we won't be
+                * able to look up the key. That's ok though, we
+                * don't need to decrypt the frame, we just won't
+                * be able to keep statistics accurate.
+                * Except for key threshold notifications, should
+                * we somehow allow the driver to tell us which key
+                * the hardware used if this flag is set?
+                */
+               if ((status->flag & RX_FLAG_DECRYPTED) &&
+                   (status->flag & RX_FLAG_IV_STRIPPED))
+                       return RX_CONTINUE;
+               hdrlen = ieee80211_hdrlen(fc);
+               if (rx->skb->len < 8 + hdrlen)
+                       return RX_DROP_UNUSABLE; /* TODO: count this? */
+               /*
+                * no need to call ieee80211_wep_get_keyidx,
+                * it verifies a bunch of things we've done already
+                */
+               skb_copy_bits(rx->skb, hdrlen + 3, &keyid, 1);
+               keyidx = keyid >> 6;
+               /* check per-station GTK first, if multicast packet */
+               if (is_multicast_ether_addr(hdr->addr1) && rx->sta)
+                       rx->key = rcu_dereference(rx->sta->gtk[keyidx]);
+               /* if not found, try default key */
+               if (!rx->key) {
+                       rx->key = rcu_dereference(rx->sdata->keys[keyidx]);
+                       /*
+                        * RSNA-protected unicast frames should always be
+                        * sent with pairwise or station-to-station keys,
+                        * but for WEP we allow using a key index as well.
+                        */
+                       if (rx->key &&
+                           rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP40 &&
+                           rx->key->conf.cipher != WLAN_CIPHER_SUITE_WEP104 &&
+                           !is_multicast_ether_addr(hdr->addr1))
+                               rx->key = NULL;
+               }
+       }
+       if (rx->key) {
+               if (unlikely(rx->key->flags & KEY_FLAG_TAINTED))
+                       return RX_DROP_MONITOR;
+               rx->key->tx_rx_count++;
+               /* TODO: add threshold stuff again */
+       } else {
+               return RX_DROP_MONITOR;
+       }
+       switch (rx->key->conf.cipher) {
+       case WLAN_CIPHER_SUITE_WEP40:
+       case WLAN_CIPHER_SUITE_WEP104:
+               result = ieee80211_crypto_wep_decrypt(rx);
+               break;
+       case WLAN_CIPHER_SUITE_TKIP:
+               result = ieee80211_crypto_tkip_decrypt(rx);
+               break;
+       case WLAN_CIPHER_SUITE_CCMP:
+               result = ieee80211_crypto_ccmp_decrypt(rx);
+               break;
+       case WLAN_CIPHER_SUITE_AES_CMAC:
+               result = ieee80211_crypto_aes_cmac_decrypt(rx);
+               break;
+       default:
+               /*
+                * We can reach here only with HW-only algorithms
+                * but why didn't it decrypt the frame?!
+                */
+               return RX_DROP_UNUSABLE;
+       }
+       /* the hdr variable is invalid after the decrypt handlers */
+       /* either the frame has been decrypted or will be dropped */
+       status->flag |= RX_FLAG_DECRYPTED;
+       return result;
+ }
  static inline struct ieee80211_fragment_entry *
  ieee80211_reassemble_add(struct ieee80211_sub_if_data *sdata,
                         unsigned int frag, unsigned int seq, int rx_queue,
@@@ -2939,10 -2933,10 +2939,10 @@@ static void ieee80211_rx_handlers(struc
                 */
                rx->skb = skb;
  
-               CALL_RXH(ieee80211_rx_h_decrypt)
                CALL_RXH(ieee80211_rx_h_check_more_data)
                CALL_RXH(ieee80211_rx_h_uapsd_and_pspoll)
                CALL_RXH(ieee80211_rx_h_sta_process)
+               CALL_RXH(ieee80211_rx_h_decrypt)
                CALL_RXH(ieee80211_rx_h_defragment)
                CALL_RXH(ieee80211_rx_h_michael_mic_verify)
                /* must be after MMIC verify so header is counted in MPDU mic */
diff --combined net/wireless/nl80211.c
@@@ -454,12 -454,10 +454,12 @@@ static int nl80211_prepare_wdev_dump(st
                        goto out_unlock;
                }
                *rdev = wiphy_to_dev((*wdev)->wiphy);
 -              cb->args[0] = (*rdev)->wiphy_idx;
 +              /* 0 is the first index - add 1 to parse only once */
 +              cb->args[0] = (*rdev)->wiphy_idx + 1;
                cb->args[1] = (*wdev)->identifier;
        } else {
 -              struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0]);
 +              /* subtract the 1 again here */
 +              struct wiphy *wiphy = wiphy_idx_to_wiphy(cb->args[0] - 1);
                struct wireless_dev *tmp;
  
                if (!wiphy) {
@@@ -4814,9 -4812,9 +4814,9 @@@ do {                                                                        
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, dot11MeshForwarding, 0, 1,
                                  mask, NL80211_MESHCONF_FORWARDING,
                                  nla_get_u8);
 -      FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, 1, 255,
 +      FILL_IN_MESH_PARAM_IF_SET(tb, cfg, rssi_threshold, -255, 0,
                                  mask, NL80211_MESHCONF_RSSI_THRESHOLD,
 -                                nla_get_u32);
 +                                nla_get_s32);
        FILL_IN_MESH_PARAM_IF_SET(tb, cfg, ht_opmode, 0, 16,
                                  mask, NL80211_MESHCONF_HT_OPMODE,
                                  nla_get_u16);
@@@ -6593,19 -6591,30 +6593,30 @@@ static struct genl_multicast_group nl80
  static int nl80211_testmode_do(struct sk_buff *skb, struct genl_info *info)
  {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
+       struct wireless_dev *wdev =
+               __cfg80211_wdev_from_attrs(genl_info_net(info), info->attrs);
        int err;
  
+       if (!rdev->ops->testmode_cmd)
+               return -EOPNOTSUPP;
+       if (IS_ERR(wdev)) {
+               err = PTR_ERR(wdev);
+               if (err != -EINVAL)
+                       return err;
+               wdev = NULL;
+       } else if (wdev->wiphy != &rdev->wiphy) {
+               return -EINVAL;
+       }
        if (!info->attrs[NL80211_ATTR_TESTDATA])
                return -EINVAL;
  
-       err = -EOPNOTSUPP;
-       if (rdev->ops->testmode_cmd) {
-               rdev->testmode_info = info;
-               err = rdev_testmode_cmd(rdev,
+       rdev->testmode_info = info;
+       err = rdev_testmode_cmd(rdev, wdev,
                                nla_data(info->attrs[NL80211_ATTR_TESTDATA]),
                                nla_len(info->attrs[NL80211_ATTR_TESTDATA]));
-               rdev->testmode_info = NULL;
-       }
+       rdev->testmode_info = NULL;
  
        return err;
  }
@@@ -6778,14 -6787,12 +6789,14 @@@ EXPORT_SYMBOL(cfg80211_testmode_alloc_e
  
  void cfg80211_testmode_event(struct sk_buff *skb, gfp_t gfp)
  {
 +      struct cfg80211_registered_device *rdev = ((void **)skb->cb)[0];
        void *hdr = ((void **)skb->cb)[1];
        struct nlattr *data = ((void **)skb->cb)[2];
  
        nla_nest_end(skb, data);
        genlmsg_end(skb, hdr);
 -      genlmsg_multicast(skb, 0, nl80211_testmode_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), skb, 0,
 +                              nl80211_testmode_mcgrp.id, gfp);
  }
  EXPORT_SYMBOL(cfg80211_testmode_event);
  #endif
@@@ -7566,14 -7573,12 +7577,12 @@@ static int nl80211_set_cqm_txe(struct g
                               u32 rate, u32 pkts, u32 intvl)
  {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
-       struct wireless_dev *wdev;
        struct net_device *dev = info->user_ptr[1];
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
  
        if (rate > 100 || intvl > NL80211_CQM_TXE_MAX_INTVL)
                return -EINVAL;
  
-       wdev = dev->ieee80211_ptr;
        if (!rdev->ops->set_cqm_txe_config)
                return -EOPNOTSUPP;
  
@@@ -7588,13 -7593,15 +7597,15 @@@ static int nl80211_set_cqm_rssi(struct 
                                s32 threshold, u32 hysteresis)
  {
        struct cfg80211_registered_device *rdev = info->user_ptr[0];
-       struct wireless_dev *wdev;
        struct net_device *dev = info->user_ptr[1];
+       struct wireless_dev *wdev = dev->ieee80211_ptr;
  
        if (threshold > 0)
                return -EINVAL;
  
-       wdev = dev->ieee80211_ptr;
+       /* disabling - hysteresis should also be zero then */
+       if (threshold == 0)
+               hysteresis = 0;
  
        if (!rdev->ops->set_cqm_rssi_config)
                return -EOPNOTSUPP;
@@@ -7613,36 -7620,33 +7624,33 @@@ static int nl80211_set_cqm(struct sk_bu
        int err;
  
        cqm = info->attrs[NL80211_ATTR_CQM];
-       if (!cqm) {
-               err = -EINVAL;
-               goto out;
-       }
+       if (!cqm)
+               return -EINVAL;
  
        err = nla_parse_nested(attrs, NL80211_ATTR_CQM_MAX, cqm,
                               nl80211_attr_cqm_policy);
        if (err)
-               goto out;
+               return err;
  
        if (attrs[NL80211_ATTR_CQM_RSSI_THOLD] &&
            attrs[NL80211_ATTR_CQM_RSSI_HYST]) {
-               s32 threshold;
-               u32 hysteresis;
-               threshold = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
-               hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
-               err = nl80211_set_cqm_rssi(info, threshold, hysteresis);
-       } else if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
-                  attrs[NL80211_ATTR_CQM_TXE_PKTS] &&
-                  attrs[NL80211_ATTR_CQM_TXE_INTVL]) {
-               u32 rate, pkts, intvl;
-               rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]);
-               pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]);
-               intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]);
-               err = nl80211_set_cqm_txe(info, rate, pkts, intvl);
-       } else
-               err = -EINVAL;
+               s32 threshold = nla_get_s32(attrs[NL80211_ATTR_CQM_RSSI_THOLD]);
+               u32 hysteresis = nla_get_u32(attrs[NL80211_ATTR_CQM_RSSI_HYST]);
  
- out:
-       return err;
+               return nl80211_set_cqm_rssi(info, threshold, hysteresis);
+       }
+       if (attrs[NL80211_ATTR_CQM_TXE_RATE] &&
+           attrs[NL80211_ATTR_CQM_TXE_PKTS] &&
+           attrs[NL80211_ATTR_CQM_TXE_INTVL]) {
+               u32 rate = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_RATE]);
+               u32 pkts = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_PKTS]);
+               u32 intvl = nla_get_u32(attrs[NL80211_ATTR_CQM_TXE_INTVL]);
+               return nl80211_set_cqm_txe(info, rate, pkts, intvl);
+       }
+       return -EINVAL;
  }
  
  static int nl80211_join_mesh(struct sk_buff *skb, struct genl_info *info)
@@@ -10510,8 -10514,7 +10518,8 @@@ void cfg80211_mgmt_tx_status(struct wir
  
        genlmsg_end(msg, hdr);
  
 -      genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, gfp);
 +      genlmsg_multicast_netns(wiphy_net(&rdev->wiphy), msg, 0,
 +                              nl80211_mlme_mcgrp.id, gfp);
        return;
  
   nla_put_failure: