Commit 76bb77e0 authored by Zhu Yi's avatar Zhu Yi Committed by David S. Miller

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: default avatarZhu Yi <yi.zhu@intel.com>
Signed-off-by: default avatarJohn W. Linville <linville@tuxdriver.com>
parent a84fd345
...@@ -714,6 +714,7 @@ struct iwl3945_priv { ...@@ -714,6 +714,7 @@ struct iwl3945_priv {
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct ieee80211_channel *ieee_channels; struct ieee80211_channel *ieee_channels;
struct ieee80211_rate *ieee_rates; struct ieee80211_rate *ieee_rates;
struct ieee80211_conf *cache_conf;
/* temporary frame storage list */ /* temporary frame storage list */
struct list_head free_frames; struct list_head free_frames;
......
...@@ -1044,6 +1044,7 @@ struct iwl4965_priv { ...@@ -1044,6 +1044,7 @@ struct iwl4965_priv {
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct ieee80211_channel *ieee_channels; struct ieee80211_channel *ieee_channels;
struct ieee80211_rate *ieee_rates; struct ieee80211_rate *ieee_rates;
struct ieee80211_conf *cache_conf;
/* temporary frame storage list */ /* temporary frame storage list */
struct list_head free_frames; struct list_head free_frames;
......
...@@ -6965,6 +6965,8 @@ static void iwl3945_bg_abort_scan(struct work_struct *work) ...@@ -6965,6 +6965,8 @@ static void iwl3945_bg_abort_scan(struct work_struct *work)
mutex_unlock(&priv->mutex); 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) static void iwl3945_bg_scan_completed(struct work_struct *work)
{ {
struct iwl3945_priv *priv = struct iwl3945_priv *priv =
...@@ -6975,6 +6977,9 @@ static void iwl3945_bg_scan_completed(struct work_struct *work) ...@@ -6975,6 +6977,9 @@ static void iwl3945_bg_scan_completed(struct work_struct *work)
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return; return;
if (priv->cache_conf)
iwl3945_mac_config(priv->hw, priv->cache_conf);
ieee80211_scan_completed(priv->hw); ieee80211_scan_completed(priv->hw);
/* Since setting the TXPOWER may have been deferred while /* 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 ...@@ -7104,23 +7109,38 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
struct iwl3945_priv *priv = hw->priv; struct iwl3945_priv *priv = hw->priv;
const struct iwl3945_channel_info *ch_info; const struct iwl3945_channel_info *ch_info;
unsigned long flags; unsigned long flags;
int ret = 0;
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel); IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
if (!iwl3945_is_ready(priv)) { if (!iwl3945_is_ready(priv)) {
IWL_DEBUG_MAC80211("leave - not ready\n"); IWL_DEBUG_MAC80211("leave - not ready\n");
mutex_unlock(&priv->mutex); ret = -EIO;
return -EIO; goto out;
} }
/* TODO: Figure out how to get ieee80211_local->sta_scanning w/ only /* TODO: Figure out how to get ieee80211_local->sta_scanning w/ only
* what is exposed through include/ declarations */ * what is exposed through include/ declarations */
if (unlikely(!iwl3945_param_disable_hw_scan && if (unlikely(!iwl3945_param_disable_hw_scan &&
test_bit(STATUS_SCANNING, &priv->status))) { test_bit(STATUS_SCANNING, &priv->status))) {
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"); IWL_DEBUG_MAC80211("leave - scanning\n");
} else {
IWL_DEBUG_MAC80211("leave - no memory\n");
ret = -ENOMEM;
}
}
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
return 0; return ret;
} }
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
...@@ -7131,8 +7151,8 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co ...@@ -7131,8 +7151,8 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
conf->channel, conf->phymode); conf->channel, conf->phymode);
IWL_DEBUG_MAC80211("leave - invalid channel\n"); IWL_DEBUG_MAC80211("leave - invalid channel\n");
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
mutex_unlock(&priv->mutex); ret = -EINVAL;
return -EINVAL; goto out;
} }
iwl3945_set_rxon_channel(priv, conf->phymode, conf->channel); 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 ...@@ -7149,8 +7169,7 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
#ifdef IEEE80211_CONF_CHANNEL_SWITCH #ifdef IEEE80211_CONF_CHANNEL_SWITCH
if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) { if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
iwl3945_hw_channel_switch(priv, conf->channel); iwl3945_hw_channel_switch(priv, conf->channel);
mutex_unlock(&priv->mutex); goto out;
return 0;
} }
#endif #endif
...@@ -7158,14 +7177,13 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co ...@@ -7158,14 +7177,13 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
if (!conf->radio_enabled) { if (!conf->radio_enabled) {
IWL_DEBUG_MAC80211("leave - radio disabled\n"); IWL_DEBUG_MAC80211("leave - radio disabled\n");
mutex_unlock(&priv->mutex); goto out;
return 0;
} }
if (iwl3945_is_rfkill(priv)) { if (iwl3945_is_rfkill(priv)) {
IWL_DEBUG_MAC80211("leave - RF kill\n"); IWL_DEBUG_MAC80211("leave - RF kill\n");
mutex_unlock(&priv->mutex); ret = -EIO;
return -EIO; goto out;
} }
iwl3945_set_rate(priv); iwl3945_set_rate(priv);
...@@ -7178,9 +7196,13 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co ...@@ -7178,9 +7196,13 @@ static int iwl3945_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
IWL_DEBUG_MAC80211("leave\n"); IWL_DEBUG_MAC80211("leave\n");
out:
if (priv->cache_conf) {
kfree(priv->cache_conf);
priv->cache_conf = NULL;
}
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
return ret;
return 0;
} }
static void iwl3945_config_ap(struct iwl3945_priv *priv) static void iwl3945_config_ap(struct iwl3945_priv *priv)
......
...@@ -7403,6 +7403,8 @@ static void iwl4965_bg_abort_scan(struct work_struct *work) ...@@ -7403,6 +7403,8 @@ static void iwl4965_bg_abort_scan(struct work_struct *work)
mutex_unlock(&priv->mutex); 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) static void iwl4965_bg_scan_completed(struct work_struct *work)
{ {
struct iwl4965_priv *priv = struct iwl4965_priv *priv =
...@@ -7413,6 +7415,9 @@ static void iwl4965_bg_scan_completed(struct work_struct *work) ...@@ -7413,6 +7415,9 @@ static void iwl4965_bg_scan_completed(struct work_struct *work)
if (test_bit(STATUS_EXIT_PENDING, &priv->status)) if (test_bit(STATUS_EXIT_PENDING, &priv->status))
return; return;
if (priv->cache_conf)
iwl4965_mac_config(priv->hw, priv->cache_conf);
ieee80211_scan_completed(priv->hw); ieee80211_scan_completed(priv->hw);
/* Since setting the TXPOWER may have been deferred while /* 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 ...@@ -7541,23 +7546,38 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
struct iwl4965_priv *priv = hw->priv; struct iwl4965_priv *priv = hw->priv;
const struct iwl4965_channel_info *ch_info; const struct iwl4965_channel_info *ch_info;
unsigned long flags; unsigned long flags;
int ret = 0;
mutex_lock(&priv->mutex); mutex_lock(&priv->mutex);
IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel); IWL_DEBUG_MAC80211("enter to channel %d\n", conf->channel);
if (!iwl4965_is_ready(priv)) { if (!iwl4965_is_ready(priv)) {
IWL_DEBUG_MAC80211("leave - not ready\n"); IWL_DEBUG_MAC80211("leave - not ready\n");
mutex_unlock(&priv->mutex); ret = -EIO;
return -EIO; goto out;
} }
/* TODO: Figure out how to get ieee80211_local->sta_scanning w/ only /* TODO: Figure out how to get ieee80211_local->sta_scanning w/ only
* what is exposed through include/ declarations */ * what is exposed through include/ declarations */
if (unlikely(!iwl4965_param_disable_hw_scan && if (unlikely(!iwl4965_param_disable_hw_scan &&
test_bit(STATUS_SCANNING, &priv->status))) { test_bit(STATUS_SCANNING, &priv->status))) {
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"); IWL_DEBUG_MAC80211("leave - scanning\n");
} else {
IWL_DEBUG_MAC80211("leave - no memory\n");
ret = -ENOMEM;
}
}
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
return 0; return ret;
} }
spin_lock_irqsave(&priv->lock, flags); spin_lock_irqsave(&priv->lock, flags);
...@@ -7568,8 +7588,8 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co ...@@ -7568,8 +7588,8 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
conf->channel, conf->phymode); conf->channel, conf->phymode);
IWL_DEBUG_MAC80211("leave - invalid channel\n"); IWL_DEBUG_MAC80211("leave - invalid channel\n");
spin_unlock_irqrestore(&priv->lock, flags); spin_unlock_irqrestore(&priv->lock, flags);
mutex_unlock(&priv->mutex); ret = -EINVAL;
return -EINVAL; goto out;
} }
#ifdef CONFIG_IWL4965_HT #ifdef CONFIG_IWL4965_HT
...@@ -7598,8 +7618,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co ...@@ -7598,8 +7618,7 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
#ifdef IEEE80211_CONF_CHANNEL_SWITCH #ifdef IEEE80211_CONF_CHANNEL_SWITCH
if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) { if (conf->flags & IEEE80211_CONF_CHANNEL_SWITCH) {
iwl4965_hw_channel_switch(priv, conf->channel); iwl4965_hw_channel_switch(priv, conf->channel);
mutex_unlock(&priv->mutex); goto out;
return 0;
} }
#endif #endif
...@@ -7607,14 +7626,13 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co ...@@ -7607,14 +7626,13 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
if (!conf->radio_enabled) { if (!conf->radio_enabled) {
IWL_DEBUG_MAC80211("leave - radio disabled\n"); IWL_DEBUG_MAC80211("leave - radio disabled\n");
mutex_unlock(&priv->mutex); goto out;
return 0;
} }
if (iwl4965_is_rfkill(priv)) { if (iwl4965_is_rfkill(priv)) {
IWL_DEBUG_MAC80211("leave - RF kill\n"); IWL_DEBUG_MAC80211("leave - RF kill\n");
mutex_unlock(&priv->mutex); ret = -EIO;
return -EIO; goto out;
} }
iwl4965_set_rate(priv); iwl4965_set_rate(priv);
...@@ -7627,9 +7645,13 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co ...@@ -7627,9 +7645,13 @@ static int iwl4965_mac_config(struct ieee80211_hw *hw, struct ieee80211_conf *co
IWL_DEBUG_MAC80211("leave\n"); IWL_DEBUG_MAC80211("leave\n");
out:
if (priv->cache_conf) {
kfree(priv->cache_conf);
priv->cache_conf = NULL;
}
mutex_unlock(&priv->mutex); mutex_unlock(&priv->mutex);
return ret;
return 0;
} }
static void iwl4965_config_ap(struct iwl4965_priv *priv) static void iwl4965_config_ap(struct iwl4965_priv *priv)
......
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