aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-agn.c
diff options
context:
space:
mode:
authorShanyu Zhao <shanyu.zhao@intel.com>2010-07-28 16:40:39 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-08-24 16:32:01 -0400
commitaa2dc6b529d781a375f7ad3185198f6315865b06 (patch)
tree86941fc4b57927321c2f8f96630aec4574b1212d /drivers/net/wireless/iwlwifi/iwl-agn.c
parent81e95430aaa898799421617c2db2882386bab69a (diff)
iwlwifi: avoid race condition in channel change
When iwl_mac_config() is called by mac80211, the channel pointer hw->conf->channel can potentially change, resulting in mismatch band and channel number when configuring RXON command. To avoid this situation, save the channel pointer in local variables and validate the channel before using it. Note that priv->mutex is locked during the whole function so the local variables are safe. Same change is applied to iwl_mac_channel_switch() since basically it copies code from iwl_mac_config(). Also removed an outdated comment in the flow. Signed-off-by: Shanyu Zhao <shanyu.zhao@intel.com> Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-agn.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c14
1 files changed, 6 insertions, 8 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index eecfec7c4063..61ecd180982e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -3632,6 +3632,7 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
3632 struct iwl_priv *priv = hw->priv; 3632 struct iwl_priv *priv = hw->priv;
3633 const struct iwl_channel_info *ch_info; 3633 const struct iwl_channel_info *ch_info;
3634 struct ieee80211_conf *conf = &hw->conf; 3634 struct ieee80211_conf *conf = &hw->conf;
3635 struct ieee80211_channel *channel = ch_switch->channel;
3635 struct iwl_ht_config *ht_conf = &priv->current_ht_config; 3636 struct iwl_ht_config *ht_conf = &priv->current_ht_config;
3636 u16 ch; 3637 u16 ch;
3637 unsigned long flags = 0; 3638 unsigned long flags = 0;
@@ -3655,10 +3656,10 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
3655 mutex_lock(&priv->mutex); 3656 mutex_lock(&priv->mutex);
3656 if (priv->cfg->ops->lib->set_channel_switch) { 3657 if (priv->cfg->ops->lib->set_channel_switch) {
3657 3658
3658 ch = ch_switch->channel->hw_value; 3659 ch = channel->hw_value;
3659 if (le16_to_cpu(priv->active_rxon.channel) != ch) { 3660 if (le16_to_cpu(priv->active_rxon.channel) != ch) {
3660 ch_info = iwl_get_channel_info(priv, 3661 ch_info = iwl_get_channel_info(priv,
3661 conf->channel->band, 3662 channel->band,
3662 ch); 3663 ch);
3663 if (!is_channel_valid(ch_info)) { 3664 if (!is_channel_valid(ch_info)) {
3664 IWL_DEBUG_MAC80211(priv, "invalid channel\n"); 3665 IWL_DEBUG_MAC80211(priv, "invalid channel\n");
@@ -3687,15 +3688,12 @@ static void iwl_mac_channel_switch(struct ieee80211_hw *hw,
3687 } else 3688 } else
3688 ht_conf->is_40mhz = false; 3689 ht_conf->is_40mhz = false;
3689 3690
3690 /* if we are switching from ht to 2.4 clear flags 3691 if (le16_to_cpu(priv->staging_rxon.channel) != ch)
3691 * from any ht related info since 2.4 does not
3692 * support ht */
3693 if ((le16_to_cpu(priv->staging_rxon.channel) != ch))
3694 priv->staging_rxon.flags = 0; 3692 priv->staging_rxon.flags = 0;
3695 3693
3696 iwl_set_rxon_channel(priv, conf->channel); 3694 iwl_set_rxon_channel(priv, channel);
3697 iwl_set_rxon_ht(priv, ht_conf); 3695 iwl_set_rxon_ht(priv, ht_conf);
3698 iwl_set_flags_for_band(priv, conf->channel->band, 3696 iwl_set_flags_for_band(priv, channel->band,
3699 priv->vif); 3697 priv->vif);
3700 spin_unlock_irqrestore(&priv->lock, flags); 3698 spin_unlock_irqrestore(&priv->lock, flags);
3701 3699