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

Dan Williams dcbw at redhat.com
Fri Sep 26 10:49:37 EDT 2008


On Thu, 2008-09-25 at 16:19 -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+.
> 
> Signed-off-by: Anna Neal <anna at cozybit.com>
> Signed-off-by: Javier Cardona <javier at cozybit.com>

Thanks!

Acked-by: Dan Williams <dcbw at redhat.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    |   32 ++++++++++++++-
>  6 files changed, 129 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
> index 7e818b0..a912fb6 100644
> --- a/drivers/net/wireless/libertas/cmd.c
> +++ b/drivers/net/wireless/libertas/cmd.c
> @@ -1927,6 +1927,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 = !!usesnr;
> +	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 9a35e15..d002160 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 c20fcf1..58d11a3 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 d1d0666..5004d76 100644
> --- a/drivers/net/wireless/libertas/host.h
> +++ b/drivers/net/wireless/libertas/host.h
> @@ -72,6 +72,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 b4ae2c2..d9f9a12 100644
> --- a/drivers/net/wireless/libertas/hostcmd.h
> +++ b/drivers/net/wireless/libertas/hostcmd.h
> @@ -605,14 +605,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 641e1c6..caf6108 100644
> --- a/drivers/net/wireless/libertas/wext.c
> +++ b/drivers/net/wireless/libertas/wext.c
> @@ -1856,7 +1856,22 @@ 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
> +		 * (enable power adaptation and disable TPC) 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,
> @@ -1866,7 +1881,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;
> @@ -1876,6 +1892,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