[PATCH] libertas: Improvements on automatic tx power control via SIOCSIWTXPOW.

Anna Neal anna at cozybit.com
Wed Sep 17 14:23:57 EDT 2008


On Sun, Sep 14, 2008 at 10:44 PM, Dan Williams <dcbw at redhat.com> wrote:
> On Thu, 2008-09-11 at 11:17 -0700, Anna Neal wrote:
>> 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+.
>
> Updated patch looks ok, but two last questions... (see below)
>
>> Signed-off-by: Anna Neal <anna at cozybit.com>
>> Signed-off-by: Javier Cardona <javier at cozybit.com>
>> ---
>>  drivers/net/wireless/libertas/cmd.c     |   64 +++++++++++++++++++++++++++++++
>>  drivers/net/wireless/libertas/cmd.h     |    6 +++
>>  drivers/net/wireless/libertas/defs.h    |    9 ++++
>>  drivers/net/wireless/libertas/host.h    |    1 +
>>  drivers/net/wireless/libertas/hostcmd.h |   24 +++++++++--
>>  drivers/net/wireless/libertas/wext.c    |   31 ++++++++++++++-
>>  6 files changed, 128 insertions(+), 7 deletions(-)
>>
>> diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
>> index 802547e..5fef05f 100644
>> --- a/drivers/net/wireless/libertas/cmd.c
>> +++ b/drivers/net/wireless/libertas/cmd.c
>> @@ -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;
>
> Hmm, do you mean !!usesnr here instead of !!enable?  Otherwise the
> usesnr parameter goes unused and you can remove it from the parameter
> list.  But I think you probably meant to use it :)

Sorry, yes I did, thanks for finding this.  I will send an update soon.

>
>> +     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 *),
>> diff --git a/drivers/net/wireless/libertas/cmd.h b/drivers/net/wireless/libertas/cmd.h
>> index 11ac996..336a181 100644
>> --- a/drivers/net/wireless/libertas/cmd.h
>> +++ b/drivers/net/wireless/libertas/cmd.h
>> @@ -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);
>>
>> diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
>> index 4b2428a..c89d7a1 100644
>> --- a/drivers/net/wireless/libertas/defs.h
>> +++ b/drivers/net/wireless/libertas/defs.h
>> @@ -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
>> diff --git a/drivers/net/wireless/libertas/host.h b/drivers/net/wireless/libertas/host.h
>> index da618fc..a916bb9 100644
>> --- a/drivers/net/wireless/libertas/host.h
>> +++ b/drivers/net/wireless/libertas/host.h
>> @@ -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
>> diff --git a/drivers/net/wireless/libertas/hostcmd.h b/drivers/net/wireless/libertas/hostcmd.h
>> index d27c276..630b799 100644
>> --- a/drivers/net/wireless/libertas/hostcmd.h
>> +++ b/drivers/net/wireless/libertas/hostcmd.h
>> @@ -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;
>> diff --git a/drivers/net/wireless/libertas/wext.c b/drivers/net/wireless/libertas/wext.c
>> index 426f1fe..e8cadad 100644
>> --- a/drivers/net/wireless/libertas/wext.c
>> +++ b/drivers/net/wireless/libertas/wext.c
>> @@ -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,
>
> Did you mean to disable TPC here when the user specified "auto" power
> control?  This would mean that PA gets used at every rate and TPC is
> disabled, while enabling TPC here would mean TPC gets used at the
> highest rate, and PA gets used at all other rates.  What was your intent
> here?  If you really mean to use '0' here to disable TPC, you might want
> to put the rationale in a comment.

My rationale for this was to keep the default functionality until we
could devise a way to control the PA and TPC functionality more
elegantly.  I will add this to a comment like you suggest.

Thanks,
Anna

>
> Thanks!
> Dan
>
>> +                             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 */
>
>



More information about the libertas-dev mailing list