Commit d7129e19 authored by Johannes Berg's avatar Johannes Berg Committed by John W. Linville

iwlwifi: revamp bss_info_changed

My earlier patch,
	"mac80211: unify config_interface and bss_info_changed"
introduced a bug in iwlwifi where it will do some things
incorrectly now when reassociating.

Revamp iwl_bss_info_changed to fix that issue and make it
easier to read. Also, while at it, add comments about things
that it should do but currently doesn't.

Finally, also improve the locking in the function.
Signed-off-by: default avatarJohannes Berg <johannes@sipsolutions.net>
Signed-off-by: default avatarReinette Chatre <reinette.chatre@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent 87e501b3
...@@ -2390,39 +2390,46 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, ...@@ -2390,39 +2390,46 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
priv->ibss_beacon = ieee80211_beacon_get(hw, vif); priv->ibss_beacon = ieee80211_beacon_get(hw, vif);
} }
if ((changes & BSS_CHANGED_BSSID) && !iwl_is_rfkill(priv)) { if (changes & BSS_CHANGED_BEACON_INT) {
/* If there is currently a HW scan going on in the background priv->beacon_int = bss_conf->beacon_int;
* then we need to cancel it else the RXON below will fail. */ /* TODO: in AP mode, do something to make this take effect */
}
if (changes & BSS_CHANGED_BSSID) {
IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
/*
* If there is currently a HW scan going on in the
* background then we need to cancel it else the RXON
* below/in post_associate will fail.
*/
if (iwl_scan_cancel_timeout(priv, 100)) { if (iwl_scan_cancel_timeout(priv, 100)) {
IWL_WARN(priv, "Aborted scan still in progress " IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
"after 100ms\n");
IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n"); IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
return; return;
} }
memcpy(priv->staging_rxon.bssid_addr,
bss_conf->bssid, ETH_ALEN);
/* TODO: Audit driver for usage of these members and see /* mac80211 only sets assoc when in STATION mode */
* if mac80211 deprecates them (priv->bssid looks like it if (priv->iw_mode == NL80211_IFTYPE_ADHOC ||
* shouldn't be there, but I haven't scanned the IBSS code bss_conf->assoc) {
* to verify) - jpk */ memcpy(priv->staging_rxon.bssid_addr,
memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN); bss_conf->bssid, ETH_ALEN);
if (priv->iw_mode == NL80211_IFTYPE_AP) /* currently needed in a few places */
iwlcore_config_ap(priv); memcpy(priv->bssid, bss_conf->bssid, ETH_ALEN);
else { } else {
int rc = iwlcore_commit_rxon(priv); priv->staging_rxon.filter_flags &=
if ((priv->iw_mode == NL80211_IFTYPE_STATION) && rc) ~RXON_FILTER_ASSOC_MSK;
iwl_rxon_add_station(
priv, priv->active_rxon.bssid_addr, 1);
} }
} else if (!iwl_is_rfkill(priv)) {
iwl_scan_cancel_timeout(priv, 100);
priv->staging_rxon.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
iwlcore_commit_rxon(priv);
} }
/*
* This needs to be after setting the BSSID in case
* mac80211 decides to do both changes at once because
* it will invoke post_associate.
*/
if (priv->iw_mode == NL80211_IFTYPE_ADHOC && if (priv->iw_mode == NL80211_IFTYPE_ADHOC &&
changes & BSS_CHANGED_BEACON) { changes & BSS_CHANGED_BEACON) {
struct sk_buff *beacon = ieee80211_beacon_get(hw, vif); struct sk_buff *beacon = ieee80211_beacon_get(hw, vif);
...@@ -2431,8 +2438,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, ...@@ -2431,8 +2438,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
iwl_mac_beacon_update(hw, beacon); iwl_mac_beacon_update(hw, beacon);
} }
mutex_unlock(&priv->mutex);
if (changes & BSS_CHANGED_ERP_PREAMBLE) { if (changes & BSS_CHANGED_ERP_PREAMBLE) {
IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n", IWL_DEBUG_MAC80211(priv, "ERP_PREAMBLE %d\n",
bss_conf->use_short_preamble); bss_conf->use_short_preamble);
...@@ -2450,6 +2455,23 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, ...@@ -2450,6 +2455,23 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK; priv->staging_rxon.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
} }
if (changes & BSS_CHANGED_BASIC_RATES) {
/* XXX use this information
*
* To do that, remove code from iwl_set_rate() and put something
* like this here:
*
if (A-band)
priv->staging_rxon.ofdm_basic_rates =
bss_conf->basic_rates;
else
priv->staging_rxon.ofdm_basic_rates =
bss_conf->basic_rates >> 4;
priv->staging_rxon.cck_basic_rates =
bss_conf->basic_rates & 0xF;
*/
}
if (changes & BSS_CHANGED_HT) { if (changes & BSS_CHANGED_HT) {
iwl_ht_conf(priv, bss_conf); iwl_ht_conf(priv, bss_conf);
...@@ -2459,10 +2481,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, ...@@ -2459,10 +2481,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
if (changes & BSS_CHANGED_ASSOC) { if (changes & BSS_CHANGED_ASSOC) {
IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc); IWL_DEBUG_MAC80211(priv, "ASSOC %d\n", bss_conf->assoc);
/* This should never happen as this function should
* never be called from interrupt context. */
if (WARN_ON_ONCE(in_interrupt()))
return;
if (bss_conf->assoc) { if (bss_conf->assoc) {
priv->assoc_id = bss_conf->aid; priv->assoc_id = bss_conf->aid;
priv->beacon_int = bss_conf->beacon_int; priv->beacon_int = bss_conf->beacon_int;
...@@ -2470,27 +2488,35 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw, ...@@ -2470,27 +2488,35 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
priv->timestamp = bss_conf->timestamp; priv->timestamp = bss_conf->timestamp;
priv->assoc_capability = bss_conf->assoc_capability; priv->assoc_capability = bss_conf->assoc_capability;
/* we have just associated, don't start scan too early /*
* leave time for EAPOL exchange to complete * We have just associated, don't start scan too early
* leave time for EAPOL exchange to complete.
*
* XXX: do this in mac80211
*/ */
priv->next_scan_jiffies = jiffies + priv->next_scan_jiffies = jiffies +
IWL_DELAY_NEXT_SCAN_AFTER_ASSOC; IWL_DELAY_NEXT_SCAN_AFTER_ASSOC;
mutex_lock(&priv->mutex); if (!iwl_is_rfkill(priv))
priv->cfg->ops->lib->post_associate(priv); priv->cfg->ops->lib->post_associate(priv);
mutex_unlock(&priv->mutex); } else
} else {
priv->assoc_id = 0; priv->assoc_id = 0;
IWL_DEBUG_MAC80211(priv, "DISASSOC %d\n", bss_conf->assoc);
}
if (changes && iwl_is_associated(priv) && priv->assoc_id) {
IWL_DEBUG_MAC80211(priv, "Changes (%#x) while associated\n",
changes);
ret = iwl_send_rxon_assoc(priv);
if (!ret) {
/* Sync active_rxon with latest change. */
memcpy((void *)&priv->active_rxon,
&priv->staging_rxon,
sizeof(struct iwl_rxon_cmd));
} }
} else if (changes && iwl_is_associated(priv) && priv->assoc_id) {
IWL_DEBUG_MAC80211(priv, "Associated Changes %d\n", changes);
ret = iwl_send_rxon_assoc(priv);
if (!ret)
/* Sync active_rxon with latest change. */
memcpy((void *)&priv->active_rxon,
&priv->staging_rxon,
sizeof(struct iwl_rxon_cmd));
} }
mutex_unlock(&priv->mutex);
IWL_DEBUG_MAC80211(priv, "leave\n"); IWL_DEBUG_MAC80211(priv, "leave\n");
} }
EXPORT_SYMBOL(iwl_bss_info_changed); EXPORT_SYMBOL(iwl_bss_info_changed);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment