openwrt / mt76

mac80211 driver for MediaTek MT76x0e, MT76x2e, MT7603, MT7615, MT7628 and MT7688
742 stars 342 forks source link

mt76 TX power not working in multiple chipsets (mt7610, mt7613, mt7615, mt7603) #633

Open dmsza opened 2 years ago

dmsza commented 2 years ago

Just looking at the bug reports here and in the OpenWRT defects repository, it is clear that for various mt76 chipsets the TX power is simply not working.

I myself am experimenting two issues with OpenWRT and mt76 drivers:

Searching here in the mt76 repository about similar TX power issues, I've found multiple similar reports:

TP-LINK RE200 problem with the operation of the WLAN chipset. OpenWRT rel 21.02rc4 #606 MT7610E: TX-Power Values incorrect -> low range #604 MT76x0: Correct VHT MCS 8/9 tx power eeprom offset #577 MT7615dn: 5G max power is 6dBm #574 Xiaomi r3p mt7615N low tx power 2ghz 5ghz #539 Low transmission power on MT7610EN #530 mt7603e max tx power is only 8 dBm on HiWiFi HC5962 #525 low tx power with mt76x0e driver #484 Low-incorrect txpower on Mediatek 7628 (TP-Link 840 ver 6.0) #279 Various issues with 5Ghz MT7610E #227 low tx power m7610e #216

And some other more.

While as in the TP-Link Archer C6 v3 (mt7613) where TX Power is stuck at maximum allows it to be perfectly usable, on other devices such as TP-Link RE200 v2 (mt7610) wifi is unusable due to the very weak 5Ghz signal power.

So instead of opening more bug reports here for my TX Power issues with mt7613 and mt7610, I've decided summarize the existing bug reports about TX power here so perhaps we can concentrate the developers' focus on this single bug report.

phil2sat commented 2 years ago

im no dev or any not familiar with driver development, but i did try to read the 0x012c value and add +17 yay, looked fine at least cosmetically, but measured on 20m there was no gain in txpower, mesh cant connect sae auth error and my fritzbox was receiving - 95/-100dbm.

after the hack i mentioned its fine and stable, no connection loss since 3 days.

my bet is that the RE200v2 radio is missing something maybe other mt76x0 also or its only the EU eeprom which is different, since on other devices the actual driver seems to get better results. im afraid of editing my radio partition, since the repeater sits in a custom housing 6m above the groundand without lan cable.

@theparasol which device do u use and did you try to build with the new reading? some progress?

i personally would like a proper implementation thats working on all devices. but after 4 years of RE200v2, its the first time it does work.

tried original firmware, problem was my childs connectet to the RE200 and since all devices behind surfed with the RE200 mac and IP no internet blocking was possible.

tried wds with openwrt no success tried bridging, no succes.

then mesh but since only 2g worked it was damn slow, now upstream mesh is 5g and ap is 2g to cover my whole garden. around 30mbit in every corner, fair enough for the mist things i do outside

theparasol commented 2 years ago

@phil2sat I'm waiting for my ordered TL-WR902AC v3 EU to arrive. I ordered it to use it as a small 5 ghz wifi STA to lan client adapter and connect the lan to the wan port of my existing YouHua WR1200JS wireless router (also with openwrt). My hopes are doing it this way it will crank up the throughput performance and simplify my WR1200JS config by removing the needed STA 5 Ghz connection on this router to the uplink and by doing this I can use a free 5 Ghz channel for my own SSID for my personal network instead of obliged sharing and interfering with the wifi uplink each time they communicate with whatever device on the local lan. Too bad I didn't notice the remark at the end of the openwrt wiki page referring to this 5 Ghz power issue before I ordered it. Already did some research myself for other existing drivers for this chip. I believe it was initialy branded as Ralink before MediaTek took over. Found another opensource driver that implements TSSI and I can already see it uses other eprom fields to calculate the delta power. At this moment I'm curious how long this issue already resides in the mt79 driver package. Did it work ok in the past?

cgm999 commented 2 years ago

@phil2sat I tried your hack.. I can not say it helps . in fact is easy to patch the ko file (from latest snapshot for example ,copy outside openwrt,patch with below perl line, then put it in /lib/modules/$kernel_version

perl -i -pe 's/\x40\x01\x42\x7c\x2c\x00\x40\x14/\x40\x01\x42\x7c\x2c\x00\x40\x10/ && warn "found\n"' mt76x0-common.ko

@phil2sat please upload your radio partition. I have re200V4 .. and would like to see if using yours is better.

pepe2k commented 2 years ago

Sorry for hijacking the topic but I might have some information which could possibly help to understand at least part of the problem.

One of the vendor which uses MediaTek radios informed that this problem could be related to usage of external PA for the 2.4 GHz band and Windows drivers which ignore EEPROM settings for that (even the fact that MediaTek EEPROM documentation describes that option, the reference design doesn't include such configuration).

As an example I was given a USB dongle based on the MT7610U with external PA for both bands (with up to 25 dBm target power on 2.4 GHz), but the EEPROM selects internal PA for the 2.4 GHz because the Windows driver doesn't understand that the board includes external PA and would enable too high gain which would result in saturating external PA. To solve this mess, vendor selects in EEPROM internal PA and a very low target output power (like 2-3 dBm). This allows to keep the real TX power (including the external PA gain) in target limits. I was told that even the mt76 driver under Linux/OpenWrt reports low TX power, the real output should be correct as the external PA is always enabled.

I'm not sure how this could be related to the embedded (PCIe/WMAC) radios and other bands but I suppose the problem could be somewhere in MediaTek tools used by vendors for calibration and EEPROM configuration.

phil2sat commented 2 years ago

@cgm999 first heres the radio partition RE200.mtd6.bin.gz

Problem was i could set maximum 10dbi on channel 36 and only 6dbi at 108, now 20dbi on all and in fact i can see the difference, the best my fritzbox ever received from the RE200 was -88bdm fluctuating around -95 to -100dbm. thats the actual values: signal: -79 [-78, -82, -89, -89] dBm signal avg: -79 [-80, -88, -89, -89] dBm waay better, not as good as my fritzbox 7530 with @17dbi signal: -65 [-65] dBm signal avg: -66 [-66] dBm But hey this device costs a lot more has more antennas multi mimo beamforming and im able to send with 30bdi(1000mw) if i want.

@theparasol so far i know its the same chip, but there could be different firmware, dont know if its the same problem as with the RE200v2, the idea is correct, set all wifi devices to lan and create only a mesh with sae auth for 5ghz and the ap sta on 2.4. So the complete router communication is on 5ghz and you benefit of the full bandwidth of the 2.4ghz (IF youre able to get a stable route to the upstream station) this cheapo devices hates walls and anything whats in their way like windows or tin roofs.

@pepe2k the 2.4 part is fine, so fine that if i sit in my kitchen on the other side of my house (3 walls, a tin roof, and 45m away) i get -65dbm on my smartphone with @23dbm txpower, so i lowered it to 19dbm. BTW caldata, EEPROM, maybe coext are also some vendor specific things i bet on but since im no dev, doin hard with hex values in eeproms, im happy that im able to use this shitty thing ive ever hated. Stock Firmware did fine, not really strong but did. But "NO" features.

image Has someone ever tried to apply an external antenna, i guess its the 5ghz in the middle!?

Im loving OpenWRT since i got my Archer C7, nice stable device, runs years without only one reboot, now i converted my FritzBox 7530, Wifi wise its ages better but hey costs also triple the Archer which i ordered refurbished fo 30€ but the Fritzbox goes for 90€ used. Really, if i wanted a reliable device ive buyed a used Archer not a MT7628AN device, maybe a Belkin 3200 or how its called (for future devices)

But its there it has to live... it has to work... there must be a way...

DragonBluep commented 2 years ago

@pepe2k I think you're right. In the circuit of #574 MSG1500, dual-band WiFi comes from the same MT7615D chip. 2.4g circuits do not have PA, but 5g circuits do, so the output power of 5G band is very low. In fact, of the multiple routers I have, all the routers without external PA/FEM have normal power output (at least 20dbm).

On the other hand, the output power of MT7612 is normal, but the power adjustment effect is not obvious for devices with high power external PA (Phicomm K2), perhaps because of what you mentioned enable too high gain which would result in saturating external PA.

phil2sat commented 2 years ago

@DragonBluep, maybe this is whats the external frontend (PA?) patch does!? #286, i tried to implement it in actual source but there is

so im unable to use this patch, since i cant code but if this is the proper way to use the "xo1" thing to initialize the external PA then i would love to implement it for RE200 or maybe in device config as extra kernel option (menuconfig -> enable external frontend) or something

+++ b/mt76x02_eeprom.h  2019-06-10 13:54:03.917757060 +0300
@@ -26,6 +26,7 @@
    MT_EE_MAC_ADDR =            0x004,
    MT_EE_PCI_ID =              0x00A,
    MT_EE_ANTENNA =             0x022,
+   MT_EE_CMB_CONF =            0x024,    ## Called CFG1_INIT in actual source
    MT_EE_NIC_CONF_0 =          0x034,
    MT_EE_NIC_CONF_1 =          0x036,
    MT_EE_COUNTRY_REGION_5GHZ =     0x038,
^^^ The upper Part has to go, as its included already ^^^

--- a/mt76x0/phy.c  2019-06-10 15:35:48.359723691 +0300
+++ b/mt76x0/phy.c  2019-06-10 14:54:42.995453471 +0300
@@ -439,14 +439,22 @@
 static void mt76x0_phy_ant_select(struct mt76x02_dev *dev)
 {
    u16 ee_ant = mt76x02_eeprom_get(dev, MT_EE_ANTENNA);
+   u16 ee_cmb = mt76x02_eeprom_get(dev, MT_EE_CMB_CONF);    ## Here i guess CFG1_INIT
    u16 nic_conf2 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_2);
-   u32 wlan, coex3, cmb;
+   u32 wlan, coex3, cmb, xo1;
    bool ant_div;

    wlan = mt76_rr(dev, MT_WLAN_FUN_CTRL);
    cmb = mt76_rr(dev, MT_CMB_CTRL);
    coex3 = mt76_rr(dev, MT_COEXCFG3);

+   xo1 = mt76_rr(dev, MT_XO_CTRL1);
+   xo1 &= 0xffff0000;
+   xo1 |= (u32)ee_cmb;
+
+   cmb &= 0xffff0000;
+   cmb |= (u32)ee_ant;
+
    cmb   &= ~(BIT(14) | BIT(12));
    wlan  &= ~(BIT(6) | BIT(5));
    coex3 &= ~GENMASK(5, 2);
@@ -481,6 +489,8 @@
    mt76_wr(dev, MT_CMB_CTRL, cmb);
    mt76_clear(dev, MT_COEXCFG0, BIT(2));
    mt76_wr(dev, MT_COEXCFG3, coex3);
+
+   mt76_wr(dev, MT_XO_CTRL1, xo1);
 }

 static void

HERE IS THE ACTUAL SOURCE

static void mt76x0_phy_ant_select(struct mt76x02_dev *dev)
{
        u16 ee_ant = mt76x02_eeprom_get(dev, MT_EE_ANTENNA);
        u16 ee_cfg1 = mt76x02_eeprom_get(dev, MT_EE_CFG1_INIT);
        u16 nic_conf2 = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_2);
        u32 wlan, coex3;
        bool ant_div;

        wlan = mt76_rr(dev, MT_WLAN_FUN_CTRL);
        coex3 = mt76_rr(dev, MT_COEXCFG3);

        ee_ant &= ~(BIT(14) | BIT(12));
        wlan  &= ~(BIT(6) | BIT(5));
        coex3 &= ~GENMASK(5, 2);

        if (ee_ant & MT_EE_ANTENNA_DUAL) {
                /* dual antenna mode */
                ant_div = !(nic_conf2 & MT_EE_NIC_CONF_2_ANT_OPT) &&
                          (nic_conf2 & MT_EE_NIC_CONF_2_ANT_DIV);
                if (ant_div)
                        ee_ant |= BIT(12);
                else
                        coex3 |= BIT(4);
                coex3 |= BIT(3);
                if (dev->mphy.cap.has_2ghz)
                        wlan |= BIT(6);
        } else {
                /* sigle antenna mode */
                if (dev->mphy.cap.has_5ghz) {
                        coex3 |= BIT(3) | BIT(4);
                } else {
                        wlan |= BIT(6);
                        coex3 |= BIT(1);
                }
        }

        if (is_mt7630(dev))
                ee_ant |= BIT(14) | BIT(11);

        mt76_wr(dev, MT_WLAN_FUN_CTRL, wlan);
        mt76_rmw(dev, MT_CMB_CTRL, GENMASK(15, 0), ee_ant);
        mt76_rmw(dev, MT_CSR_EE_CFG1, GENMASK(15, 0), ee_cfg1);
        mt76_clear(dev, MT_COEXCFG0, BIT(2));
        mt76_wr(dev, MT_COEXCFG3, coex3);
}

static void

But im afraid to try cause the codes differ so hard and i dont know what im doin

theparasol commented 2 years ago

This is another opensource driver I found for the mt7610e, perhaps we can get some pointers / ideas from it to improve things. https://github.com/wifimedia/mt7610e

https://github.com/wifimedia/mt7610e/blob/master/ap/ap.c Search for MT76x0_TSSI_CAL_COMPENSATION

phil2sat commented 2 years ago

mhmm target + efuse, if i only knew i little bit more of development

on the other hand thats what i already did, target power + 17 gave me bright and shiny 27dbi on channel 36, looks nice but what my fritzbox received was the same dbm as with the crappy default 10dbi, so thats what you see in iw or luci, but not the real txpower.

--- a/mt76x0/eeprom.c.orig      2022-04-19 15:34:13.499506211 +0200
+++ b/mt76x0/eeprom.c   2022-04-19 15:35:40.187379225 +0200
@@ -228,7 +228,7 @@
        int i, idx = 0;
        u16 data;

-       if (mt76x0_tssi_enabled(dev)) {
+       if (!mt76x0_tssi_enabled(dev)) {     # This little ! as far as i know is a NOT, does the trick for me
                s8 target_power;

                if (chan->band == NL80211_BAND_5GHZ)
DragonBluep commented 2 years ago

2022-04-23 11-42-26 I did some simple tests and it seems that the real transmit power of the MT7610E is correct, although the displayed value on the LuCI interface is very low (about 9-12dBm in different channels). The router has a SKY85703-11 FEM chip.

phil2sat commented 2 years ago

@DragonBluep and thats the problem, depending on device and firmware all have the 7610E, some have real txpower values in luci, some have low but working fine.

the RE200v2 normally has low values around 6 to 10dbi
but good connection is only possible next to the device 30cm. maybe the EU version does not have a external PA since it does not need to output a high output trought to regulatory. in this case my calculation is 10dbi + 10dbi PA gives real 20dbi which is fine but for EU its still 10dbi since there is no such amplification (just guessing).

so not using the eeprom values which are val 8 +- regdb giving 6 to 10dbi depending on channel does fix the low txpower for devices without PA which is exact 20dbi and thats max for EU, other devices do 27 or 30dbi for non EU regions. here if txpower is sames as stock but dbm is lower than on stock i guess its a caldata or coext/EEPROM issues.

that are my assumptions, so ! using tssi val s8 gives 20dbi for me rather than 6 to 10dbi.

problem is same or similar chip on so much different hardware desings/regions/EEPROMS

And the 9 to 12dbi is correct for non EU, maybe 12 +12 anplifier is 24dbi depending on regdb it should go up to 27dbi using PA as country. just try

the RE200 was one of the last supported devices and since i remeber 5ghz was unusable if not on stock firmware. always used 2g only

DragonBluep commented 2 years ago

but good connection is only possible next to the device 30cm.

@phil2sat I can confirm that re200v2 has PA. from the photos you shared, we can see that the model is sky85703, which is the same as mine. I suspect your PA is not working properly. Can you share your EEPROM file? Or you can try this EEPROM. mt7610_eeprom.zip

DragonBluep commented 2 years ago

Another test for Raisecom MSG1500 (MT7621 + MT7615D). I fixed the location of the phone and router, and tried to keep them the same during the test. It seems that the output power showed by the mt76 driver is not the real value. Although the 5G WiFi output power queried in LuCI is only 6dBm (2.4G is 25dBm, probably due to no external PA), the transmit power of the mt76 driver is even stronger than the official firmware. 2022-04-23 202703

theparasol commented 2 years ago

mt76x0_tssi_enabled is buggy. in our mt76x0\eeprom.h

MT_EE_NIC_CONF_1 = 0x036 MT_EE_NIC_CONF_1_TX_ALC_EN = BIT(13)

static inline bool mt76x0_tssi_enabled(struct mt76x02_dev *dev)
{
    return (mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1) &
        MT_EE_NIC_CONF_1_TX_ALC_EN);
}

comparing with the driver I found inside the tp-link gpl code of the WR902-AC:

EEPROM_NIC2_OFFSET = 0x036

RT28xx_EEPROM_READ16(pAd, EEPROM_NIC2_OFFSET, value);
    if (value == 0xFFFF) /*EEPROM is empty*/
        pAd->chipCap.bInternalTxALC = FALSE;
    else if (value & 1<<13) 
        pAd->chipCap.bInternalTxALC = TRUE;
    else 
        pAd->chipCap.bInternalTxALC = FALSE;

    DBGPRINT(RT_DEBUG_OFF, ("TXALC> bInternalTxALC = %d\n", pAd->chipCap.bInternalTxALC));

As we can see, the eeprom empty check is missing in our driver. So for devices with empty eeproms we test bit 13 is set and indeed it is set so enable TSSI but all power data is bogus and so messing up the power output downstream. So we need to add the empty check:

static inline bool mt76x0_tssi_enabled(struct mt76x02_dev *dev)
{
    u16 val;
    val = mt76x02_eeprom_get(dev, MT_EE_NIC_CONF_1);
    if (val == 0xFFFF) /*EEPROM is empty*/
    {
        return false; 
    }
    return val & MT_EE_NIC_CONF_1_TX_ALC_EN;
}

This is the first thing we need to fix, I cant test right now myself since my delivery was delayed. Should have received my WR902-AC yesterday.

Once we have this fix in we can drill down further comparing driver implementation details.

phil2sat commented 2 years ago

this weekend no time to test, but thats wat i guess the patch does !tssi, so mine runs, monday ill try the eeprom, btw mine i already uploaded a couple of post before. i compiled the mt eeprom check and saw that some parts missing, like others are not FFed till end.

but even if i understand halfway whats going on, i cant rewrite code, simple changes yes, but rewriting functions is too far for my knowledge.

ill try to put it in a patch file and test it monday

theparasol commented 2 years ago

Found something more:

in mt76x0\eeprom.c

MT_EE_5G_TARGET_POWER = 0x0d2

static s8 mt76x0_get_delta(struct mt76x02_dev *dev)
{
    struct cfg80211_chan_def *chandef = &dev->mphy.chandef;
    u8 val;

    if (chandef->width == NL80211_CHAN_WIDTH_80) {
        val = mt76x02_eeprom_get(dev, MT_EE_5G_TARGET_POWER) >> 8;
    } else if (chandef->width == NL80211_CHAN_WIDTH_40) {
        u16 data;

        data = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW40);
        if (chandef->chan->band == NL80211_BAND_5GHZ)
            val = data >> 8;
        else
            val = data;
    } else {
        return 0;
    }

    return mt76x02_rate_power_val(val);
}

in reference driver from gpl:

EEPROM_VHT_BW80_TX_POWER_DELTA = 0x0d3

// Get power delta for BW80
//
RT28xx_EEPROM_READ16(pAd, EEPROM_VHT_BW80_TX_POWER_DELTA, value);
TxPwrBw80ABand = 0;
pAd->chipCap.delta_tw_pwr_bw80 = \
                            (value & 0xFF) == 0xFF ? 0 : (value & 0xFF);

So we are reading the wrong value from eeprom!

so the method should be:

static s8 mt76x0_get_delta(struct mt76x02_dev *dev)
{
    struct cfg80211_chan_def *chandef = &dev->mphy.chandef;
    u8 val;

    if (chandef->width == NL80211_CHAN_WIDTH_80) {
        val = mt76x02_eeprom_get(dev, MT_EE_5G_TARGET_POWER+1) >> 8;
    } else if (chandef->width == NL80211_CHAN_WIDTH_40) {
        u16 data;

        data = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW40);
        if (chandef->chan->band == NL80211_BAND_5GHZ)
            val = data >> 8;
        else
            val = data;
    } else {
        return 0;
    }

    return mt76x02_rate_power_val(val);
}
DragonBluep commented 2 years ago

So for devices with empty eeproms we test bit 13 is set and indeed it is set so enable TSSI but all power data is bogus

I think so too, Tssi status determines whether PA is enabled. So I want to check the EEPROM of these devices that are not working properly.

So we are reading the wrong value from eeprom!

The code is correct, we have the extra offset value >>8. mt76x02_eeprom_get can read two bytes.

theparasol commented 2 years ago

Hmm... thinking my code change over again, my improve proposal is still wrong!

D2 = 12 D3 = 34 D4 = 56 D5 = 78

Our driver currently: Read 2 bytes starting on postion D2 = 0x1234h After the bitshift result = 0x0012h

the GPL implementation: Read 2 bytes starting on position D3 = 0x3456h Just keep the lowbyte of the word = 56h

So we should actually read val on position D4 = 0x5678h After the bitshift result = 0x0056h

Position D4 in eeprom has nice name "MT_EE_TSSI_BOUND1"

So to correct things the right way we should change this method actually to this:

static s8 mt76x0_get_delta(struct mt76x02_dev *dev)
{
    struct cfg80211_chan_def *chandef = &dev->mphy.chandef;
    u8 val;

    if (chandef->width == NL80211_CHAN_WIDTH_80) {
        val = mt76x02_eeprom_get(dev, MT_EE_TSSI_BOUND1) >> 8;
    } else if (chandef->width == NL80211_CHAN_WIDTH_40) {
        u16 data;

        data = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW40);
        if (chandef->chan->band == NL80211_BAND_5GHZ)
            val = data >> 8;
        else
            val = data;
    } else {
        return 0;
    }

    return mt76x02_rate_power_val(val);
}
DragonBluep commented 2 years ago

Hmm... thinking my code change over again, my improve proposal is still wrong!

D2 = 12 D3 = 34 D4 = 56 D5 = 78

Our driver currently: Read 2 bytes starting on postion D2 = 0x1234h After the bitshift result = 0x0012h

mt76x02_eeprom_get called get_unaligned_le16 (little-endian 16 bits, le16) so the upper byte of the data should be stored in the upper memory address. Read 2 bytes starting on postion D2 not get 0x1234 but 0x3412. I didn't verify it specifically but there are a lot of such operations in mt76, if your operation is correct then the WiFi will simply fail to start and not just transmit power incorrectly.

@phil2sat For the EEPROM you provided, I tried to apply it to my device and it seems to work fine except that the transmit power is 2 dBm lower than my original EEPROM. But I don't think 2 dBm will have such a big impact. If you need extra gain, you can increase the value of each byte in 0x8078 ~ 0x809A (+0.5 dBm per step), but it's better not to have this value larger than 0x15 (on my device, exceeding this value can cause system instability. sky85703's maximum transmit power is only 17 dBm). By the way, what we can see from your eeprom is that transmit power will be maximized in channel 36, so just try this channel. As a final quick summary, MT7610E is a chip with lower transmission power compared to newer models such as MT7615, but it performed at least as well as the original firmware on my device. The only problem for me is not getting the true value of the transmitting power, not the low transmitting power.

theparasol commented 2 years ago

mt76x02_eeprom_get called get_unaligned_le16 (little-endian 16 bits, le16) so the upper byte of the data should be stored in the upper memory address. Read 2 bytes starting on postion D2 not get 0x1234 but 0x3412.

I beg to differ: the same get_unaligned_le16 is indeed used all over the place and is getting correct values that match with the GPL implementation, I checked too many of them and by doing this I discovered here we are getting the wrong value from the eeprom.

DragonBluep commented 2 years ago

@theparasol Sorry for my heavy words, maybe we can do a little experiment to test it. First, this is the original eeprom and Tx power. 2022-04-24 202205

root@OpenWrt:~# iwinfo phy0 info
phy0      ESSID: unknown
          Mode: Master  Channel: 36 (5.180 GHz)
          Center Channel 1: 42 2: unknown
          Tx-Power: 12 dBm  Link Quality: unknown/70
          Signal: unknown  Noise: unknown
          Bit Rate: unknown
          Encryption: unknown
          Type: nl80211  HW Mode(s): 802.11nac
          Hardware: 14C3:7650 14C3:7650 [MediaTek MT7610E]
          TX power offset: none
          Frequency offset: none
          Supports VAPs: yes  PHY name: phy0

Then I changed the value at 0xd3 from 0x81 to 0x89. 2022-04-24 210751

root@OpenWrt:~#  iwinfo phy0 info
phy0      ESSID: unknown
          Mode: Master  Channel: 36 (5.180 GHz)
          Center Channel 1: 42 2: unknown
          Tx-Power: 8 dBm  Link Quality: unknown/70
          Signal: unknown  Noise: unknown
          Bit Rate: unknown
          Encryption: unknown
          Type: nl80211  HW Mode(s): 802.11nac
          Hardware: 14C3:7650 14C3:7650 [MediaTek MT7610E]
          TX power offset: none
          Frequency offset: none
          Supports VAPs: yes  PHY name: phy0

We can find that when configured as the default channel and the default tx power, its tx power is reduced by 4 dBm. signed(81h-89h) / 2 = 4 dBm. This indicates that the driver got the correct value from 0xd3.

MT7610E-EEPROMContentv06.pdf Hope this document is helpful. I feel that only mt7610‘s transmit power is abnormal.

I uploaded a reference document a few months ago and it looks like the register definitions are fine as well.

theparasol commented 2 years ago

@DragonBluep Your findings are correct due to this method:

MT_EE_5G_TARGET_POWER = 0x0D2h

if (mt76x0_tssi_enabled(dev)) {
        s8 target_power;

        if (chan->band == NL80211_BAND_5GHZ)
            data = mt76x02_eeprom_get(dev, MT_EE_5G_TARGET_POWER);
        else
            data = mt76x02_eeprom_get(dev, MT_EE_2G_TARGET_POWER);
        target_power = (data & 0xff) - dev->mt76.rate_power.ofdm[7];
        *tp = target_power + mt76x0_get_delta(dev);

        return;
    }

so (data & 0xff) = 0x00d3h => correct!

but if we follow the code: mt76x0_get_delta(dev) then we hit the wrong eeprom value read:

that should be

static s8 mt76x0_get_delta(struct mt76x02_dev *dev)
{
    struct cfg80211_chan_def *chandef = &dev->mphy.chandef;
    u8 val;

    if (chandef->width == NL80211_CHAN_WIDTH_80) {
        val = mt76x02_eeprom_get(dev, MT_EE_TSSI_BOUND1) >> 8;
    } else if (chandef->width == NL80211_CHAN_WIDTH_40) {
        u16 data;

        data = mt76x02_eeprom_get(dev, MT_EE_TX_POWER_DELTA_BW40);
        if (chandef->chan->band == NL80211_BAND_5GHZ)
            val = data >> 8;
        else
            val = data;
    } else {
        return 0;
    }

    return mt76x02_rate_power_val(val);
}

So the delta power component is calculated wrong (for some devices). but target power is correct. lets say:

target power = 100 (= read correct) delta power = 20 (= read wrong) 100-20 = 80

you change 100 to 80 80-20 = 60 Power decreases also! But its no proof that the complete powercalculation is done correct.

In your case right now 0x1Ah is read. thats "00011010" Bit 7 is not set => in your case delta power is off / 0 and nothing is substracted or added from power. So only the target power that is calculated correctly is used in the power calculations.

A WR902-AC eeprom has on 0x00d2h value 20 and on 0x00d4h value 40 (==same as your device!) If we read the correct value of 40, bit 7 is set but the resulting delta power is still 0 since all other less significant bits give still zeros. So everything is fine for our devices even if we improve the code.

But for some MT7610 based devices with other value than 40 they will get additional power added or substracted. Right now if for whatever reason Bit 7 is set on the value in 0x082 than power control for that device is borked. So with my code change proposal your and mine device for example are not affected but some others will benefit for sure from it.

yesrab commented 2 years ago

anyone tried openwrt 21.02.3? the issue is still present on c20 v4.

chinghanyu commented 2 years ago

@DragonBluep and @theparasol, appreciated for the hard work. I would like to check if you have gone through mt76x0_get_power_info() function in eeprom.c? According to @phil2sat's test, negating the if condition helps but that was a hack. Good news is that we know the cause might be in the following codes.

` for (i = 0; i < ARRAY_SIZE(chan_map); i++) { if (chan->hw_value <= chan_map[i].chan) { idx = (chan->hw_value == chan_map[i].chan); // iterate over the chan_map and find the smallest channel offset = chan_map[i].offset; // number that is greater than or equal to the input channel break; // (chan->hw_value), if the equality holds, set idx = true } }

if (i == ARRAY_SIZE(chan_map))                      // this seems buggy to me, if the input channel is 175,
    offset = chan_map[0].offset;                    // because 175 is the last key, i == ARRAY_SIZE(chan_map)
                                                    // holds and the offset would be 0, which I think is incorrect.

if (chan->band == NL80211_BAND_2GHZ) {              // this is OK and we have no problem with 2 GHz band
    addr = MT_EE_TX_POWER_DELTA_BW80 + offset;
} else {
    switch (chan->hw_value) {                          
    case 42:
        offset = 2;                                 // for channel 42, the for loop above would stop with i = 9,
        break;                                      // chan = 44, and offset = 2, no need to set offset here
    case 58:
        offset = 8;
        break;
    case 106:
        offset = 14;
        break;
    case 122:
        offset = 20;
        break;
    case 155:
        offset = 30;
        break;
    default:
        break;
    }
    addr = MT_EE_TX_POWER_0_GRP4_TSSI_SLOPE + 2 + offset;   // I need more time to understand this line
}

data = mt76x02_eeprom_get(dev, addr);
*tp = data >> (8 * idx);                            // oh, here comes the idx, if chan->hw_value is not
if (*tp < 0 || *tp > 0x3f)                          // found in chan_map, it will be zero; otherwise 1
    *tp = 5;                                        // it looks to me that chan_map only gives the offset
                                                    // if one out of every two channels. If found in
                                                    // chan_map, pick the higher 8 bits; otherwise,
                                                    // the lower 8 ones. Finally, set the target power to
                                                    // 5 if it is too large or too small.`

I think we can hard code *tp to some fixed value so that we can tell if the logic is wrong or the content of the EEPROM is wrong.

DragonBluep commented 2 years ago

image @chinghanyu As you can see, the max channel number is 165, so we need not care channel 175 problem. In fact, the entire power reading function is correct in mt7610. For 80 BW:

txpower = channel power + Max( rate power ) + delta
channel power = eep@ 0x78~0x9a
rate power = eep@ 0x120 ~ 0x12d, 6 bit signed value
delta = eep@ 0xd3, signed, can only be a negative number

The only thing I'm not sure about is that the unit of channel power is 0.5 db/step or 1 db/step. Usually if it is 0.5 db/step it will be marked in the eeprom content but I don't see it here. I'm guessing the unit might be 1 db/step so I created #665.

I feel there may be some problems in void mt76x0_phy_set_txpower(struct mt76x02_dev *dev) and void mt76x02_phy_set_txpower(struct mt76x02_dev *dev, int txp_0, int txp_1), if you are interested, maybe you can compare the GPL driver.

chinghanyu commented 2 years ago

@DragonBluep Thanks for the clarification. Those two functions are also used for setting 2 GHz TX power and we have little issue with 2 GHz. Mine is a 7610E.

DragonBluep commented 2 years ago

2022-04-23 11-42-26 I did some simple tests and it seems that the real transmit power of the MT7610E is correct, although the displayed value on the LuCI interface is very low (about 9-12dBm in different channels). The router has a SKY85703-11 FEM chip.

Another point of concern, in my eeprom, the transmit power of the 5.2 GHz band is significantly higher than that of 5.8 GHz. image But in the Padavan firmware (GPL driver), there is not much difference in the transmit power of the two frequency bands. Maybe I'm mistaken, the unit of channel power is indeed 0.5 db/step. So #665 is completely wrong.

chinghanyu commented 2 years ago

@DragonBluep it looks like Padavan firmware uses MTK's upstream driver rather than the OpenWRT mt76 driver. So, it is not a surprise that Padavan firmware performs the same as the stock firmware. Please correct me if I am wrong.

chinghanyu commented 2 years ago

@DragonBluep the TX power section in my TP-Link RE220v2 is different from yours but follows the same trend. Here is mine. tx_power

chinghanyu commented 2 years ago

@DragonBluep, I checked the TX power setting in the GPL driver. It looks like OpenWRT driver missed the higher two bytes 0x13b2 and 0x13b3.

In the GPL driver, it does the following,

  1. reads the 32 bits (0x13b0-0x13b3) from the registers
  2. clear the lower 16 bits by using 0x3f3f mask (0x13b0-0x13b1)
  3. set TxPwer (a char) to the lower 16 bits
  4. set 0x2f2f to the higher 16 bits (0x13b2-0x13b3)
  5. write the 32 bits back

In OpenWRT driver, the logic is as follows,

  1. write txp0 to 0x13b0 with mask MT_TX_ALC_CFG_0_CH_INIT_0 (0x3f)
  2. write txp1 to 0x13b0 with mask MT_TX_ALC_CFG_0_CH_INIT_1 (0x3f00, write to 0x13b1 because of the mask)

void mt76x0_phy_set_txpower(struct mt76x02_dev *dev) function will plug s8 info to both txp0 and txp1 and this is OK because info has only 8 bits and will become zero after applying a 0x3f00 mask. So 1. and 2. have the same logic as that in the GPL driver.

0x13b2 and 0x13b3 are untouched in OpenWRT driver but are set to 0x2f in the GPL driver. I guess we should try setting 0x2f to 0x13b2 and 0x13b3.

chinghanyu commented 2 years ago

I checked the GPL driver and almost confirm that it has 0x2f set to register 0x13b2 and 0x13b3 for all MT76x0 devices in both AP and STA modes whereas there is no such requirement for MT76x2 devices. Power settings are seperated for MT76x0 and MT76x2 in the GPL driver.

In OpenWRT driver, these two chips share the same power setting routine in void mt76x02_phy_set_txpower(struct mt76x02_dev *dev, int txp_0, int txp_1) so MT76x0 devices will miss the above mentioned settings. I read through the thread and documented that the devices in question are: TP-Link Archer C2 AC750, TP-Link Archer C20 V4, TP-Link RE200v2, and TP-Link RE220v2 with MT7610E/MT7610EN as their 2nd Wi-Fi SoC.

I have patched the codes and will see if that helps my TP-Link RE220v2.

chinghanyu commented 2 years ago

Guys, after setting 0x2f to registers 0x13b2 and 0x13b3 on my MT7610E, I got a satisfying result and could maintain connection with my TP-Link RE220v2 at -65 dBm on a different floor.

I plan to do some more stress tests. Should everything goes fine, I will submit a pull request.

phil2sat commented 2 years ago

@chinghanyu, whats aubout the visible txpower, what shows iw and luci with your patch and what did it show without your patch? is the full 5gjz band usable? was it usable before? - 65dbm sounds nice, what was the value before? are u able to connect on low 36 to 58 and alsi 100 to 149 or maybe 165 channels? maybe upload your radio partition to compare, sounds too nice.

theparasol commented 2 years ago

@chinghanyu great job! I'm still waiting for my two ordered tp-link WR902AC to arrive but according to the carrier they still seem to be lost somewhere in transit. I got a full refund of the reseller and ordered two Mikrotik RBSXTsqG-5acD from a local reseller that arrived the next day. Hope the lost tp-links will eventually turn up and get delivered anyway so I'm able to test myself and contribute to improve the mt76x0 drivers.

DragonBluep commented 2 years ago

I was even more confused, I checked at the value of the TX_ALC_CFG_0 register under the GPL driver and the mt76 driver, both are equivalent on my device (the mt7610 doesn't seem to need bits 8-15, so just ignore the second byte).

Padavan GPL Driver TX_ALC_CFG_0 Value (CH44):

Jan  1 00:00:14 kernel: FILE: drivers/net/wireless/ralink/mt7610_ap/../mt7610/chips/mt76x0.c, LINE: 2195, TX_ALC_CFG_0: 2f2f0011
Jan  1 00:00:14 kernel: FILE: drivers/net/wireless/ralink/mt7610_ap/../mt7610/chips/mt76x0.c, LINE: 1997, TX_ALC_CFG_0: 2f2f0011
Jan  1 00:00:14 kernel: FILE: drivers/net/wireless/ralink/mt7610_ap/../mt7610/chips/mt76x0.c, LINE: 4336, TX_ALC_CFG_0: 0
Jan  1 00:00:14 kernel: FILE: drivers/net/wireless/ralink/mt7610_ap/../mt7610/chips/mt76x0.c, LINE: 4371, TX_ALC_CFG_0: 2f2f0011

OpenWRT mt76 (2022-04-30) MT_TX_ALC_CFG_0 Value (CH44):

[  140.575840] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt7620/mt76-2022-04-30-46fb1a71/mt76x02_phy.c, LINE: 99, MT_TX_ALC_CFG_0: 2f2f0f0f
[  140.715836] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt7620/mt76-2022-04-30-46fb1a71/mt76x02_phy.c, LINE: 99, MT_TX_ALC_CFG_0: 2f2f1212
[  140.748421] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt7620/mt76-2022-04-30-46fb1a71/mt76x0/phy.c, LINE: 886, MT_TX_ALC_CFG_0: 0
[  140.872259] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt7620/mt76-2022-04-30-46fb1a71/mt76x0/phy.c, LINE: 909, MT_TX_ALC_CFG_0: 2f2f1212
[  140.963816] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt7620/mt76-2022-04-30-46fb1a71/mt76x02_phy.c, LINE: 99, MT_TX_ALC_CFG_0: 2f2f1111
[  141.058708] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt7620/mt76-2022-04-30-46fb1a71/mt76x0/phy.c, LINE: 886, MT_TX_ALC_CFG_0: 0
[  141.185143] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt7620/mt76-2022-04-30-46fb1a71/mt76x0/phy.c, LINE: 909, MT_TX_ALC_CFG_0: 2f2f1111
[  141.249321] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt7620/mt76-2022-04-30-46fb1a71/mt76x02_phy.c, LINE: 99, MT_TX_ALC_CFG_0: 2f2f1111

Is there such a reason that there are different revisions of mt7610, and there are slight differences in the way of control. This may be the reason why the transmit power on my router is not high, but the performance is consistent with the original firmware, but the signal is obviously weak on some other devices. Can you check what the value of this register is without adding your "0x2f patch"? @chinghanyu Adding this code prints its value in the log:

dev_info(dev->mt76.dev, "FILE: %s, LINE: %d, MT_TX_ALC_CFG_0: %lx",
    __FILE__, __LINE__, mt76_get_field(dev, MT_TX_ALC_CFG_0, GENMASK(31, 0)));

I checked the GPL driver and almost confirm that it has 0x2f set to register 0x13b2 and 0x13b3 for all MT76x0 devices in both AP and STA modes whereas there is no such requirement for MT76x2 devices.

In void mt76x02_phy_set_txpower(struct mt76x02_dev *dev, int txp_0, int txp_1), it uses masks when reading and writing registers. If the initial value of the 0x13b2 and 0x13b3 registers is 0x2f, it will always maintain this value, so there is no operation of writing 0x2f2f in mt76.

#define MT_TX_ALC_CFG_0_CH_INIT_0   GENMASK(5, 0)
#define MT_TX_ALC_CFG_0_CH_INIT_1   GENMASK(13, 8)

The initial value of MT_TX_ALC_CFG_0 (0x13b0 - 0x13b4) is defined here, but I am not sure if it is written on initialization. https://github.com/openwrt/mt76/blob/784c27b159b98740049e3b7c6751f773017a1016/mt76x0/initvals_init.h#L62

chinghanyu commented 2 years ago

@DragonBluep appreciated your comments. It was late last night when I recovered my half-bricked RE220v2 after flashing the my self-compiled sysupgrade.bin.

In addition to the 0x2f patch, I also applied the TSSI check empty EEPROM patch @theparasol mentioned. So I am not quite sure which patch contributes to the TX power increase.

BTW, is there a way to build mt76 package independently? I tried following the developer guide but the build script says there is a dependency error. It depends on a GPIO module and that might be used for LED control.

DragonBluep commented 2 years ago

In addition to the 0x2f patch, I also applied the TSSI check empty EEPROM patch @theparasol mentioned. So I am not quite sure which patch contributes to the TX power increase.

This reminds me of an interesting thing, when checking @phil2sat 's eeprom, I found that his eeprom has a TSSI calibration value (eep@0xf0~0xff), but the Internal TX ALC control bit (eep@0x37: bit 5) is disabled. In contrast, my eeprom does not have TSSI calibration values and does not have Internal TX ALC enabled.This document may help you understand TSSI:

MT7610E-EEPROMContentv06.pdf

Besides that, I also noticed that TP RE200 has some unusual values at Reserved for Customer (eep@0x100~0x10f).

phil2sat's eeprom ![2022-04-30 22-45-13](https://user-images.githubusercontent.com/70847398/166110793-f8ac5b65-e782-4bab-b359-e22e96ebdc91.png)
my eeprom ![2022-04-30 22-45-38](https://user-images.githubusercontent.com/70847398/166110864-9ba3bc30-d4cb-4a78-babd-633a43ba4752.png)

BTW, is there a way to build mt76 package independently? I tried following the developer guide but the build script says there is a dependency error. It depends on a GPIO module and that might be used for LED control.

Use make menuconfig to choose your device first to ensure mt76 is selected. And then make would work:

make package/kernel/mt76/clean
make package/kernel/mt76/compile
chinghanyu commented 2 years ago

@DragonBluep many thanks, but I still see some dependency issues. One thing I noticed is that the latest 4/30 snapshot is not stable on my RE220v2 and it crashed in 6 hours last night. I plan to use tag 21.02.3 on the openwrt-21.02 branch. My RE220v2 used to run this version for weeks without a crash but suffer low TX power as everyone here.

@phil2sat, LuCI still show low TX power around 11 dBm and iw says the same. LuCI gets these info from iwinfo through ubus.

phil2sat commented 2 years ago

@chinghanyu if u upload patches i build a rom, its snapshot from around 09.apr and runs 24/7 since i patched eeprom.c so i guess a good base, i think i could also host a repo for this but need some time

chinghanyu commented 2 years ago

@DragonBluep confirmed the following items on my RE220v2:

  1. After applying your debug print, I can see the register MT_TX_ALC_CFG_0 value change from 0x2f2f000c, 0x2f2f0c0c, and finally becomes 0x2f2f0f0f for channel 157. As I reset the channel to 44, it becomes 0x2f2f0b0b, matching what I have in the EEPROM. So, the power reading/writing parts are correct in OpenWRT driver and my patch is not necessary.
  2. LuCI gives 9 dBm TX power to channel 44, which is barely useable but gives 11 dBm to channel 157. 0x0f - 0x0b = 15 - 11 = 4 and TX power difference is 2 dBm , so 0.5 dBm/step is correct. The GPL driver also says so so I consider it correct.
  3. Some channels are not available on MT7610E but LuCI still shows. Setting these channel will make 5 GHz disabled.
  4. My EEPROM has a non-empty TSSI settings. The value of my MT_EE_NIC_CONF_1 is 0x0a.

I remember the GPL driver sets baseline power to 0x20 whenever it finds the corresponding channel power in EEPROM is 0x00 or 0xff. 0x20 - 0x0b = 32 - 11 = 21 and should gives us 9 + 21 * 0.5 = 9 + 10.5 = 19.5 dBm TX power.

chinghanyu commented 2 years ago

@DragonBluep can you help check the register TX_ALC_CFG_1's value in Padavan GPL Driver and register that of MT_TX_ALC_CFG_1 in OpenWRT driver? I noticed that OpenWRT driver only writes the default value to it and leave it untouched afterward, whereas the GPL driver will update its value during a channel switching.

chinghanyu commented 2 years ago

Added print out to mt76x0/init.c and had the following debug messages:

[   22.327102] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 36, tp: 12, chan->orig_mpwr: 10, chan->max_reg_power: 20
[   22.372108] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 40, tp: 12, chan->orig_mpwr: 10, chan->max_reg_power: 20
[   22.406891] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 44, tp: 11, chan->orig_mpwr: 9, chan->max_reg_power: 20
[   22.441500] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 48, tp: 11, chan->orig_mpwr: 9, chan->max_reg_power: 20
[   22.476110] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 52, tp: 11, chan->orig_mpwr: 9, chan->max_reg_power: 20
[   22.510728] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 56, tp: 11, chan->orig_mpwr: 9, chan->max_reg_power: 20
[   22.545341] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 60, tp: 10, chan->orig_mpwr: 9, chan->max_reg_power: 20
[   22.579960] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 64, tp: 10, chan->orig_mpwr: 9, chan->max_reg_power: 20
[   22.614572] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 100, tp: 10, chan->orig_mpwr: 9, chan->max_reg_power: 20
[   22.649357] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 104, tp: 11, chan->orig_mpwr: 9, chan->max_reg_power: 20
[   22.684141] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 108, tp: 11, chan->orig_mpwr: 9, chan->max_reg_power: 20
[   22.718927] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 112, tp: 12, chan->orig_mpwr: 10, chan->max_reg_power: 20
[   22.753882] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 116, tp: 13, chan->orig_mpwr: 10, chan->max_reg_power: 20
[   22.788837] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 120, tp: 14, chan->orig_mpwr: 11, chan->max_reg_power: 20
[   22.823792] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 124, tp: 14, chan->orig_mpwr: 11, chan->max_reg_power: 20
[   22.858746] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 128, tp: 15, chan->orig_mpwr: 11, chan->max_reg_power: 20
[   22.893701] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 132, tp: 16, chan->orig_mpwr: 12, chan->max_reg_power: 20
[   22.928658] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 136, tp: 17, chan->orig_mpwr: 12, chan->max_reg_power: 20
[   22.963615] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 140, tp: 17, chan->orig_mpwr: 12, chan->max_reg_power: 20
[   22.998569] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 144, tp: 16, chan->orig_mpwr: 12, chan->max_reg_power: 20
[   23.033524] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 149, tp: 16, chan->orig_mpwr: 12, chan->max_reg_power: 20
[   23.068479] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 153, tp: 16, chan->orig_mpwr: 12, chan->max_reg_power: 20
[   23.103434] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 157, tp: 15, chan->orig_mpwr: 11, chan->max_reg_power: 20
[   23.138390] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 161, tp: 15, chan->orig_mpwr: 11, chan->max_reg_power: 20
[   23.173346] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 165, tp: 15, chan->orig_mpwr: 11, chan->max_reg_power: 20
[   23.208301] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 169, tp: 5, chan->orig_mpwr: 6, chan->max_reg_power: 0
[   23.242741] mt76x0e 0000:01:00.0: FILE: target-mipsel_24kc_musl/linux-ramips_mt76x8/mt76-2021-12-03-678071ef/mt76x0/init.c, LINE: 234, chan: 173, tp: 5, chan->orig_mpwr: 6, chan->max_reg_power: 0

Apparently, the per-channel target_power (tp) is given by the settings in the EEPROM and mt76x02_get_max_rate_power(&t) can be deduced by the function.

Mine is

                Frequencies:
                        * 5180 MHz [36] (10.0 dBm)
                        * 5200 MHz [40] (10.0 dBm)
                        * 5220 MHz [44] (9.0 dBm)
                        * 5240 MHz [48] (9.0 dBm)
                        * 5260 MHz [52] (9.0 dBm) (radar detection)
                        * 5280 MHz [56] (9.0 dBm) (radar detection)
                        * 5300 MHz [60] (9.0 dBm) (radar detection)
                        * 5320 MHz [64] (9.0 dBm) (radar detection)
                        * 5500 MHz [100] (9.0 dBm) (radar detection)
                        * 5520 MHz [104] (9.0 dBm) (radar detection)
                        * 5540 MHz [108] (9.0 dBm) (radar detection)
                        * 5560 MHz [112] (10.0 dBm) (radar detection)
                        * 5580 MHz [116] (10.0 dBm) (radar detection)
                        * 5600 MHz [120] (11.0 dBm) (radar detection)
                        * 5620 MHz [124] (11.0 dBm) (radar detection)
                        * 5640 MHz [128] (11.0 dBm) (radar detection)
                        * 5660 MHz [132] (12.0 dBm) (radar detection)
                        * 5680 MHz [136] (12.0 dBm) (radar detection)
                        * 5700 MHz [140] (12.0 dBm) (radar detection)
                        * 5720 MHz [144] (12.0 dBm) (radar detection)
                        * 5745 MHz [149] (12.0 dBm)
                        * 5765 MHz [153] (12.0 dBm)
                        * 5785 MHz [157] (11.0 dBm)
                        * 5805 MHz [161] (11.0 dBm)
                        * 5825 MHz [165] (11.0 dBm)
                        * 5845 MHz [169] (6.0 dBm) (no IR)
                        * 5865 MHz [173] (6.0 dBm) (no IR)

Bad news, I just bricked my RE220v2 and it stocks at u-boot I guess. TP-Link made it difficult to unbox it and use a TTL cable to check.

yesrab commented 2 years ago

all this stuff is going over my head, but yall let me know if there is something needed to be done/tested on tp-link archer c20 v4

phil2sat commented 2 years ago

@chinghanyu know it, happened the same in the beginning, did this: 1651389018406 Case Mod made by Knippex.

For serial i crossed cables and used a simple Raspberry PI, Pins: 8tx ,9gnd,10rx. actually im usin it in a self printed outdoor case that fits on a pole

DragonBluep commented 2 years ago

@chinghanyu It looks like the difference is very small, probably the delta at eep@0xd3 and eep@0x50 makes the difference. 3f(Hex) = -1(Dec). A little curious if these registers can accept negative numbers? High probability it is.

Padavan GPL (CH44):
TX_ALC_CFG_0: 2f2f0011      TX_ALC_CFG_1: 89040000
TX_PWR_CFG_0: 07070000      TX_PWR_CFG_1: 07070004
TX_PWR_CFG_2: 00000004      TX_PWR_CFG_3: 00000000
TX_PWR_CFG_4: 00000000
TX_PWR_CFG_8: 3e3e0000

OpenWRT mt76 (CH44):
MT_TX_ALC_CFG_0: 2f2f1111   MT_TX_ALC_CFG_1: 89040000
MT_TX_PWR_CFG_0: 06063f3f   MT_TX_PWR_CFG_1: 06063f03
MT_TX_PWR_CFG_2: 3f3f3f03   MT_TX_PWR_CFG_3: 3f3f3f3f
MT_TX_PWR_CFG_4: 00003f3f   MT_TX_PWR_CFG_7: 003f003f
MT_TX_PWR_CFG_8: 3e3e003f   MT_TX_PWR_CFG_9: 3f3f003f

By the way, /2 can be replaced with the more elegant DIV_ROUND_UP(), which sometimes increases power by 1dB. https://github.com/openwrt/mt76/blob/784c27b159b98740049e3b7c6751f773017a1016/mt76x0/init.c#L230

DragonBluep commented 2 years ago

Through the inspection of the mt76 driver, I began to think that the low transmit power problem of mt7610 in some devices may be caused by the fact that the FEM is not properly enabled. This is the level of my FEM chip (SKY85703), H=3.3v, L≈0v. If Anyone who is interested can compare. image sky85703

Use iperf3 for download and upload test. If the voltage of LNA_EN and PA_EN can reach 2v + and the power supply VCC/VDD= 3.3v, then FEM is working normally.

chinghanyu commented 2 years ago

@phil2sat Yup, I knew that will happen but did not expect it happened so fast. I thought tag 21.02.3 on openwrt-21.02 branch should be stable enough so I did not bother to reflash my RE220v2 every time when I add new debug print outs. Good news is that it is still under warranty so I might be able to ask for a replacement but do not guarantee the replacement will be the same model so I decided to by a renewed Archer C20, hopefully it would be a v4 for me to dig in.

Noted that TP-Link Archer A5 uses a MT7612E for its 5 GHz band and support up to AC1200.

@DragonBluep, thanks for the pointer and I will let you know after I receive my Archer C20. The v4 version should have the same FEM SKY85703 as yours.

Now we have two different issues:

  1. TX power is not calculated properly in the OpenWRT driver so iw, iwinfo, and LuCI get the wrong numbers. I have not yet check if TX power setting actually work. I would be grateful if anyone can do a quick test: set channel to 157 and TX power to 11 dBm, check the bandwidth; set TX power to 7 or 9 dBm and check if the signal is actually weaker.
  2. FEM chip might not be enabled properly, the datasheet says the chip offers +16 dBm boost in 5 GHz band. If we add that number to those we see in iwinfo and cap them at 20 dBm. The signal should be good enough.
DragonBluep commented 2 years ago
  1. TX power is not calculated properly in the OpenWRT driver so iw, iwinfo, and LuCI get the wrong numbers. I have not yet check if TX power setting actually work. I would be grateful if anyone can do a quick test: set channel to 157 and TX power to 11 dBm, check the bandwidth; set TX power to 7 or 9 dBm and check if the signal is actually weaker.

For the MT7610, although not in the way I expected, the power adjustment function is effective and it takes about 30 seconds to take effect. My 5.8GHz channel was still unavailable, so I tested channel 36.

CH36 Tx power 12dBm 8dbm 4dBm 0dBm
op v19.07.10 -41 -43 -47 -52
op master -40 -43 -48 -52
Tx power 12 dBm 8 dBm 4dBm 0 dBm
MT_TX_ALC_CFG_0 2f2f1212 2f2f1212 2f2f1212 2f2f1212
MT_TX_ALC_CFG_1 89040000 89040000 89040000 89040000
MT_TX_PWR_CFG_0 06063f3f 3e3e3e3e 36363636 2e2e2e2e
MT_TX_PWR_CFG_1 06063f03 3e3e3e3e 36363636 2e2e2e2e
MT_TX_PWR_CFG_2 3f3f3f03 3e3e3e3e 36363636 2e2e2e2e
MT_TX_PWR_CFG_3 3f3f3f3f 3e3e3e3e 36363636 2e2e2e2e
MT_TX_PWR_CFG_4 00003f3f 00003e3e 00003636 00002e2e
MT_TX_PWR_CFG_7 003f003f 003e003e 00360036 002e002e
MT_TX_PWR_CFG_8 3e3e003f 3e3e003e 36360036 2e2e002e
MT_TX_PWR_CFG_9 3f3f003f 3e3e003e 36360036 2e2e002e
Additional comparison with MT7612: Router1: MT7620 + MT7610 (OpenWrt) Router2: MT7628 + MT7612 (Padavan) Experimental conditions: a 95cm thick concrete wall separated && channel 36 maximum Tx power MT7620 MT7628 MT7610 MT7612
-42dBm -42dBm -55dBm -56dBm

The Tx power of MT7610 on my HW-L1W is indeed normal, and although it shows a small value (12dBm) in LuCI, it behaves the same as the MT7612.

chinghanyu commented 2 years ago

@DragonBluep many thanks for the providing register values. As far as I know, MediaTek disables all the DFS channels (52-144). Channel 161 and 165 are not very stable and the highest stable one is 157.

My newly ordered Archer C20 will arrive in a week and I will do some more code tracing and see if I can uncover the correct logic of TX power setting for MT76x0.

chinghanyu commented 2 years ago

So register MT_TX_ALC_CFG_0 is the per-channel target power read from the EEPROM. It will not change if we set to reduce the TX Power. In my RE220v2, EEPROM address 0x8078 is 0x0c == 12 and the maximum rate power is 8 so its chan->orig_mpwer is (12 + 8) / 2 = 10. In. @DragonBluep's case, your EEPROM address 0x8078 is 0x12 == 18. The maximum rate power should be 8 also, resulting in your chan->orig_mpwer = (18 + 8) / 2 = 13.

As you pointed out, the actual TX power depends on register MT_TX_PWR_CFG_[0-9]. The GPL driver sets them here.