aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
authorIvo van Doorn <ivdoorn@gmail.com>2010-08-23 13:56:07 -0400
committerJohn W. Linville <linville@tuxdriver.com>2010-08-25 14:34:55 -0400
commit8d1331b37d5b656a7a8e561f8e9d7661dd00c910 (patch)
tree2fd13c84b703b7dcf54b0f8293aeda8eec72228a /drivers/net
parent46323e112ce2a0fdaf2dd5389f95b248576b8fda (diff)
rt2x00: Fix max TX power settings
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. This fixes bug complaining about limited TX power values like: https://bugzilla.kernel.org/show_bug.cgi?id=16358 Signed-off-by: Ivo van Doorn <IvDoorn@gmail.com> Acked-by: Helmut Schaa <helmut.schaa@googlemail.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c12
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c12
-rw-r--r--drivers/net/wireless/rt2x00/rt2800.h7
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c65
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h5
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c12
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c12
9 files changed, 86 insertions, 47 deletions
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index b86b6132a69..e3005ff5ae9 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)
1487 spec->channels_info = info; 1487 spec->channels_info = info;
1488 1488
1489 tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); 1489 tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
1490 for (i = 0; i < 14; i++) 1490 for (i = 0; i < 14; i++) {
1491 info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); 1491 info[i].max_power = TXPOWER_FROM_DEV(MAX_TXPOWER);
1492 info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
1493 }
1492 1494
1493 return 0; 1495 return 0;
1494} 1496}
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 21f45810fd1..1e6a91b8d3d 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)
1801 spec->channels_info = info; 1801 spec->channels_info = info;
1802 1802
1803 tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); 1803 tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
1804 for (i = 0; i < 14; i++) 1804 for (i = 0; i < 14; i++) {
1805 info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); 1805 info[i].max_power = MAX_TXPOWER;
1806 info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
1807 }
1806 1808
1807 if (spec->num_channels > 14) { 1809 if (spec->num_channels > 14) {
1808 for (i = 14; i < spec->num_channels; i++) 1810 for (i = 14; i < spec->num_channels; i++) {
1809 info[i].tx_power1 = DEFAULT_TXPOWER; 1811 info[i].max_power = MAX_TXPOWER;
1812 info[i].default_power1 = DEFAULT_TXPOWER;
1813 }
1810 } 1814 }
1811 1815
1812 return 0; 1816 return 0;
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index 8722464944f..71d8d821c4e 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1706,12 +1706,16 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
1706 spec->channels_info = info; 1706 spec->channels_info = info;
1707 1707
1708 tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START); 1708 tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_START);
1709 for (i = 0; i < 14; i++) 1709 for (i = 0; i < 14; i++) {
1710 info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); 1710 info[i].max_power = MAX_TXPOWER;
1711 info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
1712 }
1711 1713
1712 if (spec->num_channels > 14) { 1714 if (spec->num_channels > 14) {
1713 for (i = 14; i < spec->num_channels; i++) 1715 for (i = 14; i < spec->num_channels; i++) {
1714 info[i].tx_power1 = DEFAULT_TXPOWER; 1716 info[i].max_power = MAX_TXPOWER;
1717 info[i].default_power1 = DEFAULT_TXPOWER;
1718 }
1715 } 1719 }
1716 1720
1717 return 0; 1721 return 0;
diff --git a/drivers/net/wireless/rt2x00/rt2800.h b/drivers/net/wireless/rt2x00/rt2800.h
index cf1f16bfcd5..5c006a79534 100644
--- a/drivers/net/wireless/rt2x00/rt2800.h
+++ b/drivers/net/wireless/rt2x00/rt2800.h
@@ -1859,6 +1859,13 @@ struct mac_iveiv_entry {
1859#define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00) 1859#define EEPROM_RSSI_A2_LNA_A2 FIELD16(0xff00)
1860 1860
1861/* 1861/*
1862 * EEPROM Maximum TX power values
1863 */
1864#define EEPROM_MAX_TX_POWER 0x0027
1865#define EEPROM_MAX_TX_POWER_24GHZ FIELD16(0x00ff)
1866#define EEPROM_MAX_TX_POWER_5GHZ FIELD16(0xff00)
1867
1868/*
1862 * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power. 1869 * EEPROM TXpower delta: 20MHZ AND 40 MHZ use different power.
1863 * This is delta in 40MHZ. 1870 * This is delta in 40MHZ.
1864 * VALUE: Tx Power dalta value (MAX=4) 1871 * VALUE: Tx Power dalta value (MAX=4)
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index cbab2e12616..ecbd07a78ed 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,
1239 * double meaning, and we should set a 7DBm boost flag. 1239 * double meaning, and we should set a 7DBm boost flag.
1240 */ 1240 */
1241 rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST, 1241 rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A_7DBM_BOOST,
1242 (info->tx_power1 >= 0)); 1242 (info->default_power1 >= 0));
1243 1243
1244 if (info->tx_power1 < 0) 1244 if (info->default_power1 < 0)
1245 info->tx_power1 += 7; 1245 info->default_power1 += 7;
1246 1246
1247 rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, info->tx_power1); 1247 rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_A, info->default_power1);
1248 1248
1249 rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST, 1249 rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A_7DBM_BOOST,
1250 (info->tx_power2 >= 0)); 1250 (info->default_power2 >= 0));
1251 1251
1252 if (info->tx_power2 < 0) 1252 if (info->default_power2 < 0)
1253 info->tx_power2 += 7; 1253 info->default_power2 += 7;
1254 1254
1255 rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, info->tx_power2); 1255 rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_A, info->default_power2);
1256 } else { 1256 } else {
1257 rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, info->tx_power1); 1257 rt2x00_set_field32(&rf->rf3, RF3_TXPOWER_G, info->default_power1);
1258 rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, info->tx_power2); 1258 rt2x00_set_field32(&rf->rf4, RF4_TXPOWER_G, info->default_power2);
1259 } 1259 }
1260 1260
1261 rt2x00_set_field32(&rf->rf4, RF4_HT40, conf_is_ht40(conf)); 1261 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,
1295 rt2800_rfcsr_write(rt2x00dev, 6, rfcsr); 1295 rt2800_rfcsr_write(rt2x00dev, 6, rfcsr);
1296 1296
1297 rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr); 1297 rt2800_rfcsr_read(rt2x00dev, 12, &rfcsr);
1298 rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, info->tx_power1); 1298 rt2x00_set_field8(&rfcsr, RFCSR12_TX_POWER, info->default_power1);
1299 rt2800_rfcsr_write(rt2x00dev, 12, rfcsr); 1299 rt2800_rfcsr_write(rt2x00dev, 12, rfcsr);
1300 1300
1301 rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr); 1301 rt2800_rfcsr_read(rt2x00dev, 13, &rfcsr);
1302 rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->tx_power2); 1302 rt2x00_set_field8(&rfcsr, RFCSR13_TX_POWER, info->default_power2);
1303 rt2800_rfcsr_write(rt2x00dev, 13, rfcsr); 1303 rt2800_rfcsr_write(rt2x00dev, 13, rfcsr);
1304 1304
1305 rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr); 1305 rt2800_rfcsr_read(rt2x00dev, 23, &rfcsr);
@@ -1324,11 +1324,11 @@ static void rt2800_config_channel(struct rt2x00_dev *rt2x00dev,
1324 u8 bbp; 1324 u8 bbp;
1325 1325
1326 if (rf->channel <= 14) { 1326 if (rf->channel <= 14) {
1327 info->tx_power1 = TXPOWER_G_TO_DEV(info->tx_power1); 1327 info->default_power1 = TXPOWER_G_TO_DEV(info->default_power1);
1328 info->tx_power2 = TXPOWER_G_TO_DEV(info->tx_power2); 1328 info->default_power2 = TXPOWER_G_TO_DEV(info->default_power2);
1329 } else { 1329 } else {
1330 info->tx_power1 = TXPOWER_A_TO_DEV(info->tx_power1); 1330 info->default_power1 = TXPOWER_A_TO_DEV(info->default_power1);
1331 info->tx_power2 = TXPOWER_A_TO_DEV(info->tx_power2); 1331 info->default_power2 = TXPOWER_A_TO_DEV(info->default_power2);
1332 } 1332 }
1333 1333
1334 if (rt2x00_rf(rt2x00dev, RF2020) || 1334 if (rt2x00_rf(rt2x00dev, RF2020) ||
@@ -2729,6 +2729,13 @@ int rt2800_validate_eeprom(struct rt2x00_dev *rt2x00dev)
2729 default_lna_gain); 2729 default_lna_gain);
2730 rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word); 2730 rt2x00_eeprom_write(rt2x00dev, EEPROM_RSSI_A2, word);
2731 2731
2732 rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &word);
2733 if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_24GHZ) == 0xff)
2734 rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_24GHZ, MAX_G_TXPOWER);
2735 if (rt2x00_get_field16(word, EEPROM_MAX_TX_POWER_5GHZ) == 0xff)
2736 rt2x00_set_field16(&word, EEPROM_MAX_TX_POWER_5GHZ, MAX_A_TXPOWER);
2737 rt2x00_eeprom_write(rt2x00dev, EEPROM_MAX_TX_POWER, word);
2738
2732 return 0; 2739 return 0;
2733} 2740}
2734EXPORT_SYMBOL_GPL(rt2800_validate_eeprom); 2741EXPORT_SYMBOL_GPL(rt2800_validate_eeprom);
@@ -2968,9 +2975,10 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
2968{ 2975{
2969 struct hw_mode_spec *spec = &rt2x00dev->spec; 2976 struct hw_mode_spec *spec = &rt2x00dev->spec;
2970 struct channel_info *info; 2977 struct channel_info *info;
2971 char *tx_power1; 2978 char *default_power1;
2972 char *tx_power2; 2979 char *default_power2;
2973 unsigned int i; 2980 unsigned int i;
2981 unsigned short max_power;
2974 u16 eeprom; 2982 u16 eeprom;
2975 2983
2976 /* 2984 /*
@@ -3084,21 +3092,26 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
3084 3092
3085 spec->channels_info = info; 3093 spec->channels_info = info;
3086 3094
3087 tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1); 3095 rt2x00_eeprom_read(rt2x00dev, EEPROM_MAX_TX_POWER, &eeprom);
3088 tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2); 3096 max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_24GHZ);
3097 default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
3098 default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
3089 3099
3090 for (i = 0; i < 14; i++) { 3100 for (i = 0; i < 14; i++) {
3091 info[i].tx_power1 = TXPOWER_G_FROM_DEV(tx_power1[i]); 3101 info[i].max_power = max_power;
3092 info[i].tx_power2 = TXPOWER_G_FROM_DEV(tx_power2[i]); 3102 info[i].default_power1 = TXPOWER_G_FROM_DEV(default_power1[i]);
3103 info[i].default_power2 = TXPOWER_G_FROM_DEV(default_power2[i]);
3093 } 3104 }
3094 3105
3095 if (spec->num_channels > 14) { 3106 if (spec->num_channels > 14) {
3096 tx_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1); 3107 max_power = rt2x00_get_field16(eeprom, EEPROM_MAX_TX_POWER_5GHZ);
3097 tx_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2); 3108 default_power1 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A1);
3109 default_power2 = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A2);
3098 3110
3099 for (i = 14; i < spec->num_channels; i++) { 3111 for (i = 14; i < spec->num_channels; i++) {
3100 info[i].tx_power1 = TXPOWER_A_FROM_DEV(tx_power1[i]); 3112 info[i].max_power = max_power;
3101 info[i].tx_power2 = TXPOWER_A_FROM_DEV(tx_power2[i]); 3113 info[i].default_power1 = TXPOWER_A_FROM_DEV(default_power1[i]);
3114 info[i].default_power2 = TXPOWER_A_FROM_DEV(default_power2[i]);
3102 } 3115 }
3103 } 3116 }
3104 3117
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 69308a0df74..762f6b4e7af 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -213,8 +213,9 @@ struct channel_info {
213 unsigned int flags; 213 unsigned int flags;
214#define GEOGRAPHY_ALLOWED 0x00000001 214#define GEOGRAPHY_ALLOWED 0x00000001
215 215
216 short tx_power1; 216 short max_power;
217 short tx_power2; 217 short default_power1;
218 short default_power2;
218}; 219};
219 220
220/* 221/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index e692608bee8..580595ba568 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,
711 for (i = 0; i < spec->num_channels; i++) { 711 for (i = 0; i < spec->num_channels; i++) {
712 rt2x00lib_channel(&channels[i], 712 rt2x00lib_channel(&channels[i],
713 spec->channels[i].channel, 713 spec->channels[i].channel,
714 spec->channels_info[i].tx_power1, i); 714 spec->channels_info[i].max_power, i);
715 } 715 }
716 716
717 /* 717 /*
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index ae4698e1872..8f017ad8c3d 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)
2656 spec->channels_info = info; 2656 spec->channels_info = info;
2657 2657
2658 tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START); 2658 tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
2659 for (i = 0; i < 14; i++) 2659 for (i = 0; i < 14; i++) {
2660 info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); 2660 info[i].max_power = MAX_TXPOWER;
2661 info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
2662 }
2661 2663
2662 if (spec->num_channels > 14) { 2664 if (spec->num_channels > 14) {
2663 tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); 2665 tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
2664 for (i = 14; i < spec->num_channels; i++) 2666 for (i = 14; i < spec->num_channels; i++) {
2665 info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); 2667 info[i].max_power = MAX_TXPOWER;
2668 info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
2669 }
2666 } 2670 }
2667 2671
2668 return 0; 2672 return 0;
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index ab9389439d7..ee2c52fd0d7 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)
2090 spec->channels_info = info; 2090 spec->channels_info = info;
2091 2091
2092 tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START); 2092 tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_G_START);
2093 for (i = 0; i < 14; i++) 2093 for (i = 0; i < 14; i++) {
2094 info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); 2094 info[i].max_power = MAX_TXPOWER;
2095 info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
2096 }
2095 2097
2096 if (spec->num_channels > 14) { 2098 if (spec->num_channels > 14) {
2097 tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START); 2099 tx_power = rt2x00_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_A_START);
2098 for (i = 14; i < spec->num_channels; i++) 2100 for (i = 14; i < spec->num_channels; i++) {
2099 info[i].tx_power1 = TXPOWER_FROM_DEV(tx_power[i]); 2101 info[i].max_power = MAX_TXPOWER;
2102 info[i].default_power1 = TXPOWER_FROM_DEV(tx_power[i]);
2103 }
2100 } 2104 }
2101 2105
2102 return 0; 2106 return 0;