[rt2x00-users] [PATCH 3/5] rt2x00: Fix max TX power settings

Helmut Schaa helmut.schaa at googlemail.com
Mon Aug 23 14:25:54 UTC 2010


Am Monday 23 August 2010 schrieb Ivo van Doorn:
> During initialization each driver reads the default TX power
> for each individual channel. However mac80211 only accepts the
> maximum value (which is also handled as default value).
> 
> As a result, the TX power of the device was being limited to
> the default value, which is often quite low compared to the
> real maximum acceptable value.
> 
> This patch allows each driver to set the maximum value on a
> per-channel basis which is forwarded to mac80211. The default
> value will be preserved for now, in case we want to update
> mac80211 to differentiate between the maximum and default txpower.
> 
> Signed-off-by: Ivo van Doorn <IvDoorn at gmail.com>

Acked-by: Helmut Schaa <helmut.schaa at googlemail.com>

> ---
>  drivers/net/wireless/rt2x00/rt2400pci.c |    6 ++-
>  drivers/net/wireless/rt2x00/rt2500pci.c |   12 ++++--
>  drivers/net/wireless/rt2x00/rt2500usb.c |   12 ++++--
>  drivers/net/wireless/rt2x00/rt2800.h    |    7 +++
>  drivers/net/wireless/rt2x00/rt2800lib.c |   65 ++++++++++++++++++------------
>  drivers/net/wireless/rt2x00/rt2x00.h    |    5 +-
>  drivers/net/wireless/rt2x00/rt2x00dev.c |    2 +-
>  drivers/net/wireless/rt2x00/rt61pci.c   |   12 ++++--
>  drivers/net/wireless/rt2x00/rt73usb.c   |   12 ++++--
>  9 files changed, 86 insertions(+), 47 deletions(-)
> 
> diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
> index b86b613..e3005ff 100644
> --- a/drivers/net/wireless/rt2x00/rt2400pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2400pci.c
> @@ -1487,8 +1487,10 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
>  	spec->channels_info = info;
>  
>  	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
> -	for (i = 0; i < 14; i++)
> -		info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> +	for (i = 0; i < 14; i++) {
> +		info[i].max_power = TXPOWER_FROM_DEV(MAX_TXPOWER);
> +		info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> +	}
>  
>  	return 0;
>  }
> diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
> index 21f4581..1e6a91b 100644
> --- a/drivers/net/wireless/rt2x00/rt2500pci.c
> +++ b/drivers/net/wireless/rt2x00/rt2500pci.c
> @@ -1801,12 +1801,16 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
>  	spec->channels_info = info;
>  
>  	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
> -	for (i = 0; i < 14; i++)
> -		info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> +	for (i = 0; i < 14; i++) {
> +		info[i].max_power = MAX_TXPOWER;
> +		info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> +	}
>  
>  	if (spec->num_channels > 14) {
> -		for (i = 14; i < spec->num_channels; i++)
> -			info[i].tx_power1 = DEFAULT_TXPOWER;
> +		for (i = 14; i < spec->num_channels; i++) {
> +			info[i].max_power = MAX_TXPOWER;
> +			info[i].default_power1 = DEFAULT_TXPOWER;
> +		}
>  	}
>  
>  	return 0;
> diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
> index b70565f..e2a5088 100644
> --- a/drivers/net/wireless/rt2x00/rt2500usb.c
> +++ b/drivers/net/wireless/rt2x00/rt2500usb.c
> @@ -1704,12 +1704,16 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
>  	spec->channels_info = info;
>  
>  	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
> -	for (i = 0; i < 14; i++)
> -		info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> +	for (i = 0; i < 14; i++) {
> +		info[i].max_power = MAX_TXPOWER;
> +		info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> +	}
>  
>  	if (spec->num_channels > 14) {
> -		for (i = 14; i < spec->num_channels; i++)
> -			info[i].tx_power1 = DEFAULT_TXPOWER;
> +		for (i = 14; i < spec->num_channels; i++) {
> +			info[i].max_power = MAX_TXPOWER;
> +			info[i].default_power1 = DEFAULT_TXPOWER;
> +		}
>  	}
>  
>  	return 0;
> diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
> index cf1f16b..5c006a7 100644
> --- a/drivers/net/wireless/rt2x00/rt2800.h
> +++ b/drivers/net/wireless/rt2x00/rt2800.h
> @@ -1859,6 +1859,13 @@ struct mac_iveiv_entry {
>  #define EEPROM_RSSI_A2_LNA_A2		FIELD16(0xff00)
>  
>  /*
> + * EEPROM Maximum TX power values
> + */
> +#define EEPROM_MAX_TX_POWER		0x0027
> +#define EEPROM_MAX_TX_POWER_24GHZ	FIELD16(0x00ff)
> +#define EEPROM_MAX_TX_POWER_5GHZ	FIELD16(0xff00)
> +
> +/*
>   * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power.
>   *	This is delta in 40MHZ.
>   * VALUE: Tx Power dalta value (MAX=4)
> diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
> index cbab2e1..ecbd07a 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.c
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
> @@ -1239,23 +1239,23 @@ static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,
>  		 * double meaning, and we should set a 7DBm boost flag.
>  		 */
>  		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST,
> -				   (info->tx_power1 >= 0));
> +				   (info->default_power1 >= 0));
>  
> -		if (info->tx_power1 < 0)
> -			info->tx_power1 += 7;
> +		if (info->default_power1 < 0)
> +			info->default_power1 += 7;
>  
> -		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, info->tx_power1);
> +		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, info->default_power1);
>  
>  		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST,
> -				   (info->tx_power2 >= 0));
> +				   (info->default_power2 >= 0));
>  
> -		if (info->tx_power2 < 0)
> -			info->tx_power2 += 7;
> +		if (info->default_power2 < 0)
> +			info->default_power2 += 7;
>  
> -		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, info->tx_power2);
> +		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, info->default_power2);
>  	} else {
> -		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, info->tx_power1);
> -		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, info->tx_power2);
> +		rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, info->default_power1);
> +		rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, info->default_power2);
>  	}
>  
>  	rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf));
> @@ -1295,11 +1295,11 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
>  	rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
>  
>  	rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
> -	rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, info->tx_power1);
> +	rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, info->default_power1);
>  	rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
>  
>  	rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
> -	rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->tx_power2);
> +	rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2);
>  	rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
>  
>  	rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
> @@ -1324,11 +1324,11 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
>  	u8 bbp;
>  
>  	if (rf->channel <= 14) {
> -		info->tx_power1 = TXPOWER_G_TO_DEV(info->tx_power1);
> -		info->tx_power2 = TXPOWER_G_TO_DEV(info->tx_power2);
> +		info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1);
> +		info->default_power2 = TXPOWER_G_TO_DEV(info->default_power2);
>  	} else {
> -		info->tx_power1 = TXPOWER_A_TO_DEV(info->tx_power1);
> -		info->tx_power2 = TXPOWER_A_TO_DEV(info->tx_power2);
> +		info->default_power1 = TXPOWER_A_TO_DEV(info->default_power1);
> +		info->default_power2 = TXPOWER_A_TO_DEV(info->default_power2);
>  	}
>  
>  	if (rt2x00_rf(rt2x00dev, RF2020) ||
> @@ -2729,6 +2729,13 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
>  				   default_lna_gain);
>  	rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
>  
> +	rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &word);
> +	if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_24GHZ) == 0xff)
> +		rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_24GHZ, MAX_G_TXPOWER);
> +	if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_5GHZ) == 0xff)
> +		rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_5GHZ, MAX_A_TXPOWER);
> +	rt2x00_eeprom_write(rt2x00dev, EEPROM_MAX_TX_POWER, word);
> +
>  	return 0;
>  }
>  EXPORT_SYMBOL_GPL(rt2800_validate_eeprom);
> @@ -2968,9 +2975,10 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
>  {
>  	struct hw_mode_spec *spec = &rt2x00dev->spec;
>  	struct channel_info *info;
> -	char *tx_power1;
> -	char *tx_power2;
> +	char *default_power1;
> +	char *default_power2;
>  	unsigned int i;
> +	unsigned short max_power;
>  	u16 eeprom;
>  
>  	/*
> @@ -3084,21 +3092,26 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
>  
>  	spec->channels_info = info;
>  
> -	tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
> -	tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
> +	rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &eeprom);
> +	max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_24GHZ);
> +	default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
> +	default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
>  
>  	for (i = 0; i < 14; i++) {
> -		info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]);
> -		info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]);
> +		info[i].max_power = max_power;
> +		info[i].default_power1 = TXPOWER_G_FROM_DEV(default_power1[i]);
> +		info[i].default_power2 = TXPOWER_G_FROM_DEV(default_power2[i]);
>  	}
>  
>  	if (spec->num_channels > 14) {
> -		tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
> -		tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
> +		max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_5GHZ);
> +		default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
> +		default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
>  
>  		for (i = 14; i < spec->num_channels; i++) {
> -			info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]);
> -			info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]);
> +			info[i].max_power = max_power;
> +			info[i].default_power1 = TXPOWER_A_FROM_DEV(default_power1[i]);
> +			info[i].default_power2 = TXPOWER_A_FROM_DEV(default_power2[i]);
>  		}
>  	}
>  
> diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
> index 69308a0..762f6b4 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00.h
> +++ b/drivers/net/wireless/rt2x00/rt2x00.h
> @@ -213,8 +213,9 @@ struct channel_info {
>  	unsigned int flags;
>  #define GEOGRAPHY_ALLOWED	0x00000001
>  
> -	short tx_power1;
> -	short tx_power2;
> +	short max_power;
> +	short default_power1;
> +	short default_power2;
>  };
>  
>  /*
> diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
> index e692608..580595b 100644
> --- a/drivers/net/wireless/rt2x00/rt2x00dev.c
> +++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
> @@ -711,7 +711,7 @@ static int rt2x00lib_probe_hw_modes(struct rt2x00_dev *rt2x00dev,
>  	for (i = 0; i < spec->num_channels; i++) {
>  		rt2x00lib_channel(&channels[i],
>  				  spec->channels[i].channel,
> -				  spec->channels_info[i].tx_power1, i);
> +				  spec->channels_info[i].max_power, i);
>  	}
>  
>  	/*
> diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
> index ae4698e..8f017ad 100644
> --- a/drivers/net/wireless/rt2x00/rt61pci.c
> +++ b/drivers/net/wireless/rt2x00/rt61pci.c
> @@ -2656,13 +2656,17 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
>  	spec->channels_info = info;
>  
>  	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
> -	for (i = 0; i < 14; i++)
> -		info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> +	for (i = 0; i < 14; i++) {
> +		info[i].max_power = MAX_TXPOWER;
> +		info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> +	}
>  
>  	if (spec->num_channels > 14) {
>  		tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
> -		for (i = 14; i < spec->num_channels; i++)
> -			info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> +		for (i = 14; i < spec->num_channels; i++) {
> +			info[i].max_power = MAX_TXPOWER;
> +			info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> +		}
>  	}
>  
>  	return 0;
> diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
> index ab93894..ee2c52f 100644
> --- a/drivers/net/wireless/rt2x00/rt73usb.c
> +++ b/drivers/net/wireless/rt2x00/rt73usb.c
> @@ -2090,13 +2090,17 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
>  	spec->channels_info = info;
>  
>  	tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
> -	for (i = 0; i < 14; i++)
> -		info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> +	for (i = 0; i < 14; i++) {
> +		info[i].max_power = MAX_TXPOWER;
> +		info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> +	}
>  
>  	if (spec->num_channels > 14) {
>  		tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
> -		for (i = 14; i < spec->num_channels; i++)
> -			info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> +		for (i = 14; i < spec->num_channels; i++) {
> +			info[i].max_power = MAX_TXPOWER;
> +			info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
> +		}
>  	}
>  
>  	return 0;
> 




More information about the users mailing list