aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStanislaw Gruszka <sgruszka@redhat.com>2010-10-22 11:04:26 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-11-15 13:24:24 -0500
commita25a66ac94db88190653d5725c563e3f8faeee61 (patch)
tree8ab28f02619472cb2c989629ded2045e5f9ccfc9
parent4cbf1b12491cd43032846acc6c6924d9090fa19f (diff)
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>
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c54
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c10
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c1
5 files changed, 42 insertions, 34 deletions
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index c2636a7ab9ee..d3435c430273 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -245,13 +245,10 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
245 245
246 /* If we issue a new RXON command which required a tune then we must 246 /* If we issue a new RXON command which required a tune then we must
247 * send a new TXPOWER command or we won't be able to Tx any frames */ 247 * send a new TXPOWER command or we won't be able to Tx any frames */
248 ret = iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); 248 ret = priv->cfg->ops->lib->send_tx_power(priv);
249 if (ret) { 249 if (ret)
250 IWL_ERR(priv, "Error sending TX power (%d)\n", ret); 250 IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
251 return ret; 251 return ret;
252 }
253
254 return 0;
255} 252}
256 253
257void iwl_update_chain_flags(struct iwl_priv *priv) 254void iwl_update_chain_flags(struct iwl_priv *priv)
@@ -4179,6 +4176,7 @@ static int iwl_init_drv(struct iwl_priv *priv)
4179 * this value will get overwritten by channel max power avg 4176 * this value will get overwritten by channel max power avg
4180 * from eeprom */ 4177 * from eeprom */
4181 priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN; 4178 priv->tx_power_user_lmt = IWLAGN_TX_POWER_TARGET_POWER_MIN;
4179 priv->tx_power_next = IWLAGN_TX_POWER_TARGET_POWER_MIN;
4182 4180
4183 ret = iwl_init_channel_map(priv); 4181 ret = iwl_init_channel_map(priv);
4184 if (ret) { 4182 if (ret) {
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);
1206 1206
1207int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) 1207int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
1208{ 1208{
1209 int ret = 0; 1209 int ret;
1210 s8 prev_tx_power = priv->tx_power_user_lmt; 1210 s8 prev_tx_power;
1211
1212 lockdep_assert_held(&priv->mutex);
1213
1214 if (priv->tx_power_user_lmt == tx_power && !force)
1215 return 0;
1216
1217 if (!priv->cfg->ops->lib->send_tx_power)
1218 return -EOPNOTSUPP;
1211 1219
1212 if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) { 1220 if (tx_power < IWLAGN_TX_POWER_TARGET_POWER_MIN) {
1213 IWL_WARN(priv, 1221 IWL_WARN(priv,
@@ -1224,30 +1232,26 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
1224 return -EINVAL; 1232 return -EINVAL;
1225 } 1233 }
1226 1234
1227 if (priv->tx_power_user_lmt != tx_power) 1235 if (!iwl_is_ready_rf(priv))
1228 force = true; 1236 return -EIO;
1229 1237
1230 /* if nic is not up don't send command */ 1238 /* scan complete use tx_power_next, need to be updated */
1231 if (iwl_is_ready_rf(priv)) { 1239 priv->tx_power_next = tx_power;
1232 priv->tx_power_user_lmt = tx_power; 1240 if (test_bit(STATUS_SCANNING, &priv->status) && !force) {
1233 if (force && priv->cfg->ops->lib->send_tx_power) 1241 IWL_DEBUG_INFO(priv, "Deferring tx power set while scanning\n");
1234 ret = priv->cfg->ops->lib->send_tx_power(priv); 1242 return 0;
1235 else if (!priv->cfg->ops->lib->send_tx_power)
1236 ret = -EOPNOTSUPP;
1237 /*
1238 * if fail to set tx_power, restore the orig. tx power
1239 */
1240 if (ret)
1241 priv->tx_power_user_lmt = prev_tx_power;
1242 } 1243 }
1243 1244
1244 /* 1245 prev_tx_power = priv->tx_power_user_lmt;
1245 * Even this is an async host command, the command 1246 priv->tx_power_user_lmt = tx_power;
1246 * will always report success from uCode 1247
1247 * So once driver can placing the command into the queue 1248 ret = priv->cfg->ops->lib->send_tx_power(priv);
1248 * successfully, driver can use priv->tx_power_user_lmt 1249
1249 * to reflect the current tx power 1250 /* if fail to set tx_power, restore the orig. tx power */
1250 */ 1251 if (ret) {
1252 priv->tx_power_user_lmt = prev_tx_power;
1253 priv->tx_power_next = prev_tx_power;
1254 }
1251 return ret; 1255 return ret;
1252} 1256}
1253EXPORT_SYMBOL(iwl_set_tx_power); 1257EXPORT_SYMBOL(iwl_set_tx_power);
@@ -2016,7 +2020,9 @@ int iwl_mac_config(struct ieee80211_hw *hw, u32 changed)
2016 IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n", 2020 IWL_DEBUG_MAC80211(priv, "TX Power old=%d new=%d\n",
2017 priv->tx_power_user_lmt, conf->power_level); 2021 priv->tx_power_user_lmt, conf->power_level);
2018 2022
2019 iwl_set_tx_power(priv, conf->power_level, false); 2023 ret = iwl_set_tx_power(priv, conf->power_level, false);
2024 if (ret)
2025 IWL_ERR(priv, "Error sending TX power (%d)\n", ret);
2020 } 2026 }
2021 2027
2022 if (!iwl_is_ready(priv)) { 2028 if (!iwl_is_ready(priv)) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 70e07fa48405..cd6daed99931 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1517,6 +1517,7 @@ struct iwl_priv {
1517 s8 tx_power_user_lmt; 1517 s8 tx_power_user_lmt;
1518 s8 tx_power_device_lmt; 1518 s8 tx_power_device_lmt;
1519 s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */ 1519 s8 tx_power_lmt_in_half_dbm; /* max tx power in half-dBm format */
1520 s8 tx_power_next;
1520 1521
1521 1522
1522#ifdef CONFIG_IWLWIFI_DEBUG 1523#ifdef CONFIG_IWLWIFI_DEBUG
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index 67da31295781..d63e30e1106a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -603,13 +603,15 @@ out_settings:
603 if (!iwl_is_ready_rf(priv)) 603 if (!iwl_is_ready_rf(priv))
604 goto out; 604 goto out;
605 605
606 /* Since setting the TXPOWER may have been deferred while 606 /*
607 * performing the scan, fire one off */ 607 * We do not commit power settings while scan is pending,
608 iwl_set_tx_power(priv, priv->tx_power_user_lmt, true); 608 * do it now if the settings changed.
609 */
610 iwl_set_tx_power(priv, priv->tx_power_next, false);
609 611
610 priv->cfg->ops->utils->post_scan(priv); 612 priv->cfg->ops->utils->post_scan(priv);
611 613
612 out: 614out:
613 mutex_unlock(&priv->mutex); 615 mutex_unlock(&priv->mutex);
614} 616}
615 617
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 8f8c4b73f8b9..a75429171c46 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -3866,6 +3866,7 @@ static int iwl3945_init_drv(struct iwl_priv *priv)
3866 priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF; 3866 priv->missed_beacon_threshold = IWL_MISSED_BEACON_THRESHOLD_DEF;
3867 3867
3868 priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER; 3868 priv->tx_power_user_lmt = IWL_DEFAULT_TX_POWER;
3869 priv->tx_power_next = IWL_DEFAULT_TX_POWER;
3869 3870
3870 if (eeprom->version < EEPROM_3945_EEPROM_VERSION) { 3871 if (eeprom->version < EEPROM_3945_EEPROM_VERSION) {
3871 IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n", 3872 IWL_WARN(priv, "Unsupported EEPROM version: 0x%04X\n",