Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net
[deliverable/linux.git] / net / mac80211 / mlme.c
index f76da5b3f5c5864f0b649187fca47517d244ce77..03f93f958fa41cb5948f11375fd6392faf16d37d 100644 (file)
@@ -171,122 +171,64 @@ static int ecw2cw(int ecw)
        return (1 << ecw) - 1;
 }
 
-/*
- * ieee80211_enable_ht should be called only after the operating band
- * has been determined as ht configuration depends on the hw's
- * HT abilities for a specific band.
- */
-static u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata,
-                              struct ieee80211_ht_info *hti,
-                              const u8 *bssid, u16 ap_ht_cap_flags,
-                              bool beacon_htcap_ie)
+static u32 ieee80211_config_ht_tx(struct ieee80211_sub_if_data *sdata,
+                                 struct ieee80211_ht_operation *ht_oper,
+                                 const u8 *bssid, bool reconfig)
 {
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_supported_band *sband;
        struct sta_info *sta;
        u32 changed = 0;
-       int hti_cfreq;
        u16 ht_opmode;
-       bool enable_ht = true;
-       enum nl80211_channel_type prev_chantype;
-       enum nl80211_channel_type rx_channel_type = NL80211_CHAN_NO_HT;
-       enum nl80211_channel_type tx_channel_type;
+       bool disable_40 = false;
 
        sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
-       prev_chantype = sdata->vif.bss_conf.channel_type;
 
-
-       hti_cfreq = ieee80211_channel_to_frequency(hti->control_chan,
-                                                  sband->band);
-       /* check that channel matches the right operating channel */
-       if (local->hw.conf.channel->center_freq != hti_cfreq) {
-               /* Some APs mess this up, evidently.
-                * Netgear WNDR3700 sometimes reports 4 higher than
-                * the actual channel, for instance.
-                */
-               printk(KERN_DEBUG
-                      "%s: Wrong control channel in association"
-                      " response: configured center-freq: %d"
-                      " hti-cfreq: %d  hti->control_chan: %d"
-                      " band: %d.  Disabling HT.\n",
-                      sdata->name,
-                      local->hw.conf.channel->center_freq,
-                      hti_cfreq, hti->control_chan,
-                      sband->band);
-               enable_ht = false;
-       }
-
-       if (enable_ht) {
-               rx_channel_type = NL80211_CHAN_HT20;
-
-               if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) &&
-                   !ieee80111_cfg_override_disables_ht40(sdata) &&
-                   (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) &&
-                   (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) {
-                       switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
-                       case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
-                               rx_channel_type = NL80211_CHAN_HT40PLUS;
-                               break;
-                       case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
-                               rx_channel_type = NL80211_CHAN_HT40MINUS;
-                               break;
-                       }
-               }
+       switch (sdata->vif.bss_conf.channel_type) {
+       case NL80211_CHAN_HT40PLUS:
+               if (local->hw.conf.channel->flags & IEEE80211_CHAN_NO_HT40PLUS)
+                       disable_40 = true;
+               break;
+       case NL80211_CHAN_HT40MINUS:
+               if (local->hw.conf.channel->flags & IEEE80211_CHAN_NO_HT40MINUS)
+                       disable_40 = true;
+               break;
+       default:
+               break;
        }
 
-       tx_channel_type = ieee80211_get_tx_channel_type(local, rx_channel_type);
-
-       if (local->tmp_channel)
-               local->tmp_channel_type = rx_channel_type;
+       /* This can change during the lifetime of the BSS */
+       if (!(ht_oper->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY))
+               disable_40 = true;
 
-       if (!ieee80211_set_channel_type(local, sdata, rx_channel_type)) {
-               /* can only fail due to HT40+/- mismatch */
-               rx_channel_type = NL80211_CHAN_HT20;
-               WARN_ON(!ieee80211_set_channel_type(local, sdata,
-                                                   rx_channel_type));
-       }
-
-       if (beacon_htcap_ie && (prev_chantype != rx_channel_type)) {
-               /*
-                * Whenever the AP announces the HT mode change that can be
-                * 40MHz intolerant or etc., it would be safer to stop tx
-                * queues before doing hw config to avoid buffer overflow.
-                */
-               ieee80211_stop_queues_by_reason(&sdata->local->hw,
-                               IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE);
+       mutex_lock(&local->sta_mtx);
+       sta = sta_info_get(sdata, bssid);
 
-               /* flush out all packets */
-               synchronize_net();
+       WARN_ON_ONCE(!sta);
 
-               drv_flush(local, false);
-       }
+       if (sta && !sta->supports_40mhz)
+               disable_40 = true;
 
-       /* channel_type change automatically detected */
-       ieee80211_hw_config(local, 0);
+       if (sta && (!reconfig ||
+                   (disable_40 != !!(sta->sta.ht_cap.cap &
+                                       IEEE80211_HT_CAP_SUP_WIDTH_20_40)))) {
 
-       if (prev_chantype != tx_channel_type) {
-               rcu_read_lock();
-               sta = sta_info_get(sdata, bssid);
-               if (sta)
-                       rate_control_rate_update(local, sband, sta,
-                                                IEEE80211_RC_HT_CHANGED,
-                                                tx_channel_type);
-               rcu_read_unlock();
+               if (disable_40)
+                       sta->sta.ht_cap.cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+               else
+                       sta->sta.ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 
-               if (beacon_htcap_ie)
-                       ieee80211_wake_queues_by_reason(&sdata->local->hw,
-                               IEEE80211_QUEUE_STOP_REASON_CHTYPE_CHANGE);
+               rate_control_rate_update(local, sband, sta,
+                                        IEEE80211_RC_BW_CHANGED);
        }
+       mutex_unlock(&local->sta_mtx);
 
-       ht_opmode = le16_to_cpu(hti->operation_mode);
+       ht_opmode = le16_to_cpu(ht_oper->operation_mode);
 
        /* if bss configuration changed store the new one */
-       if (sdata->ht_opmode_valid != enable_ht ||
-           sdata->vif.bss_conf.ht_operation_mode != ht_opmode ||
-           prev_chantype != rx_channel_type) {
+       if (!reconfig || (sdata->vif.bss_conf.ht_operation_mode != ht_opmode)) {
                changed |= BSS_CHANGED_HT;
                sdata->vif.bss_conf.ht_operation_mode = ht_opmode;
-               sdata->ht_opmode_valid = enable_ht;
        }
 
        return changed;
@@ -316,12 +258,12 @@ static int ieee80211_compatible_rates(const u8 *supp_rates, int supp_rates_len,
 }
 
 static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
-                               struct sk_buff *skb, const u8 *ht_info_ie,
+                               struct sk_buff *skb, const u8 *ht_oper_ie,
                                struct ieee80211_supported_band *sband,
                                struct ieee80211_channel *channel,
                                enum ieee80211_smps_mode smps)
 {
-       struct ieee80211_ht_info *ht_info;
+       struct ieee80211_ht_operation *ht_oper;
        u8 *pos;
        u32 flags = channel->flags;
        u16 cap;
@@ -329,21 +271,21 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
 
        BUILD_BUG_ON(sizeof(ht_cap) != sizeof(sband->ht_cap));
 
-       if (!ht_info_ie)
+       if (!ht_oper_ie)
                return;
 
-       if (ht_info_ie[1] < sizeof(struct ieee80211_ht_info))
+       if (ht_oper_ie[1] < sizeof(struct ieee80211_ht_operation))
                return;
 
        memcpy(&ht_cap, &sband->ht_cap, sizeof(ht_cap));
        ieee80211_apply_htcap_overrides(sdata, &ht_cap);
 
-       ht_info = (struct ieee80211_ht_info *)(ht_info_ie + 2);
+       ht_oper = (struct ieee80211_ht_operation *)(ht_oper_ie + 2);
 
        /* determine capability flags */
        cap = ht_cap.cap;
 
-       switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
+       switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
        case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
                if (flags & IEEE80211_CHAN_NO_HT40PLUS) {
                        cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
@@ -358,6 +300,16 @@ static void ieee80211_add_ht_ie(struct ieee80211_sub_if_data *sdata,
                break;
        }
 
+       /*
+        * If 40 MHz was disabled associate as though we weren't
+        * capable of 40 MHz -- some broken APs will never fall
+        * back to trying to transmit in 20 MHz.
+        */
+       if (sdata->u.mgd.flags & IEEE80211_STA_DISABLE_40MHZ) {
+               cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+               cap &= ~IEEE80211_HT_CAP_SGI_40;
+       }
+
        /* set SM PS mode properly */
        cap &= ~IEEE80211_HT_CAP_SM_PS;
        switch (smps) {
@@ -557,7 +509,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata)
        }
 
        if (!(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
-               ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_information_ie,
+               ieee80211_add_ht_ie(sdata, skb, assoc_data->ht_operation_ie,
                                    sband, local->oper_channel, ifmgd->ap_smps);
 
        /* if present, add any custom non-vendor IEs that go after HT */
@@ -1182,7 +1134,7 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local,
        if (!local->ops->conf_tx)
                return;
 
-       if (local->hw.queues < 4)
+       if (local->hw.queues < IEEE80211_NUM_ACS)
                return;
 
        if (!wmm_param)
@@ -1435,7 +1387,6 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        sdata->vif.bss_conf.assoc = false;
 
        /* on the next assoc, re-program HT parameters */
-       sdata->ht_opmode_valid = false;
        memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
        memset(&ifmgd->ht_capa_mask, 0, sizeof(ifmgd->ht_capa_mask));
 
@@ -1496,19 +1447,24 @@ void ieee80211_sta_rx_notify(struct ieee80211_sub_if_data *sdata,
 static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
+       struct ieee80211_local *local = sdata->local;
 
+       mutex_lock(&local->mtx);
        if (!(ifmgd->flags & (IEEE80211_STA_BEACON_POLL |
-                             IEEE80211_STA_CONNECTION_POLL)))
-           return;
+                             IEEE80211_STA_CONNECTION_POLL))) {
+               mutex_unlock(&local->mtx);
+               return;
+       }
 
        ifmgd->flags &= ~(IEEE80211_STA_CONNECTION_POLL |
                          IEEE80211_STA_BEACON_POLL);
-       mutex_lock(&sdata->local->iflist_mtx);
-       ieee80211_recalc_ps(sdata->local, -1);
-       mutex_unlock(&sdata->local->iflist_mtx);
+
+       mutex_lock(&local->iflist_mtx);
+       ieee80211_recalc_ps(local, -1);
+       mutex_unlock(&local->iflist_mtx);
 
        if (sdata->local->hw.flags & IEEE80211_HW_CONNECTION_MONITOR)
-               return;
+               goto out;
 
        /*
         * We've received a probe response, but are not sure whether
@@ -1520,6 +1476,9 @@ static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
        mod_timer(&ifmgd->conn_mon_timer,
                  round_jiffies_up(jiffies +
                                   IEEE80211_CONNECTION_IDLE_TIME));
+out:
+       ieee80211_run_deferred_scan(local);
+       mutex_unlock(&local->mtx);
 }
 
 void ieee80211_sta_tx_notify(struct ieee80211_sub_if_data *sdata,
@@ -1567,14 +1526,23 @@ static void ieee80211_mgd_probe_ap_send(struct ieee80211_sub_if_data *sdata)
                ifmgd->nullfunc_failed = false;
                ieee80211_send_nullfunc(sdata->local, sdata, 0);
        } else {
+               int ssid_len;
+
                ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
-               ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid[1], NULL, 0,
-                                        (u32) -1, true, false);
+               if (WARN_ON_ONCE(ssid == NULL))
+                       ssid_len = 0;
+               else
+                       ssid_len = ssid[1];
+
+               ieee80211_send_probe_req(sdata, dst, ssid + 2, ssid_len, NULL,
+                                        0, (u32) -1, true, false);
        }
 
        ifmgd->probe_send_count++;
        ifmgd->probe_timeout = jiffies + msecs_to_jiffies(probe_wait_ms);
        run_again(ifmgd, ifmgd->probe_timeout);
+       if (sdata->local->hw.flags & IEEE80211_HW_REPORTS_TX_ACK_STATUS)
+               drv_flush(sdata->local, false);
 }
 
 static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
@@ -1586,17 +1554,18 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
        if (!ieee80211_sdata_running(sdata))
                return;
 
-       if (sdata->local->scanning)
-               return;
-
-       if (sdata->local->tmp_channel)
-               return;
-
        mutex_lock(&ifmgd->mtx);
 
        if (!ifmgd->associated)
                goto out;
 
+       mutex_lock(&sdata->local->mtx);
+
+       if (sdata->local->tmp_channel || sdata->local->scanning) {
+               mutex_unlock(&sdata->local->mtx);
+               goto out;
+       }
+
 #ifdef CONFIG_MAC80211_VERBOSE_DEBUG
        if (beacon && net_ratelimit())
                printk(KERN_DEBUG "%s: detected beacon loss from AP "
@@ -1623,6 +1592,8 @@ static void ieee80211_mgd_probe_ap(struct ieee80211_sub_if_data *sdata,
        else
                ifmgd->flags |= IEEE80211_STA_CONNECTION_POLL;
 
+       mutex_unlock(&sdata->local->mtx);
+
        if (already)
                goto out;
 
@@ -1643,6 +1614,7 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
        struct sk_buff *skb;
        const u8 *ssid;
+       int ssid_len;
 
        if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
                return NULL;
@@ -1653,8 +1625,13 @@ struct sk_buff *ieee80211_ap_probereq_get(struct ieee80211_hw *hw,
                return NULL;
 
        ssid = ieee80211_bss_get_ie(ifmgd->associated, WLAN_EID_SSID);
+       if (WARN_ON_ONCE(ssid == NULL))
+               ssid_len = 0;
+       else
+               ssid_len = ssid[1];
+
        skb = ieee80211_build_probe_req(sdata, ifmgd->associated->bssid,
-                                       (u32) -1, ssid + 2, ssid[1],
+                                       (u32) -1, ssid + 2, ssid_len,
                                        NULL, 0, true);
 
        return skb;
@@ -2000,7 +1977,6 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf;
        u32 changed = 0;
        int err;
-       u16 ap_ht_cap_flags;
 
        /* AssocResp and ReassocResp have identical structure */
 
@@ -2051,7 +2027,8 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
                ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
                                elems.ht_cap_elem, &sta->sta.ht_cap);
 
-       ap_ht_cap_flags = sta->sta.ht_cap.cap;
+       sta->supports_40mhz =
+               sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
 
        rate_control_rate_init(sta);
 
@@ -2092,11 +2069,10 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
                ieee80211_set_wmm_default(sdata, false);
        changed |= BSS_CHANGED_QOS;
 
-       if (elems.ht_info_elem && elems.wmm_param &&
+       if (elems.ht_operation && elems.wmm_param &&
            !(ifmgd->flags & IEEE80211_STA_DISABLE_11N))
-               changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
-                                              cbss->bssid, ap_ht_cap_flags,
-                                              false);
+               changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation,
+                                                 cbss->bssid, false);
 
        /* set AID and assoc capability,
         * ieee80211_set_associated() will tell the driver */
@@ -2319,7 +2295,7 @@ static const u64 care_about_ies =
        (1ULL << WLAN_EID_CHANNEL_SWITCH) |
        (1ULL << WLAN_EID_PWR_CONSTRAINT) |
        (1ULL << WLAN_EID_HT_CAPABILITY) |
-       (1ULL << WLAN_EID_HT_INFORMATION);
+       (1ULL << WLAN_EID_HT_OPERATION);
 
 static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                                     struct ieee80211_mgmt *mgmt,
@@ -2468,11 +2444,13 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
        if (local->hw.flags & IEEE80211_HW_PS_NULLFUNC_STACK) {
                if (directed_tim) {
                        if (local->hw.conf.dynamic_ps_timeout > 0) {
-                               local->hw.conf.flags &= ~IEEE80211_CONF_PS;
-                               ieee80211_hw_config(local,
-                                                   IEEE80211_CONF_CHANGE_PS);
+                               if (local->hw.conf.flags & IEEE80211_CONF_PS) {
+                                       local->hw.conf.flags &= ~IEEE80211_CONF_PS;
+                                       ieee80211_hw_config(local,
+                                                           IEEE80211_CONF_CHANGE_PS);
+                               }
                                ieee80211_send_nullfunc(local, sdata, 0);
-                       } else {
+                       } else if (!local->pspolling && sdata->u.mgd.powersave) {
                                local->pspolling = true;
 
                                /*
@@ -2504,31 +2482,14 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
                        erp_valid, erp_value);
 
 
-       if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param &&
+       if (elems.ht_cap_elem && elems.ht_operation && elems.wmm_param &&
            !(ifmgd->flags & IEEE80211_STA_DISABLE_11N)) {
-               struct sta_info *sta;
                struct ieee80211_supported_band *sband;
-               u16 ap_ht_cap_flags;
-
-               rcu_read_lock();
-
-               sta = sta_info_get(sdata, bssid);
-               if (WARN_ON(!sta)) {
-                       rcu_read_unlock();
-                       return;
-               }
 
                sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
 
-               ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
-                               elems.ht_cap_elem, &sta->sta.ht_cap);
-
-               ap_ht_cap_flags = sta->sta.ht_cap.cap;
-
-               rcu_read_unlock();
-
-               changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem,
-                                              bssid, ap_ht_cap_flags, true);
+               changed |= ieee80211_config_ht_tx(sdata, elems.ht_operation,
+                                                 bssid, true);
        }
 
        /* Note: country IE parsing is done for us by cfg80211 */
@@ -3060,6 +3021,11 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
        struct sta_info *sta;
        bool have_sta = false;
        int err;
+       int ht_cfreq;
+       enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT;
+       const u8 *ht_oper_ie;
+       const struct ieee80211_ht_operation *ht_oper = NULL;
+       struct ieee80211_supported_band *sband;
 
        if (WARN_ON(!ifmgd->auth_data && !ifmgd->assoc_data))
                return -EINVAL;
@@ -3081,17 +3047,76 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
        mutex_unlock(&local->mtx);
 
        /* switch to the right channel */
+       sband = local->hw.wiphy->bands[cbss->channel->band];
+
+       ifmgd->flags &= ~IEEE80211_STA_DISABLE_40MHZ;
+
+       if (sband->ht_cap.ht_supported) {
+               ht_oper_ie = cfg80211_find_ie(WLAN_EID_HT_OPERATION,
+                                             cbss->information_elements,
+                                             cbss->len_information_elements);
+               if (ht_oper_ie && ht_oper_ie[1] >= sizeof(*ht_oper))
+                       ht_oper = (void *)(ht_oper_ie + 2);
+       }
+
+       if (ht_oper) {
+               ht_cfreq = ieee80211_channel_to_frequency(ht_oper->primary_chan,
+                                                         cbss->channel->band);
+               /* check that channel matches the right operating channel */
+               if (cbss->channel->center_freq != ht_cfreq) {
+                       /*
+                        * It's possible that some APs are confused here;
+                        * Netgear WNDR3700 sometimes reports 4 higher than
+                        * the actual channel in association responses, but
+                        * since we look at probe response/beacon data here
+                        * it should be OK.
+                        */
+                       printk(KERN_DEBUG
+                              "%s: Wrong control channel: center-freq: %d"
+                              " ht-cfreq: %d ht->primary_chan: %d"
+                              " band: %d. Disabling HT.\n",
+                              sdata->name, cbss->channel->center_freq,
+                              ht_cfreq, ht_oper->primary_chan,
+                              cbss->channel->band);
+                       ht_oper = NULL;
+               }
+       }
+
+       if (ht_oper) {
+               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:
+                               channel_type = NL80211_CHAN_HT40PLUS;
+                               break;
+                       case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
+                               channel_type = NL80211_CHAN_HT40MINUS;
+                               break;
+                       }
+               }
+       }
+
+       if (!ieee80211_set_channel_type(local, sdata, channel_type)) {
+               /* can only fail due to HT40+/- mismatch */
+               channel_type = NL80211_CHAN_HT20;
+               printk(KERN_DEBUG
+                      "%s: disabling 40 MHz due to multi-vif mismatch\n",
+                      sdata->name);
+               ifmgd->flags |= IEEE80211_STA_DISABLE_40MHZ;
+               WARN_ON(!ieee80211_set_channel_type(local, sdata,
+                                                   channel_type));
+       }
+
        local->oper_channel = cbss->channel;
-       ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
+       ieee80211_hw_config(local, 0);
 
        if (!have_sta) {
-               struct ieee80211_supported_band *sband;
                u32 rates = 0, basic_rates = 0;
                bool have_higher_than_11mbit;
                int min_rate = INT_MAX, min_rate_index = -1;
 
-               sband = sdata->local->hw.wiphy->bands[cbss->channel->band];
-
                ieee80211_get_rates(sband, bss->supp_rates,
                                    bss->supp_rates_len,
                                    &rates, &basic_rates,
@@ -3311,7 +3336,7 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
        /* Also disable HT if we don't support it or the AP doesn't use WMM */
        sband = local->hw.wiphy->bands[req->bss->channel->band];
        if (!sband->ht_cap.ht_supported ||
-           local->hw.queues < 4 || !bss->wmm_used)
+           local->hw.queues < IEEE80211_NUM_ACS || !bss->wmm_used)
                ifmgd->flags |= IEEE80211_STA_DISABLE_11N;
 
        memcpy(&ifmgd->ht_capa, &req->ht_capa, sizeof(ifmgd->ht_capa));
@@ -3334,11 +3359,12 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
                ifmgd->ap_smps = ifmgd->req_smps;
 
        assoc_data->capability = req->bss->capability;
-       assoc_data->wmm = bss->wmm_used && (local->hw.queues >= 4);
+       assoc_data->wmm = bss->wmm_used &&
+                         (local->hw.queues >= IEEE80211_NUM_ACS);
        assoc_data->supp_rates = bss->supp_rates;
        assoc_data->supp_rates_len = bss->supp_rates_len;
-       assoc_data->ht_information_ie =
-               ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_INFORMATION);
+       assoc_data->ht_operation_ie =
+               ieee80211_bss_get_ie(req->bss, WLAN_EID_HT_OPERATION);
 
        if (bss->wmm_used && bss->uapsd_supported &&
            (sdata->local->hw.flags & IEEE80211_HW_SUPPORTS_UAPSD)) {
@@ -3497,7 +3523,7 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
        return 0;
 }
 
-void ieee80211_mgd_teardown(struct ieee80211_sub_if_data *sdata)
+void ieee80211_mgd_stop(struct ieee80211_sub_if_data *sdata)
 {
        struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
 
This page took 0.032567 seconds and 5 git commands to generate.