mirror of
https://github.com/openwrt/openwrt.git
synced 2024-12-25 08:21:14 +00:00
6bcd1c2501
Some local patches have been sent to upstream and they are slightly different from the upstream version. So it's better to replace them to avoid conflicts with the new mac80211 backport driver. The different parts have been merged into patch 996. This commit also includes some additional fixes: * Fix watchdog function. * Improve MT7620 register initialization. * Introduce DMA busy watchdog for rt2800. P.S. Sometimes rt2800 series chips may fall into a DMA busy state. The tx queues become very slow and the client cannot connect to the AP. Usually, We can see a lot of hostapd warnings at this point: 'hostapd: IEEE 802.11: did not acknowledge authentication response' The DMA busy watchdog can help the driver automatically recover from this abnormal state. By the way, setting higer 'cell_density' and disabling 'disassoc_low_ack' can significantly reduce the probability of the DMA busy. Signed-off-by: Shiji Yang <yangshiji66@qq.com>
116 lines
4.5 KiB
Diff
116 lines
4.5 KiB
Diff
From 821b5192c955144bd2f0aeea6cd153e1aedd16e1 Mon Sep 17 00:00:00 2001
|
|
From: Shiji Yang <yangshiji66@outlook.com>
|
|
Date: Fri, 11 Aug 2023 14:34:54 +0800
|
|
Subject: wifi: rt2x00: limit MT7620 TX power based on eeprom calibration
|
|
|
|
In the vendor driver, the current channel power is queried from
|
|
EEPROM_TXPOWER_BG1 and EEPROM_TXPOWER_BG2. And then the mixed value
|
|
will be written into the low half-word of the TX_ALC_CFG_0 register.
|
|
The high half-word of the TX_ALC_CFG_0 is a fixed value 0x2f2f.
|
|
|
|
We can't get the accurate TX power. Based on my tests and the new
|
|
MediaTek mt76 driver source code, the real TX power is approximately
|
|
equal to channel_power + (max) rate_power. Usually max rate_power is
|
|
the gain of the OFDM 6M rate, which can be readed from the offset
|
|
EEPROM_TXPOWER_BYRATE +1.
|
|
|
|
Based on these eeprom values, this patch adds basic TX power control
|
|
for the MT7620 and limits its maximum TX power. This can avoid the
|
|
link speed decrease caused by chip overheating. rt2800_config_alc()
|
|
function has also been renamed to rt2800_config_alc_rt6352() because
|
|
it's only used by RT6352 (MT7620).
|
|
|
|
Notice:
|
|
It's still need some work to sync the max channel power to the user
|
|
interface. This part is missing from the rt2x00 driver framework. If
|
|
we set the power exceed the calibration value, it won't take effect.
|
|
|
|
Signed-off-by: Shiji Yang <yangshiji66@outlook.com>
|
|
Acked-by: Stanislaw Gruszka <stf_xl@wp.pl>
|
|
Signed-off-by: Kalle Valo <kvalo@kernel.org>
|
|
Link: https://lore.kernel.org/r/TYAP286MB03159090ED14044215E59FD6BC10A@TYAP286MB0315.JPNP286.PROD.OUTLOOK.COM
|
|
---
|
|
drivers/net/wireless/ralink/rt2x00/rt2800lib.c | 57 ++++++++++++++++++--------
|
|
1 file changed, 40 insertions(+), 17 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
|
+++ b/drivers/net/wireless/ralink/rt2x00/rt2800lib.c
|
|
@@ -3865,28 +3865,51 @@ static void rt2800_config_channel_rf7620
|
|
}
|
|
}
|
|
|
|
-static void rt2800_config_alc(struct rt2x00_dev *rt2x00dev,
|
|
- struct ieee80211_channel *chan,
|
|
- int power_level) {
|
|
- u16 eeprom, target_power, max_power;
|
|
+static void rt2800_config_alc_rt6352(struct rt2x00_dev *rt2x00dev,
|
|
+ struct ieee80211_channel *chan,
|
|
+ int power_level)
|
|
+{
|
|
+ int cur_channel = rt2x00dev->rf_channel;
|
|
+ u16 eeprom, chan_power, rate_power, target_power;
|
|
+ u16 tx_power[2];
|
|
+ s8 *power_group[2];
|
|
u32 mac_sys_ctrl;
|
|
- u32 reg;
|
|
+ u32 cnt, reg;
|
|
u8 bbp;
|
|
|
|
- /* hardware unit is 0.5dBm, limited to 23.5dBm */
|
|
- power_level *= 2;
|
|
- if (power_level > 0x2f)
|
|
- power_level = 0x2f;
|
|
-
|
|
- max_power = chan->max_power * 2;
|
|
- if (max_power > 0x2f)
|
|
- max_power = 0x2f;
|
|
+ if (WARN_ON(cur_channel < 1 || cur_channel > 14))
|
|
+ return;
|
|
+
|
|
+ /* get per chain power, 2 chains in total, unit is 0.5dBm */
|
|
+ power_level = (power_level - 3) * 2;
|
|
+
|
|
+ /* We can't get the accurate TX power. Based on some tests, the real
|
|
+ * TX power is approximately equal to channel_power + (max)rate_power.
|
|
+ * Usually max rate_power is the gain of the OFDM 6M rate. The antenna
|
|
+ * gain and externel PA gain are not included as we are unable to
|
|
+ * obtain these values.
|
|
+ */
|
|
+ rate_power = rt2800_eeprom_read_from_array(rt2x00dev,
|
|
+ EEPROM_TXPOWER_BYRATE, 1);
|
|
+ rate_power &= 0x3f;
|
|
+ power_level -= rate_power;
|
|
+ if (power_level < 1)
|
|
+ power_level = 1;
|
|
+
|
|
+ power_group[0] = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG1);
|
|
+ power_group[1] = rt2800_eeprom_addr(rt2x00dev, EEPROM_TXPOWER_BG2);
|
|
+ for (cnt = 0; cnt < 2; cnt++) {
|
|
+ chan_power = power_group[cnt][cur_channel - 1];
|
|
+ if (chan_power >= 0x20 || chan_power == 0)
|
|
+ chan_power = 0x10;
|
|
+ tx_power[cnt] = power_level < chan_power ? power_level : chan_power;
|
|
+ }
|
|
|
|
reg = rt2800_register_read(rt2x00dev, TX_ALC_CFG_0);
|
|
- rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_0, power_level);
|
|
- rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_1, power_level);
|
|
- rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_0, max_power);
|
|
- rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_1, max_power);
|
|
+ rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_0, tx_power[0]);
|
|
+ rt2x00_set_field32(®, TX_ALC_CFG_0_CH_INIT_1, tx_power[1]);
|
|
+ rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_0, 0x2f);
|
|
+ rt2x00_set_field32(®, TX_ALC_CFG_0_LIMIT_1, 0x2f);
|
|
|
|
eeprom = rt2800_eeprom_read(rt2x00dev, EEPROM_NIC_CONF1);
|
|
if (rt2x00_get_field16(eeprom, EEPROM_NIC_CONF1_INTERNAL_TX_ALC)) {
|
|
@@ -5268,7 +5291,7 @@ static void rt2800_config_txpower_rt6352
|
|
rt2x00_set_field32(&pwreg, TX_PWR_CFG_9B_STBC_MCS7, t);
|
|
rt2800_register_write(rt2x00dev, TX_PWR_CFG_9, pwreg);
|
|
|
|
- rt2800_config_alc(rt2x00dev, chan, power_level);
|
|
+ rt2800_config_alc_rt6352(rt2x00dev, chan, power_level);
|
|
|
|
/* TODO: temperature compensation code! */
|
|
}
|