Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless
John W. Linville [Tue, 23 Oct 2012 15:41:46 +0000 (11:41 -0400)]
Conflicts:
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
net/mac80211/mlme.c

1  2 
drivers/bcma/main.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
include/net/cfg80211.h
net/bluetooth/smp.c
net/mac80211/iface.c
net/mac80211/mlme.c
net/mac80211/sta_info.c
net/mac80211/util.c
net/wireless/mlme.c

Simple merge
@@@ -3972,8 -3972,8 +3972,8 @@@ brcmf_set_management_ie(struct brcmf_cf
        u8  *iovar_ie_buf;
        u8  *curr_ie_buf;
        u8  *mgmt_ie_buf = NULL;
-       u32 mgmt_ie_buf_len;
+       int mgmt_ie_buf_len;
 -      u32 *mgmt_ie_len = 0;
 +      u32 *mgmt_ie_len;
        u32 del_add_ie_buf_len = 0;
        u32 total_ie_buf_len = 0;
        u32 parsed_ie_buf_len = 0;
Simple merge
Simple merge
Simple merge
@@@ -3181,43 -3104,44 +3183,52 @@@ static int ieee80211_prep_channel(struc
                }
        }
  
-       if (ht_oper) {
+       if (ht_oper && sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
+               /*
+                * cfg80211 already verified that the channel itself can
+                * be used, but it didn't check that we can do the right
+                * HT type, so do that here as well. If HT40 isn't allowed
+                * on this channel, disable 40 MHz operation.
+                */
 +              const u8 *ht_cap_ie;
 +              const struct ieee80211_ht_cap *ht_cap;
 +              u8 chains = 1;
 +
 +              channel_type = NL80211_CHAN_HT20;
  
-               if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) {
-                       switch (ht_oper->ht_param &
-                                       IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
-                       case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+               switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+               case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
+                       if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40PLUS)
+                               ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
+                       else
                                channel_type = NL80211_CHAN_HT40PLUS;
-                               break;
-                       case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+                       break;
+               case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+                       if (cbss->channel->flags & IEEE80211_CHAN_NO_HT40MINUS)
+                               ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
+                       else
                                channel_type = NL80211_CHAN_HT40MINUS;
-                               break;
-                       }
+                       break;
                }
 -      }
  
 -      if (!ieee80211_set_channel_type(local, sdata, channel_type)) {
 -              /* can only fail due to HT40+/- mismatch */
 -              channel_type = NL80211_CHAN_HT20;
 -              sdata_info(sdata,
 -                         "disabling 40 MHz due to multi-vif mismatch\n");
 -              ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
 -              WARN_ON(!ieee80211_set_channel_type(local, sdata,
 -                                                  channel_type));
 +              ht_cap_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY,
 +                                           cbss->information_elements,
 +                                           cbss->len_information_elements);
 +              if (ht_cap_ie && ht_cap_ie[1] >= sizeof(*ht_cap)) {
 +                      ht_cap = (void *)(ht_cap_ie + 2);
 +                      chains = ieee80211_mcs_to_chains(&ht_cap->mcs);
 +              }
 +              sdata->needed_rx_chains = min(chains, local->rx_chains);
 +      } else {
 +              sdata->needed_rx_chains = 1;
        }
  
 -      local->oper_channel = cbss->channel;
 -      ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
 +      /* will change later if needed */
 +      sdata->smps_mode = IEEE80211_SMPS_OFF;
  
 -      return 0;
 +      ieee80211_vif_release_channel(sdata);
 +      return ieee80211_vif_use_channel(sdata, cbss->channel, channel_type,
 +                                       IEEE80211_CHANCTX_SHARED);
  }
  
  static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
Simple merge
Simple merge
@@@ -477,18 -462,11 +478,11 @@@ int __cfg80211_mlme_deauth(struct cfg80
  
        ASSERT_WDEV_LOCK(wdev);
  
-       if (local_state_change) {
-               if (wdev->current_bss &&
-                   ether_addr_equal(wdev->current_bss->pub.bssid, bssid)) {
-                       cfg80211_unhold_bss(wdev->current_bss);
-                       cfg80211_put_bss(&wdev->current_bss->pub);
-                       wdev->current_bss = NULL;
-               }
+       if (local_state_change && (!wdev->current_bss ||
+           !ether_addr_equal(wdev->current_bss->pub.bssid, bssid)))
                return 0;
-       }
  
 -      return rdev->ops->deauth(&rdev->wiphy, dev, &req);
 +      return rdev_deauth(rdev, dev, &req);
  }
  
  int cfg80211_mlme_deauth(struct cfg80211_registered_device *rdev,