From: Zhu Yi Date: Thu, 22 Nov 2007 02:53:22 +0000 (+0800) Subject: iwlwifi: cache mac80211 conf setting during a hardware scan X-Git-Tag: v2.6.25-rc1~1162^2~472 X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=76bb77e03f5b01fb83fb9fa79febba6e499f948b;p=linux-2.6 iwlwifi: cache mac80211 conf setting during a hardware scan This patch caches mac80211 configuration setting during a hardware scan for the iwlwifi drivers. Signed-off-by: Zhu Yi Signed-off-by: John W. Linville --- diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index 462936a74c..263b0b71c0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h @@ -714,6 +714,7 @@ struct iwl3945_priv { struct ieee80211_hw *hw; struct ieee80211_channel *ieee_channels; struct ieee80211_rate *ieee_rates; + struct ieee80211_conf *cache_conf; /* temporary frame storage list */ struct list_head free_frames; diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.h b/drivers/net/wireless/iwlwifi/iwl-4965.h index 42ce27f2ee..dda2bfbcb0 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.h +++ b/drivers/net/wireless/iwlwifi/iwl-4965.h @@ -1044,6 +1044,7 @@ struct iwl4965_priv { struct ieee80211_hw *hw; struct ieee80211_channel *ieee_channels; struct ieee80211_rate *ieee_rates; + struct ieee80211_conf *cache_conf; /* temporary frame storage list */ struct list_head free_frames; diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index ae352daeb3..bab42a1351 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c @@ -6965,6 +6965,8 @@ static void iwl3945_bg_abort_scan(struct work_struct *work) mutex_unlock(&priv->mutex); } +static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); + static void iwl3945_bg_scan_completed(struct work_struct *work) { struct iwl3945_priv *priv = @@ -6975,6 +6977,9 @@ static void iwl3945_bg_scan_completed(struct work_struct *work) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; + if (priv->cache_conf) + iwl3945_mac_config(priv->hw, priv->cache_conf); + ieee80211_scan_completed(priv->hw); /* Since setting the TXPOWER may have been deferred while @@ -7104,23 +7109,38 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co struct iwl3945_priv *priv = hw->priv; const struct iwl3945_channel_info *ch_info; unsigned long flags; + int ret = 0; mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel); if (!iwl3945_is_ready(priv)) { IWL_DEBUG_MAC80211("leave - not ready\n"); - mutex_unlock(&priv->mutex); - return -EIO; + ret = -EIO; + goto out; } /* TODO: Figure out how to get ieee80211_local->sta_scanning w/ only * what is exposed through include/ declarations */ if (unlikely(!iwl3945_param_disable_hw_scan && test_bit(STATUS_SCANNING, &priv->status))) { - IWL_DEBUG_MAC80211("leave - scanning\n"); + + if (priv->cache_conf) + IWL_DEBUG_MAC80211("leave - still scanning\n"); + else { + /* Cache the configuration now so that we can + * replay it after the hardware scan is finished. */ + priv->cache_conf = kmalloc(sizeof(*conf), GFP_KERNEL); + if (priv->cache_conf) { + memcpy(priv->cache_conf, conf, sizeof(*conf)); + IWL_DEBUG_MAC80211("leave - scanning\n"); + } else { + IWL_DEBUG_MAC80211("leave - no memory\n"); + ret = -ENOMEM; + } + } mutex_unlock(&priv->mutex); - return 0; + return ret; } spin_lock_irqsave(&priv->lock, flags); @@ -7131,8 +7151,8 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co conf->channel, conf->phymode); IWL_DEBUG_MAC80211("leave - invalid channel\n"); spin_unlock_irqrestore(&priv->lock, flags); - mutex_unlock(&priv->mutex); - return -EINVAL; + ret = -EINVAL; + goto out; } iwl3945_set_rxon_channel(priv, conf->phymode, conf->channel); @@ -7149,8 +7169,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co #ifdef IEEE80211_CONF_CHANNEL_SWITCH if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) { iwl3945_hw_channel_switch(priv, conf->channel); - mutex_unlock(&priv->mutex); - return 0; + goto out; } #endif @@ -7158,14 +7177,13 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co if (!conf->radio_enabled) { IWL_DEBUG_MAC80211("leave - radio disabled\n"); - mutex_unlock(&priv->mutex); - return 0; + goto out; } if (iwl3945_is_rfkill(priv)) { IWL_DEBUG_MAC80211("leave - RF kill\n"); - mutex_unlock(&priv->mutex); - return -EIO; + ret = -EIO; + goto out; } iwl3945_set_rate(priv); @@ -7178,9 +7196,13 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co IWL_DEBUG_MAC80211("leave\n"); +out: + if (priv->cache_conf) { + kfree(priv->cache_conf); + priv->cache_conf = NULL; + } mutex_unlock(&priv->mutex); - - return 0; + return ret; } static void iwl3945_config_ap(struct iwl3945_priv *priv) diff --git a/drivers/net/wireless/iwlwifi/iwl4965-base.c b/drivers/net/wireless/iwlwifi/iwl4965-base.c index 6a8c629ce0..8bc2634bb4 100644 --- a/drivers/net/wireless/iwlwifi/iwl4965-base.c +++ b/drivers/net/wireless/iwlwifi/iwl4965-base.c @@ -7403,6 +7403,8 @@ static void iwl4965_bg_abort_scan(struct work_struct *work) mutex_unlock(&priv->mutex); } +static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *conf); + static void iwl4965_bg_scan_completed(struct work_struct *work) { struct iwl4965_priv *priv = @@ -7413,6 +7415,9 @@ static void iwl4965_bg_scan_completed(struct work_struct *work) if (test_bit(STATUS_EXIT_PENDING, &priv->status)) return; + if (priv->cache_conf) + iwl4965_mac_config(priv->hw, priv->cache_conf); + ieee80211_scan_completed(priv->hw); /* Since setting the TXPOWER may have been deferred while @@ -7541,23 +7546,38 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co struct iwl4965_priv *priv = hw->priv; const struct iwl4965_channel_info *ch_info; unsigned long flags; + int ret = 0; mutex_lock(&priv->mutex); IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel); if (!iwl4965_is_ready(priv)) { IWL_DEBUG_MAC80211("leave - not ready\n"); - mutex_unlock(&priv->mutex); - return -EIO; + ret = -EIO; + goto out; } /* TODO: Figure out how to get ieee80211_local->sta_scanning w/ only * what is exposed through include/ declarations */ if (unlikely(!iwl4965_param_disable_hw_scan && test_bit(STATUS_SCANNING, &priv->status))) { - IWL_DEBUG_MAC80211("leave - scanning\n"); + + if (unlikely(priv->cache_conf)) + IWL_DEBUG_MAC80211("leave - still scanning\n"); + else { + /* Cache the configuration now so that we can + * replay it after the hardware scan is finished. */ + priv->cache_conf = kmalloc(sizeof(*conf), GFP_KERNEL); + if (priv->cache_conf) { + memcpy(priv->cache_conf, conf, sizeof(*conf)); + IWL_DEBUG_MAC80211("leave - scanning\n"); + } else { + IWL_DEBUG_MAC80211("leave - no memory\n"); + ret = -ENOMEM; + } + } mutex_unlock(&priv->mutex); - return 0; + return ret; } spin_lock_irqsave(&priv->lock, flags); @@ -7568,8 +7588,8 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co conf->channel, conf->phymode); IWL_DEBUG_MAC80211("leave - invalid channel\n"); spin_unlock_irqrestore(&priv->lock, flags); - mutex_unlock(&priv->mutex); - return -EINVAL; + ret = -EINVAL; + goto out; } #ifdef CONFIG_IWL4965_HT @@ -7598,8 +7618,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co #ifdef IEEE80211_CONF_CHANNEL_SWITCH if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) { iwl4965_hw_channel_switch(priv, conf->channel); - mutex_unlock(&priv->mutex); - return 0; + goto out; } #endif @@ -7607,14 +7626,13 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co if (!conf->radio_enabled) { IWL_DEBUG_MAC80211("leave - radio disabled\n"); - mutex_unlock(&priv->mutex); - return 0; + goto out; } if (iwl4965_is_rfkill(priv)) { IWL_DEBUG_MAC80211("leave - RF kill\n"); - mutex_unlock(&priv->mutex); - return -EIO; + ret = -EIO; + goto out; } iwl4965_set_rate(priv); @@ -7627,9 +7645,13 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co IWL_DEBUG_MAC80211("leave\n"); +out: + if (priv->cache_conf) { + kfree(priv->cache_conf); + priv->cache_conf = NULL; + } mutex_unlock(&priv->mutex); - - return 0; + return ret; } static void iwl4965_config_ap(struct iwl4965_priv *priv)