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);
 
 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,
        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);