libertas: Improvements on automatic tx power control via SIOCSIWTXPOW.
authorAnna Neal <anna@cozybit.com>
Thu, 11 Sep 2008 18:17:25 +0000 (11:17 -0700)
committerJohn W. Linville <linville@tuxdriver.com>
Thu, 11 Sep 2008 19:53:40 +0000 (15:53 -0400)
iwconfig txpower can now be used to set tx power to fixed or auto. If set to
auto the default firmware settings are used.

The command CMD_802_11_PA_CFG is only sent to older firmware, as Dan Williams
noted the command was no longer supported in firmware V9+.

Signed-off-by: Anna Neal <anna@cozybit.com>
Signed-off-by: Javier Cardona <javier@cozybit.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
drivers/net/wireless/libertas/cmd.c
drivers/net/wireless/libertas/cmd.h
drivers/net/wireless/libertas/defs.h
drivers/net/wireless/libertas/host.h
drivers/net/wireless/libertas/hostcmd.h
drivers/net/wireless/libertas/wext.c

index 802547e7967190e8f2c3bdb2735a1c0e9fedeb1c..5fef05f3cd008774699199f0ac77578277ae43ab 100644 (file)
@@ -1971,6 +1971,70 @@ void lbs_ps_confirm_sleep(struct lbs_private *priv)
 }
 
 
+/**
+ * @brief Configures the transmission power control functionality.
+ *
+ * @param priv         A pointer to struct lbs_private structure
+ * @param enable       Transmission power control enable
+ * @param p0           Power level when link quality is good (dBm).
+ * @param p1           Power level when link quality is fair (dBm).
+ * @param p2           Power level when link quality is poor (dBm).
+ * @param usesnr       Use Signal to Noise Ratio in TPC
+ *
+ * @return 0 on success
+ */
+int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
+               int8_t p2, int usesnr)
+{
+       struct cmd_ds_802_11_tpc_cfg cmd;
+       int ret;
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+       cmd.action = cpu_to_le16(CMD_ACT_SET);
+       cmd.enable = !!enable;
+       cmd.usesnr = !!enable;
+       cmd.P0 = p0;
+       cmd.P1 = p1;
+       cmd.P2 = p2;
+
+       ret = lbs_cmd_with_response(priv, CMD_802_11_TPC_CFG, &cmd);
+
+       return ret;
+}
+
+/**
+ * @brief Configures the power adaptation settings.
+ *
+ * @param priv         A pointer to struct lbs_private structure
+ * @param enable       Power adaptation enable
+ * @param p0           Power level for 1, 2, 5.5 and 11 Mbps (dBm).
+ * @param p1           Power level for 6, 9, 12, 18, 22, 24 and 36 Mbps (dBm).
+ * @param p2           Power level for 48 and 54 Mbps (dBm).
+ *
+ * @return 0 on Success
+ */
+
+int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
+               int8_t p1, int8_t p2)
+{
+       struct cmd_ds_802_11_pa_cfg cmd;
+       int ret;
+
+       memset(&cmd, 0, sizeof(cmd));
+       cmd.hdr.size = cpu_to_le16(sizeof(cmd));
+       cmd.action = cpu_to_le16(CMD_ACT_SET);
+       cmd.enable = !!enable;
+       cmd.P0 = p0;
+       cmd.P1 = p1;
+       cmd.P2 = p2;
+
+       ret = lbs_cmd_with_response(priv, CMD_802_11_PA_CFG , &cmd);
+
+       return ret;
+}
+
+
 static struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
        uint16_t command, struct cmd_header *in_cmd, int in_cmd_size,
        int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
index 11ac996e895ed2d136370b42837d20869c9b38ec..336a181d857a0a15d31a2e44c31f74de2b3da089 100644 (file)
@@ -26,6 +26,12 @@ int __lbs_cmd(struct lbs_private *priv, uint16_t command,
              int (*callback)(struct lbs_private *, unsigned long, struct cmd_header *),
              unsigned long callback_arg);
 
+int lbs_set_power_adapt_cfg(struct lbs_private *priv, int enable, int8_t p0,
+               int8_t p1, int8_t p2);
+
+int lbs_set_tpc_cfg(struct lbs_private *priv, int enable, int8_t p0, int8_t p1,
+               int8_t p2, int usesnr);
+
 int lbs_cmd_copyback(struct lbs_private *priv, unsigned long extra,
                     struct cmd_header *resp);
 
index 4b2428ac2223805843c498c186b10004633dc220..c89d7a1041a83ffa9e2b6e3a7e5b0d62e0efc2ca 100644 (file)
@@ -189,6 +189,15 @@ static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, in
 #define MRVDRV_CMD_UPLD_RDY            0x0008
 #define MRVDRV_CARDEVENT               0x0010
 
+
+/* Automatic TX control default levels */
+#define POW_ADAPT_DEFAULT_P0 13
+#define POW_ADAPT_DEFAULT_P1 15
+#define POW_ADAPT_DEFAULT_P2 18
+#define TPC_DEFAULT_P0 5
+#define TPC_DEFAULT_P1 10
+#define TPC_DEFAULT_P2 13
+
 /** TxPD status */
 
 /*     Station firmware use TxPD status field to report final Tx transmit
index da618fc997cec132eb4613590ed1ea8bacf53fbb..a916bb9bd5dacdb410e98699dd20a04d4333b5e5 100644 (file)
@@ -83,6 +83,7 @@
 #define CMD_802_11_INACTIVITY_TIMEOUT          0x0067
 #define CMD_802_11_SLEEP_PERIOD                        0x0068
 #define CMD_802_11_TPC_CFG                     0x0072
+#define CMD_802_11_PA_CFG                      0x0073
 #define CMD_802_11_FW_WAKE_METHOD              0x0074
 #define CMD_802_11_SUBSCRIBE_EVENT             0x0075
 #define CMD_802_11_RATE_ADAPT_RATESET          0x0076
index d27c276b219182b86b06fa4e7db536ab0d03f639..630b79967560902193feeba03557ba102440cc49 100644 (file)
@@ -607,14 +607,28 @@ struct cmd_ds_802_11_eeprom_access {
 } __attribute__ ((packed));
 
 struct cmd_ds_802_11_tpc_cfg {
+       struct cmd_header hdr;
+
        __le16 action;
-       u8 enable;
-       s8 P0;
-       s8 P1;
-       s8 P2;
-       u8 usesnr;
+       uint8_t enable;
+       int8_t P0;
+       int8_t P1;
+       int8_t P2;
+       uint8_t usesnr;
 } __attribute__ ((packed));
 
+
+struct cmd_ds_802_11_pa_cfg {
+       struct cmd_header hdr;
+
+       __le16 action;
+       uint8_t enable;
+       int8_t P0;
+       int8_t P1;
+       int8_t P2;
+} __attribute__ ((packed));
+
+
 struct cmd_ds_802_11_led_ctrl {
        __le16 action;
        __le16 numled;
index 426f1fe3bb4298aadc6d2ec3d52060ba91d2ff94..e8cadad2c863acd8e11334287a93dd395121c527 100644 (file)
@@ -1820,7 +1820,21 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
        }
 
        if (vwrq->fixed == 0) {
-               /* Auto power control */
+               /* User requests automatic tx power control, however there are
+                * many auto tx settings.  For now use firmware defaults until
+                * we come up with a good way to expose these to the user. */
+               if (priv->fwrelease < 0x09000000) {
+                       ret = lbs_set_power_adapt_cfg(priv, 1,
+                                       POW_ADAPT_DEFAULT_P0,
+                                       POW_ADAPT_DEFAULT_P1,
+                                       POW_ADAPT_DEFAULT_P2);
+                       if (ret)
+                               goto out;
+               }
+               ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
+                               TPC_DEFAULT_P2, 1);
+               if (ret)
+                       goto out;
                dbm = priv->txpower_max;
        } else {
                /* Userspace check in iwrange if it should use dBm or mW,
@@ -1830,7 +1844,8 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
                        goto out;
                }
 
-               /* Validate requested power level against firmware allowed levels */
+               /* Validate requested power level against firmware allowed
+                * levels */
                if (priv->txpower_min && (dbm < priv->txpower_min)) {
                        ret = -EINVAL;
                        goto out;
@@ -1840,6 +1855,18 @@ static int lbs_set_txpow(struct net_device *dev, struct iw_request_info *info,
                        ret = -EINVAL;
                        goto out;
                }
+               if (priv->fwrelease < 0x09000000) {
+                       ret = lbs_set_power_adapt_cfg(priv, 0,
+                                       POW_ADAPT_DEFAULT_P0,
+                                       POW_ADAPT_DEFAULT_P1,
+                                       POW_ADAPT_DEFAULT_P2);
+                       if (ret)
+                               goto out;
+               }
+               ret = lbs_set_tpc_cfg(priv, 0, TPC_DEFAULT_P0, TPC_DEFAULT_P1,
+                               TPC_DEFAULT_P2, 1);
+               if (ret)
+                       goto out;
        }
 
        /* If the radio was off, turn it on */