struct sta_info *sta;
u32 changed = 0;
u16 ht_opmode;
- enum nl80211_channel_type channel_type;
+ bool disable_40 = false;
sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
- channel_type = local->hw.conf.channel_type;
- if (WARN_ON_ONCE(channel_type == NL80211_CHAN_NO_HT))
- return 0;
-
- channel_type = ieee80211_get_tx_channel_type(local, channel_type);
+ 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;
+ }
/* This can change during the lifetime of the BSS */
if (!(ht_oper->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY))
- channel_type = NL80211_CHAN_HT20;
+ disable_40 = true;
- if (!reconfig || (sdata->u.mgd.tx_chantype != channel_type)) {
- if (reconfig) {
- /*
- * Whenever the AP announces the HT mode changed
- * (e.g. 40 MHz intolerant) stop queues to avoid
- * sending out frames while the rate control is
- * reconfiguring.
- */
- 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;
- rcu_read_lock();
- sta = sta_info_get(sdata, bssid);
- if (sta)
- rate_control_rate_update(local, sband, sta,
- IEEE80211_RC_HT_CHANGED,
- channel_type);
- rcu_read_unlock();
+ if (sta && (!reconfig ||
+ (disable_40 != !!(sta->sta.ht_cap.cap &
+ IEEE80211_HT_CAP_SUP_WIDTH_20_40)))) {
- sdata->u.mgd.tx_chantype = channel_type;
+ 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 (reconfig)
- 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(ht_oper->operation_mode);
if (!local->ops->conf_tx)
return;
- if (local->hw.queues < 4)
+ if (local->hw.queues < IEEE80211_NUM_ACS)
return;
if (!wmm_param)
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
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,
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++;
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 "
else
ifmgd->flags |= IEEE80211_STA_CONNECTION_POLL;
+ mutex_unlock(&sdata->local->mtx);
+
if (already)
goto out;
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;
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;
ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
elems.ht_cap_elem, &sta->sta.ht_cap);
+ sta->supports_40mhz =
+ sta->sta.ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+
rate_control_rate_init(sta);
if (ifmgd->flags & IEEE80211_STA_MFP_ENABLED)
/* 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));
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_operation_ie =
*/
printk(KERN_DEBUG "%s: waiting for beacon from %pM\n",
sdata->name, ifmgd->bssid);
- assoc_data->timeout = jiffies +
- TU_TO_EXP_TIME(req->bss->beacon_interval);
+ assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval);
} else {
assoc_data->have_beacon = true;
assoc_data->sent_assoc = false;
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;