summaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/iwlwifi/iwl-core.c
diff options
context:
space:
mode:
authorStanislaw Gruszka2010-10-22 17:04:26 +0200
committerJohn W. Linville2010-11-15 19:24:24 +0100
commita25a66ac94db88190653d5725c563e3f8faeee61 (patch)
tree8ab28f02619472cb2c989629ded2045e5f9ccfc9 /drivers/net/wireless/iwlwifi/iwl-core.c
parentiwlwifi: send tx_power_cmd synchronously (diff)
downloadkernel-qcow2-linux-a25a66ac94db88190653d5725c563e3f8faeee61.tar.gz
kernel-qcow2-linux-a25a66ac94db88190653d5725c563e3f8faeee61.tar.xz
kernel-qcow2-linux-a25a66ac94db88190653d5725c563e3f8faeee61.zip
iwlwifi: fix set_tx_power vs scan
According to comment in iwl_bg_scan_completed, setting tx power should be deferred during pending scan, but we are not doing this. This patch change code to really defer setting tx power after scan complete. Additionally refactor iwl_set_tx_power code and call lib->send_tx_power() directly from iwlagn_commit_rxon. Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> Acked-by: Wey-Yi Guy <wey-yi.w.guy@intel.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/iwlwifi/iwl-core.c')
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c54
1 files changed, 30 insertions, 24 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index 25fb3912342c..8bbd152617fc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -1206,8 +1206,16 @@ EXPORT_SYMBOL(iwl_apm_init);
int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
{
- int ret = 0;
- s8 prev_tx_power = priv->tx_power_user_lmt;
+ int ret;
+ s8 prev_tx_power;
+
+ lockdep_assert_held(&priv->mutex);
+
+ if (priv->tx_power_user_lmt == tx_power && !force)
+ return 0;
+
+ if (!priv->cfg->ops->lib->send_tx_power)
+ return -EOPNOTSUPP;
if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) {
IWL_WARN(priv,
@@ -1224,30 +1232,26 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
return -EINVAL;
}
- if (priv->tx_power_user_lmt != tx_power)
- force = true;
+ if (!iwl_is_ready_rf(priv))
+ return -EIO;
- /* if nic is not up don't send command */
- if (iwl_is_ready_rf(priv)) {
- priv->tx_power_user_lmt = tx_power;
- if (force && priv->cfg->ops->lib->send_tx_power)
- ret = priv->cfg->ops->lib->send_tx_power(priv);
- else if (!priv->cfg->ops->lib->send_tx_power)
- ret = -EOPNOTSUPP;
- /*
- * if fail to set tx_power, restore the orig. tx power
- */
- if (ret)
- priv->tx_power_user_lmt = prev_tx_power;
+ /* scan complete use tx_power_next, need to be updated */
+ priv->tx_power_next = tx_power;
+ if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
+ IWL_DEBUG_INFO(priv, "Deferring tx power set while scanning\n");
+ return 0;
}
- /*
- * Even this is an async host command, the command
- * will always report success from uCode
- * So once driver can placing the command into the queue
- * successfully, driver can use priv->tx_power_user_lmt
- * to reflect the current tx power
- */
+ prev_tx_power = priv->tx_power_user_lmt;
+ priv->tx_power_user_lmt = tx_power;
+
+ ret = priv->cfg->ops->lib->send_tx_power(priv);
+
+ /* if fail to set tx_power, restore the orig. tx power */
+ if (ret) {
+ priv->tx_power_user_lmt = prev_tx_power;
+ priv->tx_power_next = prev_tx_power;
+ }
return ret;
}
EXPORT_SYMBOL(iwl_set_tx_power);
@@ -2016,7 +2020,9 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
priv->tx_power_user_lmt, conf->power_level);
- iwl_set_tx_power(priv, conf->power_level, false);
+ ret = iwl_set_tx_power(priv, conf->power_level, false);
+ if (ret)
+ IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
}
if (!iwl_is_ready(priv)) {