Commit Graph
532 Commits
Author SHA1 Message Date
StanleyYP WangandFelix Fietkau 95c614cc6b wifi: mt76: mt7996: remove repeater muar config
Repeater mode is not supported currently, so remove it.
get_omac_idx() only hands out HW_BSSID/EXT_BSSID indices, so the
omac_idx >= REPEATER_BSSID_START call sites are unreachable.

Signed-off-by: StanleyYP Wang <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
2026-08-01 17:46:21 +02:00
StanleyYP WangandFelix Fietkau f3541c1fc3 wifi: mt76: mt7996: add scan dwell time hw cap
Add NL80211_EXT_FEATURE_SET_SCAN_DWELL support in driver.
This allows user to specify channel dwell time during scanning.

Signed-off-by: StanleyYP Wang <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
2026-08-01 17:46:21 +02:00
Felix Fietkau fa98398ec4 wifi: mt76: mt7996: do not attach hif2 WED when the main WED attach failed
If the WED attach for the primary PCIe function fails, the probe path
still attached wed_hif2 for the secondary function, leaving the device
in an inconsistent half-WED configuration that crashes later. The hif2
call also re-enabled hwrro_mode, which the failed primary attach had
just turned off.

Skip the hif2 WED setup when the primary WED device is not active.

Fixes: 83eafc9251d6 ("wifi: mt76: mt7996: add wed tx support")
Signed-off-by: Felix Fietkau <[email protected]>
2026-08-01 17:46:21 +02:00
Felix Fietkau be7e2fa433 wifi: mt76: mt7996: fix MIB TX aggregation counter registers for mt7990
The MIB_TSCR0-7 counters read by mt7996_mac_update_stats() are
hardcoded at the mt7996/mt7992 offsets 0x6b0-0x6d0, but mt7990 moved
them to 0x750-0x770, so TX AMPDU statistics were read from unrelated
registers on that chip. Move the offsets into the per-chip register
tables.

Fixes: f6c87411d15f ("wifi: mt76: mt7996: rework register mapping for mt7990")
Signed-off-by: Felix Fietkau <[email protected]>
2026-08-01 17:46:21 +02:00
Felix Fietkau 00107991a2 wifi: mt76: mt7996: use the default timeout for STA_REC and BSS_INFO updates
STA_REC_UPDATE and BSS_INFO_UPDATE carry variable-size payloads,
including beacon templates that grow considerably with 11v MBSS and
MLD configurations, and firmware can legitimately take longer than 2
seconds to process them. Since a message timeout now triggers a full
device reset, a false timeout on these commands is punished harshly.

Keep the shorter timeout for the small fixed-size commands and move
STA_REC_UPDATE/BSS_INFO_UPDATE back to the 5 second default.

Fixes: beb01caa570c ("wifi: mt76: mt7996: decrease timeout for commonly issued MCU commands")
Signed-off-by: Felix Fietkau <[email protected]>
2026-08-01 17:46:21 +02:00
StanleyYP WangandFelix Fietkau c85317f1d4 wifi: mt76: mt7996: fix reg addr remap when addr is 0
When addr is less than the hardcoded threshold in __mt7996_reg_addr,
it indicates that remapping is unnecessary.
Currently, the flow remaps address 0x0 to MT_HIF_REMAP_BASE_L2,
which is incorrect.
To address this, modify __mt7996_reg_addr to return INVALID_REG_ADDR
if the address is not below the hardcoded value or is not present in
the mt7996_reg_map array.
Additionally, update the remap condition to check if addr is equal to
INVALID_REG_ADDR.

Fixes: 3687854d3e7e ("wifi: mt76: mt7996: add locking for accessing mapped registers")
Signed-off-by: StanleyYP Wang <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
2026-08-01 17:46:21 +02:00
Felix Fietkau 686b509b9f wifi: mt76: mt7996: bound RRO session id before indexing addr_elem[]
seq_id from the WED RRO indication is a 12-bit field (0-4095), but only
values up to MT7996_RRO_MAX_SESSION map into wed_rro.addr_elem[], which
has MT7996_RRO_ADDR_ELEM_LEN (128) entries. A larger session id computes
an out-of-bounds element index that is then read and, on a signature
mismatch, written. Reject an out-of-range session id.

Fixes: a09d2f9d69af ("wifi: mt76: Convert mt76_wed_rro_ind to LE")
Signed-off-by: Felix Fietkau <[email protected]>
2026-08-01 17:46:21 +02:00
Felix Fietkau 5367804a6a wifi: mt76: mt7915: guard firmware memory dump write on disabled memdump
mt7915_coredump_build()/mt7996_coredump_build() wrote dump_mem->len
unconditionally, but the allocation only reserves room for the memory
dump header when coredump_memdump is enabled and memdump_buf_len is
non-zero. In the default configuration the allocation ends right after
the fixed header, so the write landed one struct past the buffer. Only
populate the memory-dump section when it was actually allocated.

Fixes: 4dbcb9125cc3 ("wifi: mt76: mt7915: enable coredump support")
Fixes: 878161d5d4a4 ("wifi: mt76: mt7996: enable coredump support")
Signed-off-by: Felix Fietkau <[email protected]>
2026-08-01 17:46:21 +02:00
Felix Fietkau a06dbaf0c3 wifi: mt76: mt7996: validate firmware event lengths before parsing
Two unsolicited event handlers trusted firmware-provided lengths:
mt7996_mcu_rx_all_sta_info_event() looped over res->sta_num without
checking it against skb->len, reading the flex array out of bounds; and
mt7996_mcu_rx_log_message() could compute a negative or oversized length
from tlv->len and feed it to %.*s and the debugfs log path. Bound both
against the actual skb length.

Fixes: adde3eed4a75 ("wifi: mt76: mt7996: Add mcu commands for getting sta tx statistic")
Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
Signed-off-by: Felix Fietkau <[email protected]>
2026-08-01 17:46:20 +02:00
Felix Fietkau 591568f4e6 wifi: mt76: mt7996: bound EEPROM access event before copying
mt7996_mcu_get_eeprom() copied the event->eeprom payload out of the
firmware response skb without checking that the response actually held
the bytes being read. A short or malformed response could read past the
end of the skb. Reject a response shorter than the event header and bound
each copy to the payload present in the skb.

Fixes: 0da2e410705e ("wifi: mt76: mt7996: extend flexibility of mt7996_mcu_get_eeprom()")
Signed-off-by: Felix Fietkau <[email protected]>
2026-08-01 17:46:20 +02:00
Felix Fietkau b2704cf5a4 wifi: mt76: mt7996: fix out-of-bounds link array access in mt7996_tx()
When mac80211 leaves the link unspecified, mt7996_tx() substitutes the
primary link id of the station or vif. That value is
IEEE80211_LINK_UNSPECIFIED (0xf) until the first link has been added,
and it is then used unchecked to index vif->link_conf[],
mvif->mt76.link[] and sta->link[], all of which hold
IEEE80211_MLD_MAX_NUM_LINKS (15) entries.

Clamp the primary link id to the default link before using it, and use
the clamped value for the link_sta fallback as well.

Fixes: 1609b014aa29 ("wifi: mt76: mt7996: Overwrite unspecified link_id in mt7996_tx()")
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
2026-08-01 17:45:48 +02:00
Felix Fietkau da2c90d216 wifi: mt76: mt7996: send the STA_REC before the per-station VoW setup
mt7996_mcu_add_sta() issued the VoW DRR control commands for a station
before sending the STA_REC that instantiates it in the firmware. On a
fresh peer entry there is no station context yet, so the firmware
rejects UNI_VOW_DRR_CTRL with 0xC0000001, logging "GetDisablePerStaTx
Failed". That error was returned to the caller, which freed the STA_REC
skb without ever sending it, so bringing up client mode occasionally
failed with "failed to move station to desired state".

Send the STA_REC first and set up the airtime scheduler afterwards.
Airtime fairness is not required for the link to work and the station
record has already been committed at that point, so a failure there no
longer aborts the connection.

Fixes: 910db36ae5 ("wifi: mt76: mt7996: HW ATF support")
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-29 18:02:19 +02:00
Felix Fietkau 06b69763f2 wifi: mt76: mt7996: fix infinite loop in PS sync event parsing
A zero-length TLV makes the parser loop spin forever, since neither
skb_pull() nor the remaining length advance, hanging the RX NAPI thread
until RCU reports a stall.

Reject TLVs shorter than their header, and validate the per-tag payload
lengths before dereferencing them.

Fixes: https://github.com/openwrt/mt76/issues/1109
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-27 17:01:10 +02:00
Chad MonroeandFelix Fietkau 50480826f5 wifi: mt76: mt7996: hold dev->mutex in remove_interface teardown
mt7996_remove_interface() destroys the remaining vif links, clearing
omac_mask, vif_mask and mld_idx_mask, with only the wiphy mutex held.
Those masks are modified under dev->mutex everywhere else, so the
unlocked clears can race the scan-link teardown and the reset work
and lose updates.

Take dev->mutex around the link destroy loop, matching
mt7996_add_interface() and mt7915_remove_interface(). The mutex is
released before mt76_vif_cleanup(), which aborts a pending scan and
takes the mutex itself.

Signed-off-by: Chad Monroe <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Felix Fietkau 31f1fdb7cd wifi: mt76: mt7996: clear stale link state on full reset
After a full chip reset, mac80211 reconfig replays interface, link and
channel context setup. mt7996_vif_link_add() short-circuits when the
link_id is still marked in mvif->valid_links, a state introduced for
postponing link teardown to interface removal. The reset path frees the
link structures without clearing those bits, so the replayed setup never
re-creates dev_info/bss_info/STA records in the restarted firmware and
never re-registers the link wcid, leaving the device inoperative.

The reset path also leaks every allocated MLD index: per-link indices
and the per-vif group/remap indices are re-allocated from scratch during
reconfig, but the old bits stay set in the masks, so repeated full
resets exhaust the index space.

Clear valid_links in the reset vif iterator and reset the MLD index
masks alongside the existing omac_mask clearing.

Fixes: ace5d3b6b49e ("wifi: mt76: mt7996: improve hardware restart reliability")
Fixes: 08813703ac41 ("wifi: mt76: mt7996: Destroy vif active links in mt7996_remove_interface()")
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Felix Fietkau 386fd21557 wifi: mt76: mt7996: free vif links after clearing wcid entries on full reset
mt7996_mac_reset_vif_iter() queues non-default vif links for kfree_rcu
while dev->wcid[] still holds pointers to the wcid embedded in each
freed link; mt76_reset_device() then dereferences those entries and
runs mt76_wcid_cleanup() on them. If a grace period elapses in between,
the cleanup operates on freed memory.

Run mt76_reset_device() first, so the wcid entries are cleaned up and
cleared while the links are still valid.

Fixes: ace5d3b6b49e ("wifi: mt76: mt7996: improve hardware restart reliability")
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Chad MonroeandFelix Fietkau 130273a947 wifi: mt76: fix stuck TX queues after SER with no active interfaces
When a firmware watchdog triggers full SER recovery before any VAPs
are up, mac80211 skips drv_reconfig_complete() because open_count is
zero. This leaves the DRIVER queue stop reason set permanently,
blocking all TX when interfaces eventually start.

Signed-off-by: Chad Monroe <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Chad MonroeandFelix Fietkau 5ecae46405 wifi: mt76: mt7996: select net_setup_tc handler at runtime
The net_setup_tc callback is chosen at compile time and the WED
handler shadows the NPU one when CONFIG_NET_MEDIATEK_SOC_WED is
enabled. mt76_wed_net_setup_tc() returns -EOPNOTSUPP without an
active WED device, so on boards using the Airoha NPU with a WED
enabled kernel the tc offload block is never bound and PPE flow
offload for wireless traffic is silently disabled.

Dispatch on the active offload backend instead: use the WED handler
when a WED device is attached and fall back to the NPU handler
otherwise. Builds without MT76_NPU keep the old behavior through the
mt76_npu_net_setup_tc() stub.

Signed-off-by: Chad Monroe <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Felix Fietkau be8657a1cd wifi: mt76: mt7996: wake MCU waiters before aborting scan in L1 SER
The L1 reset path calls mt76_abort_scan() between setting MT76_MCU_RESET
and waking mcu.wait. A scan work blocked on an in-flight MCU command
does not re-evaluate its wait condition until woken, so the
cancel_delayed_work_sync() inside the abort sleeps out the full MCU
timeout before recovery can proceed, adding several seconds of SER
latency. mt7996_mac_full_reset() and the mt7915 counterpart already
order the wake-up first.

Wake mcu.wait immediately after setting MT76_MCU_RESET so in-flight
commands bail out before the abort synchronises against them.

Fixes: b36d55610215 ("wifi: mt76: abort scan/roc on hw restart")
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Felix Fietkau e14869fcee wifi: mt76: mt7996: skip key upload when adding an offchannel link
No hw keys are ever uploaded for scanning/roc links and the link remove
path already skips the key iteration for them. The add path still runs
it, and since mt7996_set_hw_key() resolves the target through
mvif->link[link_id] rather than the offchannel link, starting a scan on
another band re-uploads the group keys of the link sharing the same
link_id, re-sending its BSS cipher info and, for BIGTK with beacon
protection on an AP link, toggling its beacons off and on.

Skip the key iteration for offchannel links, mirroring the remove path.

Fixes: 69d54ce7491d ("wifi: mt76: mt7996: switch to single multi-radio wiphy")
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Peter ChiuandFelix Fietkau ffabf1e53b wifi: mt76: mt7996: leave PS when a 4-address connection is established
Because 4 address non-AMSDU packets do not have a bssid field, the
hardware cannot get the bssid. Without the bssid, stations are not
able to leave PS mode due to HW design. Wake up non-setup links when
4-address mode is established to prevent this issue.

mt7992 and mt7990 handle this via the BSSID mapping band config
instead, so restrict the command to mt7996.

Signed-off-by: Peter Chiu <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Peter ChiuandFelix Fietkau eeb07a4edc wifi: mt76: mt7996: add mcu command to set bssid mapping address
When receiving a 4 address non-AMSDU packet, there is no bssid in the
address fields, which breaks powersave handling for 4-address peers.
Set the mcu command to use A1 as bssid when receiving 4 address
non-AMSDU packets on mt7992 and mt7990.

Also skip mt7996_mac_init_band() for invalid bands, so the command is
only sent for bands that actually exist on the device.

Signed-off-by: Peter Chiu <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
StanleyYP WangandFelix Fietkau 1ece37f8a9 wifi: mt76: mt7996: add missing rdd_idx check when enabling background radar
Add the missing rdd idx check (< 0) in
mt7996_mcu_rdd_background_enable(). mt7996_get_rdd_idx() returns -1
for phys without 5 GHz support, and the negative index was passed to
the RDD MCU command unchecked.

Fixes: 1529e335f93d ("wifi: mt76: mt7996: rework radar HWRDD idx")
Signed-off-by: StanleyYP Wang <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Felix Fietkau 10a1541fb2 wifi: mt76: report data NSS for STBC frames in RX rate decode
The RX rate decoder set status->nss straight from the PRXV NSTS field,
which for STBC frames is twice the data spatial-stream count. cfg80211
then reported a doubled RX bitrate in station dumps and radiotap. Halve
nss for STBC, matching the TX status path.

Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
Fixes: d832f5e73815 ("mt76: connac: move mt76_connac2_mac_fill_rx_rate in connac module")
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Felix Fietkau 3def033512 wifi: mt76: cancel reset and rc work on device unregister
Both drivers cancelled dump_work on unregister but left reset_work and
rc_work to be flushed only by destroy_workqueue() in mt76_free_device(),
which runs after the hw is unregistered and the hardware stopped. A
reset_work that fires in that window calls ieee80211_restart_hw() and
re-arms mac_work on an unregistered hw, and rc_work touches station state
being torn down. Cancel both up front, alongside dump_work.

Fixes: e57b7901469f ("mt76: add mac80211 driver for MT7915 PCIe-based chipsets")
Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Felix Fietkau d67367ec32 wifi: mt76: mt7996: don't leak MLD group index on remap alloc failure
mt7996_change_vif_links() sets the mld_idx_mask group bit before
allocating the remap index. If the remap allocation fails it jumped to
the exit without clearing that bit, permanently consuming one of the 16
MLD group slots. Release the group bit on the error path.

Fixes: 4fb3b4e7d1ca ("wifi: mt76: mt7996: fix MLD group index assignment")
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Felix Fietkau f66cff22fb wifi: mt76: mt7996: reserve space for the CSA-abort countdown TLV
When a CSA countdown is active, mt7996_mcu_beacon_cntdwn() emits two
bss_bcn_cntdwn_tlv entries (the CSA countdown and the CCA-abort BCC), but
MT7996_BEACON_UPDATE_SIZE only reserved one. With MBSSID enabled and a
near-maximum beacon template the extra 8 bytes could push the offload
command past MT7996_MAX_BSS_OFFLOAD_SIZE and trigger skb_over_panic().
Reserve room for both countdown TLVs.

Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Felix Fietkau f012f82a81 wifi: mt76: fix ER-SU 106-tone RU check in RX rate decode
MT_PHY_TYPE_HE_EXT_SU is an enum value (9), not a bit flag, so the
bitwise test "*mode & MT_PHY_TYPE_HE_EXT_SU" also matches OFDM, HT-GF and
several HE/EHT modes. Only genuine ER-SU should be classified as a
106-tone RU at 40 MHz; use an equality comparison.

Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
Fixes: d832f5e73815 ("mt76: connac: move mt76_connac2_mac_fill_rx_rate in connac module")
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Felix Fietkau 41cecc382b wifi: mt76: decode the full VHT Rx STBC capability field
The Rx STBC subfield of the VHT capabilities is a 3-bit cumulative value,
but the driver only tested the RXSTBC_1 bit when advertising the peer's
Rx STBC support to firmware. A peer reporting Rx STBC of 2, 3 or 4 has
that bit clear, so STBC was never used towards it. Test the full
IEEE80211_VHT_CAP_RXSTBC_MASK, matching the HT path.

Fixes: 046d2e7c50e3 ("mac80211: prepare sta handling for MLO support")
Fixes: 2660fde82f65 ("wifi: mt76: mt7996: Update mt7996_mcu_add_rate_ctrl to MLO")
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Felix Fietkau 2a574ac536 wifi: mt76: mt7996: hold dev->mt76.mutex while disabling tx worker in SER
mt7996_mac_reset_work() parked the tx worker and disabled the RX/TX NAPIs
before taking dev->mt76.mutex. mt76_worker_disable()/_enable() are plain
kthread park/unpark, not refcounted, and __mt76_set_channel() toggles the
same worker and the MT76_RESET bit under the mutex. An L1 SER racing a
channel switch could therefore have the worker unparked and MT76_RESET
cleared while the reset path resets the DMA rings, corrupting descriptors
or tokens. Take the mutex before disabling the worker, as mt7915 does.

Fixes: 27015b6fbcca ("wifi: mt76: mt7996: enable full system reset support")
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:39 +02:00
Felix Fietkau 48c4d99acd wifi: mt76: mt7996: bound TLV walk in mt7996_mcu_get_chip_config
The response TLV loop advanced by tlv->len without a minimum, so a
theoretical firmware response containing a zero-length TLV could spin
forever, hanging the CPU during device probe.
The u32 payload was also read without bounds checking.
Reject a short fixed field, stop on a TLV whose length underruns the
header or overruns the skb.

Fixes: 5d33053be609 ("wifi: mt76: mt7996: add variants support")
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-24 14:45:25 +02:00
Felix Fietkau f67ffb60cd wifi: mt76: allow TX aggregation on the VO queue
The TX aggregation check skipped TIDs 6 and 7, so all voice-priority
traffic was sent without a BA session and therefore unaggregated,
limiting throughput for stations that map bulk traffic to VO. The
hardware handles aggregation on the VO queue fine, and a peer that
prefers unaggregated voice frames can still decline the ADDBA request.

Remove the skip from both the connac2 and the mt7996 aggregation setup
paths.

Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-22 10:51:13 +02:00
Felix Fietkau cdc6c0d07c wifi: mt76: fix 4th chain ACK RSSI bitmask in sta_poll
The per-chain response-frame RSSI values are packed one per byte, but the
4th chain was extracted with GENMASK(31, 14) instead of GENMASK(31, 24).
The wrong mask overlaps chains 1-3 and shifts by 14, producing a garbage
chain-3 value that corrupts ack_signal/avg_ack_signal on 4x4 radios.
Extract the correct byte.

Fixes: a71b648e3527 ("wifi: mt76: mt7915: add ack signal support")
Fixes: ea5d99d07fbf ("wifi: mt76: mt7996: enable ack signal support")
Fixes: 67fc7a304bf5 ("wifi: mt76: mt7921: add ack signal support")
Fixes: c948b5da6bbe ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips")
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-22 10:51:04 +02:00
Felix Fietkau 8ad57c3cca wifi: mt76: mt7996: don't report a zero TX bitrate
mt7996_sta_statistics() set NL80211_STA_INFO_TX_BITRATE unconditionally
after the block that already sets it, so a station with no rate info yet
was reported to userspace with a valid-but-zero TX rate. Drop the
redundant unconditional assignments; the in-block ones are sufficient.

Fixes: b34f346b917e ("wifi: mt76: mt7996: drop return in mt7996_sta_statistics")
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-22 10:51:04 +02:00
Felix Fietkau a3b62f2330 wifi: mt76: mt7996: set MT76_MCU_RESET before waking MCU waiters on full reset
mt7996_mac_full_reset() called wake_up(&dev->mt76.mcu.wait) without first
setting MT76_MCU_RESET. The MCU response wait condition only checks the
response queue and that bit, so the wake-up released nobody: a thread
blocked in an MCU command against the dead firmware (typically holding
dev->mt76.mutex) stayed asleep until its multi-second timeout, stalling
recovery. Set the bit before the wake-up, as mt7915 does.

Fixes: 27015b6fbcca ("wifi: mt76: mt7996: enable full system reset support")
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-22 10:51:04 +02:00
Felix Fietkau fc74da790f wifi: mt76: mt7996: validate RX band_idx before dereferencing phys[]
band_idx comes from a 2-bit descriptor field (0-3) and was used directly
to index dev->mt76.phys[] (size __MT_MAX_BAND == 3) and dereference the
result. A corrupt or reserved descriptor value could index out of bounds
or hit a NULL phy on parts with fewer bands. Reject invalid band indices,
mirroring mt7996_rx_get_wcid().

Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-22 10:51:04 +02:00
Peter ChiuandFelix Fietkau 4efe882252 wifi: mt76: mt7996: fix MLD ID in MAC TXD and HIF TXP
Problem:
MCU command timeout while the firmware state is normal, and the
firmware keeps showing the error log "ERROR!! NO PAUSE...".

Root cause:
If the MLD_ID field in the TXD is neither the primary link id nor the
secondary link id, it may lead to a firmware busy loop when the third
link is in power saving mode.

Remap frames directed to a third link to the primary link wcid. Since
TX status events and txfree completions carry the wcid the firmware
saw, use the remapped wcid for packet id tracking and non-AQL packet
accounting as well, while the frame keeps its original link context
for addressing, band and OMAC selection.

Fixes: 85cd5534a3f2 ("wifi: mt76: mt7996: use correct link_id when filling TXD and TXP")
Signed-off-by: Peter Chiu <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-22 10:51:04 +02:00
Shayne ChenandFelix Fietkau 968dc6335a wifi: mt76: mt7996: fix capability of EHT-MCS 15 in MRU
According to the definition in IEEE Std 802.11be-2024, Table 9-417r:
- If 80 MHz is not supported, bit 1-3 are set to 0.
- If 160 MHz is not supported, bit 2-3 are set to 0.
- If 320 MHz is not supported, bit 3 is set to 0.

Fixes: 348533eb968d ("wifi: mt76: mt7996: add EHT capability init")
Signed-off-by: Shayne Chen <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-22 09:49:38 +02:00
Lorenzo BianconiandFelix Fietkau 763e99aadb wifi: mt76: mt7996: fix possible NULL-pointer deref in mt7996_mcu_sta_bfer_eht()
mt76_connac_get_eht_phy_cap routine can theoretically return NULL so
check cap pointer before dereferencing it.

Fixes: ba01944adee9f ("wifi: mt76: mt7996: add EHT beamforming support")
Signed-off-by: Lorenzo Bianconi <[email protected]>
Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-4-ed4ccf7a0363@kernel.org
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-21 12:39:16 +02:00
Lorenzo BianconiandFelix Fietkau 89b69012de wifi: mt76: mt7996: check pointer returned by mt76_connac_get_he_phy_cap()
mt76_connac_get_he_phy_cap routine can theoretically return NULL so
check cap pointer before dereferencing it.

Fixes: 98686cd21624c ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
Signed-off-by: Lorenzo Bianconi <[email protected]>
Link: https://patch.msgid.link/20260621-mt76_connac_get_he_phy_cap-fix-v1-3-ed4ccf7a0363@kernel.org
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-21 12:39:16 +02:00
Kenneth KasilagandFelix Fietkau 1ee3e2f6c2 wifi: mt76: mt7996: expose per-band MAC addresses to cfg80211
mt7996/mt7992 are single-wiphy, multi-band devices. The driver assigns
each band its own MAC address from a per-band EEPROM entry, or derives
it from the primary band's address when that entry is empty, however
only the primary band's is published as perm_addr. The per-band
addresses are not exposed to cfg80211, so consumers usually fall back
to deriving one from perm_addr.

Store each band's address in wiphy->addresses[], indexed by radio, so
cfg80211 exposes the address the hardware actually uses for that radio.
addresses[0] is the primary band and matches perm_addr, as cfg80211
requires.

Link: https://github.com/openwrt/openwrt/issues/23578
Tested-on: Gemtek W1700K (MT7996)
Signed-off-by: Kenneth Kasilag <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-21 12:39:16 +02:00
Bryam VargasandFelix Fietkau 76c38706bb wifi: mt76: mt7996: bound the device EEPROM address before the EFUSE copy
mt7996_mcu_get_eeprom() derives the destination of the EFUSE/EXT block
copy from the address reported by the MCU response (event->addr, a
device-controlled __le32) and clamps only the copy length, never the
destination offset into dev->mt76.eeprom.data. A malicious or
malfunctioning device can report an arbitrary address and drive an
out-of-bounds write of up to MT7996_EXT_EEPROM_BLOCK_SIZE bytes past
eeprom.data.

Reject a response whose address would place the copy outside eeprom.data
before deriving the destination pointer. Devices that echo the requested
in-bounds offset are unaffected.

Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
Cc: [email protected]
Signed-off-by: Bryam Vargas <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-21 12:39:16 +02:00
Laxman Acharya PadhyaandFelix Fietkau 3eb3ab6b43 wifi: mt76: mt7996: validate default EEPROM firmware size
The default EEPROM firmware is parsed and copied as a full EEPROM
without checking its length. A truncated file can make the driver
read beyond the firmware buffer during variant validation or the
fallback copy.

Reject files shorter than MT7996_EEPROM_SIZE before parsing or
copying the firmware.

Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
Cc: [email protected]
Signed-off-by: Laxman Acharya Padhya <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-21 12:38:45 +02:00
Felix Fietkau 36917c4e63 wifi: mt76: mt7996: fix TX DMA mapping leak for AddBA req frames
mt7996/mt7992 hand the firmware a HW MAC-TXP for AddBA req action frames
(MT_TXD7_MAC_TXD, set in mt7996_mac_write_txwi_80211()), but are otherwise
FW-TXP devices. On tx free mt76_connac_txp_skb_unmap() therefore decodes the
per-frame txp as a struct mt76_connac_fw_txp. For a MAC-TXP the fw_txp.nbuf
byte aliases the AddBA TID word (MT_TXP1_TID_ADDBA), which is always zero, so
the unmap loop runs zero times and the skb DMA mapping in buf[1] is never
unmapped. buf[1].skip_unmap is set unconditionally, so the generic DMA-ring
cleanup skips it as well.

Each AddBA req therefore leaks one TX DMA mapping, roughly one per
(re)association. With WED enabled these mappings are bounced through the WED
swiotlb pool, so under continuous client reconnect churn the pool is exhausted
after ~1-2 days, after which DMA mapping fails for WED, the WiFi MCU and other
on-SoC consumers.

Keep the deferred (token release) unmap that the design relies on, and add an
mt7996-specific txp unmap that inspects MT_TXD7_MAC_TXD and unmaps buf[1] from
the MAC-TXP layout for those frames, delegating to mt76_connac_txp_skb_unmap()
otherwise.

Fixes: cb6ebbdffef2 ("wifi: mt76: mt7996: support writing MAC TXD for AddBA Request")
Cc: [email protected]
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-21 10:30:02 +02:00
Ethan Nelson-MooreandFelix Fietkau 13561afa1f wifi: mt76: mt7996: remove code guarded by nonexistent config option
A small piece of code in mt7996.h depends on CONFIG_MTK_DEBUG, which
has never been defined in the kernel. Remove this dead code.

Discovered while searching for CONFIG_* symbols referenced in code but
not defined in any Kconfig file.

Signed-off-by: Ethan Nelson-Moore <[email protected]>
Reviewed-by: Matthias Brugger <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-21 10:30:02 +02:00
Chad MonroeandFelix Fietkau 59676919ea wifi: mt76: mt7996: fix non-MLD station num_sta leak
The MLO link-reconfiguration rework moved the per-phy num_sta
decrement inside a link_valid guard. link_valid is only set for
MLO links, but num_sta is incremented for every station link,
including the non-MLO deflink. Non-MLO stations bump num_sta
on association and never drop it on removal.

A non-zero num_sta forces connected-mode off-channel scanning which
prevents the directed probe exchange needed to find hidden APs.

Decrement phy->num_sta on the actual link teardown, pairing it with
the unconditional increment on link creation.

Fixes: 018f60316d ("wifi: mt76: mt7996: Destroy active sta links in mt7996_mac_sta_remove()")
Signed-off-by: Chad Monroe <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
2026-07-01 10:46:39 +02:00
Chad MonroeandFelix Fietkau fe40221e05 wifi: mt76: mt7996: fix EAPOL source BSS for non-MLD stations
A non-MLD station's EAPOL and data frames are tagged with link_id ==
IEEE80211_LINK_UNSPECIFIED, which now skips the per-link lookup in
mt7996_mac_write_txwi() and leaves omac_idx/band_idx/wmm_idx at slot
0. When the radio also runs AP VAPs the station's omac is non-zero
(get_omac_idx() prefers HW BSSID slots 1-3), so its EAPOL frames
egress from the wrong BSS and the 4-way handshake times out even
though association succeeds.

In mt7996_tx_prepare_skb(), resolve the link from the peer wcid when
link_id is UNSPECIFIED and the wcid is not the global entry, restoring
the pre-MLO behaviour for station traffic.

Fixes: 934f647104 ("wifi: mt76: mt7996: fix reading zeroed info->control.flags after mt76_tx_status_skb_add()")
Signed-off-by: Chad Monroe <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
2026-06-30 14:24:23 +02:00
Felix Fietkau 910db36ae5 wifi: mt76: mt7996: HW ATF support
Add hardware airtime fairness (ATF) support for mt7996, using the MAC's
weighted DWRR scheduler (VoW) to balance TX airtime between stations, in
the same way as the mt7915 implementation.

This supplements mac80211's software airtime fairness rather than
replacing it: software ATF keeps scheduling the host TX queues, while the
hardware scheduler enforces fairness on the offloaded path where the host
has no airtime accounting, such as when WED is active.

A station's TX airtime weight is taken from mac80211 through the
sta_set_airtime_weight op and applied to the hardware scheduler directly;
the per-AC DWRR quantum levels and the station's BSS group index are
derived on the fly, mapping the weight logarithmically onto the global
hardware quantum table. ATF and WATF are enabled by default and can be
toggled together at runtime through the "vow_atf" debugfs file.

Signed-off-by: Benjamin Lin <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
2026-06-30 09:55:10 +02:00
Ingyu JangandFelix Fietkau 72d8dc8574 wifi: mt76: Drop unneeded mt76_register_debugfs_fops() return checks
mt76_register_debugfs_fops() returns the dentry from
debugfs_create_dir(), which yields an error pointer on failure
(notably ERR_PTR(-ENODEV) when CONFIG_DEBUG_FS=n), never NULL. Per
commit ff9fb72bc077 ("debugfs: return error values, not NULL"),
callers do not need to check the return value.

Drop the dead !dir checks in mt7615/mt7915/mt7921/mt7925/mt7996
_init_debugfs(). Converting them to IS_ERR() instead would have
exposed a probe abort on CONFIG_DEBUG_FS=n, since each
*_init_debugfs() caller propagates the helper's return value.

This patch supersedes an earlier proposal that converted the checks
to IS_ERR().

Link: https://lore.kernel.org/all/[email protected]
Signed-off-by: Ingyu Jang <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
2026-06-09 12:34:14 +02:00
Ryder LeeandFelix Fietkau 9f60dd01e6 wifi: mt76: mt7996: fix potential tx_retries underflow
When FIELD_GET returns 0 for the retry count, subtracting 1 causes
an unsigned integer underflow, resulting in tx_retries becoming a
very large value (0xFFFFFFFF for u32).

Fix by checking if count is non-zero before subtracting 1.

Fixes: 2461599f835e ("wifi: mt76: mt7996: get tx_retries and tx_failed from txfree")
Signed-off-by: Ryder Lee <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
2026-06-09 12:28:21 +02:00