Skip to content

wifi: mt76: mt7615: fix MT7663 PCIe embedded EEPROM loading#1063

Open
davkdavk wants to merge 2 commits intoopenwrt:masterfrom
davkdavk:mt7663-pcie-eeprom-fix
Open

wifi: mt76: mt7615: fix MT7663 PCIe embedded EEPROM loading#1063
davkdavk wants to merge 2 commits intoopenwrt:masterfrom
davkdavk:mt7663-pcie-eeprom-fix

Conversation

@davkdavk
Copy link

@davkdavk davkdavk commented Mar 8, 2026

Summary

  • fix MT7663 PCIe boards that store the WiFi EEPROM image inside the factory partition at offset 0x8000
  • use an early PCI probe flag for PCI ID 14c3:7663 so the fallback does not depend on EEPROM contents
  • fall back to reading the full factory partition (or mtd2) when mediatek,mtd-eeprom is not present

Problem

On a Wavlink WL-WN575A3 Rev B running OpenWrt 25.12.0, the MT7663 PCIe radio (PCI ID 14c3:7663) was loaded by mt7615e, but the driver read an empty or invalid EEPROM image from the default path.

The actual MT7663 EEPROM image is embedded in the factory partition at offset 0x8000.

Because the driver did not load that embedded image:

  • the MAC address was invalid and randomized on every boot
  • the firmware received incorrect EEPROM data
  • 5 GHz throughput was severely degraded

EEPROM analysis

Observed layout in factory:

  • partition: factory (mtd2)
  • size: 0x10000
  • MT7663 EEPROM image offset: 0x8000
  • MT7663 header at 0x8000: 0x7663
  • MAC at 0x8004: 80:3f:5d:33:90:32

Before

dmesg:

mt7615e 0000:01:00.0: Invalid MAC address, using random address ...

Observed throughput:

  • ~11 Mbps down
  • ~45 Mbps up

After

The driver now:

  • detects the MT7663 PCIe variant from PCI probe
  • reads the full factory partition when the DT lacks mediatek,mtd-eeprom
  • loads the embedded EEPROM image from 0x8000

Observed validation log:

mt7663 debug: reg_map=mt7663 rev=0x76630010 chip=0x7663 initial header=0x0000 mac=00:00:00:00:00:00
mt7663 debug: fallback probe enabled for embedded EEPROM
mt7663 debug: mediatek,mtd-eeprom missing, reading full factory partition
mt7663 debug: probe offset 0x8000 header=0x7663 mac=80:3f:5d:33:90:32
found embedded MT7663 EEPROM at offset 0x8000

Observed results:

  • correct stable MAC address: 80:3f:5d:33:90:32
  • 5 GHz throughput improved from ~11 Mbps to ~84 Mbps

Notes

This change is targeted at MT7663 PCIe boards whose EEPROM is embedded in factory at 0x8000 and that do not expose the usual mediatek,mtd-eeprom binding.

davkdavk added 2 commits March 8, 2026 21:46
Some MT7663 PCIe boards store the WiFi EEPROM image inside the factory
partition at offset 0x8000 instead of exposing it through the usual
mediatek,mtd-eeprom binding. Record the PCI probe result early and fall
back to reading the full factory/mtd2 partition so the driver can load
the embedded 0x7663 EEPROM image with the correct MAC address and power
calibration data.

Signed-off-by: David Kearsley <thadavhjb@gmail.com>
MT7663 currently bypasses the computed per-rate power limits when
building the MCU SKU table and fills every entry with a flat txpower
value. Drop that special case so the firmware receives the EEPROM-derived
OFDM/HT/VHT power limits that are already parsed by the driver.

Signed-off-by: David Kearsley <thadavhjb@gmail.com>
@Djfe
Copy link

Djfe commented Mar 15, 2026

Just wondering, since I'm not a maintainer:
Can't the EEPROM loading be fixed within the DTS? I mean it already specifies the offset of 0x8000.
https://github.com/openwrt/openwrt/blob/7824dbcab815a6fa605b6cecf94c200b9d3973f7/target/linux/ramips/dts/mt7628an_wavlink_wl-wn575a3.dts#L113

please send patches to mt76 to the linux kernel wireless mailing list
This github repo does not merge pull requests at all.

see for examples:
https://patchwork.kernel.org/project/linux-wireless/list/?order=date&state=*

@Djfe
Copy link

Djfe commented Mar 15, 2026

@davkdavk
Copy link
Author

davkdavk commented Mar 15, 2026 via email

@Djfe
Copy link

Djfe commented Mar 15, 2026

weird, why does the driver not look at the offset that is defined in the nvmem partition (0x8000)? @neheb @Ansuel do you maybe have an idea? (sorry to bother you but you worked on the nvmem implementation for eeprom/calibration data iirc)

@Djfe
Copy link

Djfe commented Mar 15, 2026

In the meantime: could you upload the factory partition to github maybe? (zipped img file or so)

@neheb
Copy link
Contributor

neheb commented Mar 15, 2026

Sounds like a bug. Nvmem eeprom loading works absolutely fine.

@davkdavk
Copy link
Author

davkdavk commented Mar 16, 2026 via email

@davkdavk
Copy link
Author

davkdavk commented Mar 16, 2026 via email

@neheb
Copy link
Contributor

neheb commented Mar 16, 2026

Instead of this hack solution, please use nvmem. It's already implemented.

@davkdavk
Copy link
Author

davkdavk commented Mar 16, 2026 via email

@davkdavk
Copy link
Author

davkdavk commented Mar 16, 2026 via email

@Djfe
Copy link

Djfe commented Mar 17, 2026

@neheb the dts for the device already gets it from nvmem using the 0x8000 offset which is why I was confused why a custom function should be necessary.
https://github.com/openwrt/openwrt/blob/7824dbcab815a6fa605b6cecf94c200b9d3973f7/target/linux/ramips/dts/mt7628an_wavlink_wl-wn575a3.dts#L68

@davkdavk great find

according to this it's 0x600, I think. (1536)
The thing is: that is just the maximum length that should not be exceeded, no?
how large is the section in the factory partition on the flash of your wavlink actually? (the section that starts at 0x8000 within that partition)
If it's not larger than 0x200 (defined in the dts) then it should be fine

@neheb
Copy link
Contributor

neheb commented Mar 17, 2026

So the actual bug is

					eeprom_factory_8000: eeprom@8000 {
						reg = <0x8000 0x200>;
					};

needs to be 600.

openwrt/openwrt@65cd6a6

says it's 4da8.

ping @DragonBluep

@DragonBluep
Copy link

So the actual bug is

					eeprom_factory_8000: eeprom@8000 {
						reg = <0x8000 0x200>;
					};

needs to be 600.

openwrt/openwrt@65cd6a6

says it's 4da8.

ping @DragonBluep

Yes. If you are interested, you can insert some debugging code into mt76 to print its size len.

mt76/eeprom.c

Line 154 in d2b1e1a

static int mt76_get_of_eeprom(struct mt76_dev *dev, void *eep, int len)

@neheb
Copy link
Contributor

neheb commented Mar 17, 2026

git grep 0x8000\ 0x | grep -v 0x200 | grep -v 0x4da8
dts/mt7628an_yuncore_cpe200.dts:						reg = <0x8000 0x600>;

sounds like that's wrong then.

@DragonBluep
Copy link

git grep 0x8000\ 0x | grep -v 0x200 | grep -v 0x4da8
dts/mt7628an_yuncore_cpe200.dts:						reg = <0x8000 0x600>;

sounds like that's wrong then.

Please PR to fix them. Incorrect eeprom size can result in very low tx power, about 3 dBm. Acked-by: Shiji Yang <yangshiji66@outlook.com>.

@davkdavk
Copy link
Author

davkdavk commented Mar 17, 2026 via email

@neheb
Copy link
Contributor

neheb commented Mar 17, 2026

openwrt/openwrt#22463

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants