]> git.karo-electronics.de Git - mv-sheeva.git/blobdiff - drivers/net/wireless/iwlwifi/iwl-core.c
iwlwifi: avoid commit rxon during scan in iwl_set_no_assoc
[mv-sheeva.git] / drivers / net / wireless / iwlwifi / iwl-core.c
index 25fb3912342ceff334f6c2d82cb61defc5b0ee75..87c18001d2c0dfa0a08d41935c21d937e46a4cf0 100644 (file)
@@ -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);
@@ -1586,6 +1590,19 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
 
        mutex_lock(&priv->mutex);
 
+       if (changes & (BSS_CHANGED_BSSID | BSS_CHANGED_ASSOC |
+                      BSS_CHANGED_BEACON_ENABLED)) {
+               /*
+                * If there is currently a HW scan going on in the
+                * background then we need to cancel it else the RXON
+                * below in post_associate or set_no_assoc can fail.
+                */
+               if (iwl_scan_cancel_timeout(priv, 200)) {
+                       IWL_WARN(priv, "Can not cancel scan\n");
+                       goto out;
+               }
+       }
+
        if (changes & BSS_CHANGED_QOS) {
                unsigned long flags;
 
@@ -1618,18 +1635,6 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
        if (changes & BSS_CHANGED_BSSID) {
                IWL_DEBUG_MAC80211(priv, "BSSID %pM\n", bss_conf->bssid);
 
-               /*
-                * If there is currently a HW scan going on in the
-                * background then we need to cancel it else the RXON
-                * below/in post_associate will fail.
-                */
-               if (iwl_scan_cancel_timeout(priv, 100)) {
-                       IWL_WARN(priv, "Aborted scan still in progress after 100ms\n");
-                       IWL_DEBUG_MAC80211(priv, "leaving - scan abort failed.\n");
-                       mutex_unlock(&priv->mutex);
-                       return;
-               }
-
                /* mac80211 only sets assoc when in STATION mode */
                if (vif->type == NL80211_IFTYPE_ADHOC || bss_conf->assoc) {
                        memcpy(ctx->staging.bssid_addr,
@@ -1748,6 +1753,7 @@ void iwl_bss_info_changed(struct ieee80211_hw *hw,
                        IWL_ERR(priv, "failed to update PAN params\n");
        }
 
+out:
        mutex_unlock(&priv->mutex);
 
        IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -2016,7 +2022,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)) {