diff options
author | Stanislaw Gruszka <sgruszka@redhat.com> | 2010-10-22 11:04:26 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2010-11-15 13:24:24 -0500 |
commit | a25a66ac94db88190653d5725c563e3f8faeee61 (patch) | |
tree | 8ab28f02619472cb2c989629ded2045e5f9ccfc9 | |
parent | 4cbf1b12491cd43032846acc6c6924d9090fa19f (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.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-core.c | 54 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-dev.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl-scan.c | 10 | ||||
-rw-r--r-- | drivers/net/wireless/iwlwifi/iwl3945-base.c | 1 |
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 | ||
257 | void iwl_update_chain_flags(struct iwl_priv *priv) | 254 | void 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 | ||
1207 | int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force) | 1207 | int 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 | } |
1253 | EXPORT_SYMBOL(iwl_set_tx_power); | 1257 | EXPORT_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: | 614 | out: |
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", |