[rt2x00-users] rt2x00: Fix max TX power settings
Gertjan van Wingerde
gwingerde at gmail.com
Sun Aug 22 18:31:50 UTC 2010
On Sun, Aug 22, 2010 at 4:39 PM, Ivo van Doorn <ivdoorn at gmail.com> wrote:
> 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>
> ---
> 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/rt2800lib.c | 77 ++++++++++++++----------------
> 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 +++--
> 8 files changed, 76 insertions(+), 62 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;
> }
There seems to be a typo in the above hunk of code, I don't think the
TXPOWER_FROM_DEV should be there for the max_power field.
> 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/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
> index b2f9b04..4e34b0b 100644
> --- a/drivers/net/wireless/rt2x00/rt2800lib.c
> +++ b/drivers/net/wireless/rt2x00/rt2800lib.c
> @@ -1218,8 +1218,19 @@ static void rt2800_config_lna_gain(struct rt2x00_dev *rt2x00dev,
> static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,
> struct ieee80211_conf *conf,
> struct rf_channel *rf,
> - struct channel_info *info)
> + int txpower)
> {
> + bool boost = (txpower >= 0);
> +
> + /*
> + * When TX power is below 0, we should increase it by 7 to
> + * make it a positive value (Minumum value is -7).
> + * However this means that values between 0 and 7 have
> + * double meaning, and we should set a 7DBm boost flag.
> + */
> + if (txpower < 0)
> + txpower += 7;
> +
> rt2x00_set_field32(&rf->rf4, RF4_FREQ_OFFSET, rt2x00dev->freq_offset);
>
> if (rt2x00dev->default_ant.tx == 1)
> @@ -1232,34 +1243,13 @@ static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,
> rt2x00_set_field32(&rf->rf2, RF2_ANTENNA_RX2, 1);
>
> if (rf->channel > 14) {
> - /*
> - * When TX power is below 0, we should increase it by 7 to
> - * make it a positive value (Minumum value is -7).
> - * However this means that values between 0 and 7 have
> - * double meaning, and we should set a 7DBm boost flag.
> - */
> - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST,
> - (info->tx_power1 >= 0));
> -
> - if (info->tx_power1 < 0)
> - info->tx_power1 += 7;
> -
> - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A,
> - TXPOWER_A_TO_DEV(info->tx_power1));
> -
> - rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST,
> - (info->tx_power2 >= 0));
> -
> - if (info->tx_power2 < 0)
> - info->tx_power2 += 7;
> -
> - rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A,
> - TXPOWER_A_TO_DEV(info->tx_power2));
> + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, boost);
> + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, txpower);
> + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, boost);
> + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, txpower);
> } else {
> - rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G,
> - TXPOWER_G_TO_DEV(info->tx_power1));
> - rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G,
> - TXPOWER_G_TO_DEV(info->tx_power2));
> + rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, txpower);
> + rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, txpower);
> }
>
> rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf));
> @@ -1287,7 +1277,7 @@ static void rt2800_config_channel_rf2xxx(struct rt2x00_dev *rt2x00dev,
> static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
> struct ieee80211_conf *conf,
> struct rf_channel *rf,
> - struct channel_info *info)
> + int txpower)
> {
> u8 rfcsr;
>
> @@ -1299,13 +1289,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,
> - TXPOWER_G_TO_DEV(info->tx_power1));
> + rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, txpower);
> rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
>
> rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
> - rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER,
> - TXPOWER_G_TO_DEV(info->tx_power2));
> + rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, txpower);
> rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
>
> rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
> @@ -1323,19 +1311,24 @@ static void rt2800_config_channel_rf3xxx(struct rt2x00_dev *rt2x00dev,
> static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
> struct ieee80211_conf *conf,
> struct rf_channel *rf,
> - struct channel_info *info)
> + int txpower)
> {
> u32 reg;
> unsigned int tx_pin;
> u8 bbp;
>
> + if (rf->channel > 14)
> + txpower = TXPOWER_A_TO_DEV(txpower);
> + else
> + txpower = TXPOWER_G_TO_DEV(txpower);
> +
> if (rt2x00_rf(rt2x00dev, RF2020) ||
> rt2x00_rf(rt2x00dev, RF3020) ||
> rt2x00_rf(rt2x00dev, RF3021) ||
> rt2x00_rf(rt2x00dev, RF3022))
> - rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, info);
> + rt2800_config_channel_rf3xxx(rt2x00dev, conf, rf, txpower);
> else
> - rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, info);
> + rt2800_config_channel_rf2xxx(rt2x00dev, conf, rf, txpower);
>
> /*
> * Change BBP settings
> @@ -1578,7 +1571,7 @@ void rt2800_config(struct rt2x00_dev *rt2x00dev,
>
> if (flags & IEEE80211_CONF_CHANGE_CHANNEL)
> rt2800_config_channel(rt2x00dev, libconf->conf,
> - &libconf->rf, &libconf->channel);
> + &libconf->rf, libconf->conf->power_level);
> if (flags & IEEE80211_CONF_CHANGE_POWER)
> rt2800_config_txpower(rt2x00dev, libconf->conf->power_level);
> if (flags & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
> @@ -3085,8 +3078,9 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> tx_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_G_TXPOWER;
> + info[i].default_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]);
> + info[i].default_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]);
> }
>
> if (spec->num_channels > 14) {
> @@ -3094,8 +3088,9 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
> tx_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_A_TXPOWER;
> + info[i].default_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]);
> + info[i].default_power2 = TXPOWER_A_FROM_DEV(tx_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;
> };
>
> /*
Maybe it's just me, but to me it seems that in the current code
default_power1 and default_power2 are not used at all. What is the use
of these fields?
> 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;
> --
> 1.7.2.1
>
>
> _______________________________________________
> users mailing list
> users at rt2x00.serialmonkey.com
> http://rt2x00.serialmonkey.com/mailman/listinfo/users_rt2x00.serialmonkey.com
>
More information about the users
mailing list