iwlwifi: error checking for setting tx_power in sysfs
authorWey-Yi Guy <wey-yi.w.guy@intel.com>
Fri, 21 Aug 2009 20:34:17 +0000 (13:34 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Fri, 28 Aug 2009 18:40:37 +0000 (14:40 -0400)
Perform error checking and report failure when setting tx power from
sysfs.
If fail to set the tx power, do not update the local copy, so user will
not see the incorrect tx power in sysfs

Signed-off-by: Wey-Yi Guy <wey-yi.w.guy@intel.com>
Signed-off-by: Reinette Chatre <reinette.chatre@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/iwlwifi/iwl-agn.c
drivers/net/wireless/iwlwifi/iwl-core.c

index 2232b1794e766fd0aa1b2281ec39401318567991..533b393e8cf64875aec74aa3c003f8b1d7cef3a4 100644 (file)
@@ -2477,10 +2477,15 @@ static ssize_t store_tx_power(struct device *d,
        ret = strict_strtoul(buf, 10, &val);
        if (ret)
                IWL_INFO(priv, "%s is not in decimal form.\n", buf);
-       else
-               iwl_set_tx_power(priv, val, false);
-
-       return count;
+       else {
+               ret = iwl_set_tx_power(priv, val, false);
+               if (ret)
+                       IWL_ERR(priv, "failed setting tx power (0x%d).\n",
+                               ret);
+               else
+                       ret = count;
+       }
+       return ret;
 }
 
 static DEVICE_ATTR(tx_power, S_IWUSR | S_IRUGO, show_tx_power, store_tx_power);
index 82dadd043b8f481aa4739dba400dc2fc7249b086..c62c081cfbb7cf7df3bb08a9fb0c22becefe9596 100644 (file)
@@ -1701,6 +1701,8 @@ EXPORT_SYMBOL(iwl_init_drv);
 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;
+
        if (tx_power < IWL_TX_POWER_TARGET_POWER_MIN) {
                IWL_WARN(priv, "Requested user TXPOWER %d below lower limit %d.\n",
                         tx_power,
@@ -1718,15 +1720,27 @@ int iwl_set_tx_power(struct iwl_priv *priv, s8 tx_power, bool force)
        if (priv->tx_power_user_lmt != tx_power)
                force = true;
 
-       priv->tx_power_user_lmt = tx_power;
-
        /* if nic is not up don't send command */
-       if (!iwl_is_ready_rf(priv))
-               return ret;
-
-       if (force && priv->cfg->ops->lib->send_tx_power)
-               ret = priv->cfg->ops->lib->send_tx_power(priv);
+       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;
+       }
 
+       /*
+        * 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
+        */
        return ret;
 }
 EXPORT_SYMBOL(iwl_set_tx_power);