mt7915: MT7916 LED never lights — init_led_mux() matches 0x7916, chip ID is 0x7906
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 1-2 days
- Newbie friendliness
- 56/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Active
- Tech stack
- c, linux
- Domain
- embedded-iot
Research direction
Start with drivers/net/wireless/mediatek/mt76/mt7915/init.c, especially mt7915_init_led_mux() and the LED polarity setup. Check how the driver identifies the MT7916 PCI device and configures LED pins for PCIe devices without a device tree node. The reported mux and polarity behavior should be corrected while preserving boards with different LED wiring, then verified on MT7916 hardware.
Written by the indexing model from the issue text.
Description
I built a small x86 router (Intel N100, NixOS) and put an AsiaRF AW7916-NPD in it — MT7916 on a mini-PCIe card, through AsiaRF's own ACPCX1-M01 PCIe-to-mPCIe adapter. Everything works great with mt7915e: AP mode, both bands, WPA3, beamforming, no complaints at all. The only thing that never worked was the Wi-Fi LED on the adapter. It stayed dark no matter what was written to /sys/class/leds/mt76-phy*.
I first assumed the module simply doesn't route the LED, but the adapter traces go straight to the mPCIe connector, so I followed the signal from sysfs down to the pins. It turned out to be two small things in the driver; with both fixed the LED now blinks with traffic exactly like an Ethernet port LED. Details below, in case they are useful. How to fix it properly is of course up to you.
Setup
- Card: AsiaRF AW7916-NPD (MT7916AN + MT7976DN), PCI ID
14c3:7906, DBDC (phy0 2.4 GHz, phy1 5 GHz) - Host: Intel N100 (x86_64), no device tree
- Kernel: 7.2.10, in-tree
mt7915e,CONFIG_MT76_LEDS=y - The LED code in
mt7915/init.cis identical in v6.12, v7.2 and current openwrt/mt76 master; I also found no change to it in mediatek/mtk-openwrt-feeds (snapshot of 2026-10-14)
1. LED GPIO mux is never written for MT7916
mt7915_init_led_mux() switches on mt76_chip(&dev->mt76) and has case 0x7916: in all three branches. But mt76_chip() returns the PCI device ID, which is 0x7906 for MT7916 — that is what is_mt7916() compares against, and what mt7915_mmio_probe() uses to select the register map. So no case matches, and the mux stays at its reset value.
(case 0x7916 is correct in mt7915_check_eeprom(), because that one compares the ID stored in the EEPROM, which really is 0x7916 — maybe that is where the constant came from.)
What the card shows via debugfs (regidx/regval):
| register | address | expected from code | actual |
|---|---|---|---|
MT_LED_GPIO_MUX1 |
0x70005054 |
0x33000000 |
0x00000000 |
MT_LED_EN(0/1) |
0x18013040/44 |
1 | 1 |
MT_LED_CTRL(1) |
0x18013004 |
BAND |
0x10 |
The LED controller is configured correctly; only the pin mux is missing. Sanity checks: MT_HW_REV reads 0x8a00, writing MUX1 reads back, and a full chip reset via sys_recovery (which goes through mac_init() → init_led_mux() again) leaves MUX1 at 0. Writing 0x33000000 by hand makes the LED light up immediately.
I also checked each field separately: GPIO 14 (MUX1[27:24] = 3) outputs LED channel 0, GPIO 15 (MUX1[31:28] = 3) outputs channel 1, so the values in the MT7916 branch are right — only the case label is wrong. On this module both GPIOs go to the same LED_WLAN# pin (44) through a dual diode (D2 on the board), so enabling both, as the DBDC branch does, is fine here.
2. Polarity is inverted on PCIe cards without a DT node
With the mux fixed, the LED is inverted: brightness 0 lights it, 255 turns it off, and phyNtpt shows a steady glow with short dark blips.
The mini-PCIe LED_WLAN# / LED_WWAN# / LED_WPAN# lines are active-low by spec. On this adapter each LED is wired anode → 330 Ω → 3.3 V, cathode → the mPCIe pin, so the card has to pull the pin low to light it. The driver sets MT_LED_CTRL_POLARITY only when leds.al is set, and that comes only from led-active-low in the device tree, which a PCIe card in an x86 box does not have.
Setting POLARITY by hand gives the correct behaviour (off is dark, on is lit, blink blinks).
What worked for me
For reference only — I'm sure you will want to solve the polarity part differently (I can imagine boards wired the other way):
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -243,7 +243,10 @@
/* control LED */
val = MT_LED_CTRL_KICK;
- if (dev->mphy.leds.al)
+ /* PCIe cards without a DT node drive the mini-PCIe / M.2 LED_*#
+ * lines, which are active-low by spec.
+ */
+ if (dev->mphy.leds.al || !dev->mt76.dev->of_node)
val |= MT_LED_CTRL_POLARITY;
if (mphy->band_idx)
val |= MT_LED_CTRL_BAND;
@@ -571,7 +574,7 @@
mt76_rmw_field(dev, MT_LED_GPIO_MUX0,
GENMASK(11, 8), 1);
break;
- case 0x7916:
+ case 0x7906:
mt76_rmw_field(dev, MT_LED_GPIO_MUX1,
GENMASK(27, 24), 3);
mt76_rmw_field(dev, MT_LED_GPIO_MUX1,
@@ -590,7 +593,7 @@
mt76_rmw_field(dev, MT_LED_GPIO_MUX0,
GENMASK(11, 8), 1);
break;
- case 0x7916:
+ case 0x7906:
mt76_rmw_field(dev, MT_LED_GPIO_MUX1,
GENMASK(31, 28), 3);
break;
@@ -607,7 +610,7 @@
mt76_rmw_field(dev, MT_LED_GPIO_MUX0,
GENMASK(7, 4), 1);
break;
- case 0x7916:
+ case 0x7906:
mt76_rmw_field(dev, MT_LED_GPIO_MUX1,
GENMASK(27, 24), 3);
break;
With this module loaded from a cold boot: MUX1 = 0x33000000 (written by the driver itself), CTRL1 = 0x12 (BAND | POLARITY), and the LED follows the trigger correctly. It has been running on the router since.
Side note, not a bug: I ended up using the netdev trigger on the 5 GHz interface (tx + rx, no link) and keeping the 2.4 GHz channel off. Since both channels share one physical LED here, any channel that is "on" keeps it lit, and phyNtpt (created with IEEE80211_TPT_LEDTRIG_FL_RADIO) is solid whenever the radio is up.
Happy to test patches on this hardware.
- Dominant language
- C
- Stars
- 895
- Forks
- 461
- PR merge metrics
- No merged PRs in 30d
Getting set up
This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from openwrt/mt76
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
MT76xx - WLAN leds doesn't work with the testing kernelMay be free again A pull request for this issue was closed without being merged. Open
Difficulty 2/5 1-3 hours Newbie friendliness 65/100
-
mt7925: Netgear A8000 (0846:9072) reports hw_path without WF0_5G, so 5 GHz band is never registeredOpen
Difficulty 4/5 3-5 days Newbie friendliness 48/100
-
Difficulty 4/5 3-5 days Newbie friendliness 22/100
Similar issues
-
bug
Difficulty 2/5 1-3 hours Newbie friendliness 85/100
Maintainers usually reply within 1 day
-
SPIDevice selects an active-high device as soon as it is createdPossibly taken @mikeysklar claimed this today. Open
Difficulty 2/5 1-3 hours Newbie friendliness 73/100
adafruit/circuitpython#11869 ·
Maintainers usually reply within 1 day
-
Difficulty 1/5 Under an hour Newbie friendliness 78/100
gnif/LookingGlass#1352 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Maintainers usually reply within 1 day
-
Difficulty 2/5 1-3 hours Newbie friendliness 85/100