The last frame of a service period was always sent with MORE_DATA clear,
regardless of what mac80211 asked for and regardless of what is left in
the released TIDs. mac80211 sets @more_data when other TIDs still hold
buffered frames, and it expects the driver to set the bit itself when the
released TIDs hold more than the requested number of frames. Neither was
done, so a client that trusts MORE_DATA stops polling and its remaining
traffic sits in the queues until the next TIM or until the client leaves
powersave.
Pass the flag down to the last frame and add what is still queued for the
released TIDs.
Signed-off-by: Felix Fietkau <[email protected]>
One MT_WCID_DROP register word holds the drop bits of 32 stations, and the
read-modify-write that flips a single bit is not serialised against
anything. On MMIO devices mt76x02_sta_ps() runs it from the rx path while
mt76x02_tx_prepare_skb() runs it from the tx path, so an update for one
station can be lost, or an old value can be written back over it. A
station whose drop bit is restored that way has all of its traffic
discarded by the hardware until its next powersave transition.
Take mt76.lock around the update. USB devices can only reach this from
station setup, where register access may sleep and mt76.mutex already
serialises the only two callers.
Signed-off-by: Felix Fietkau <[email protected]>
Only frames that the driver has buffered in an ieee80211_txq are released
through mt76_release_buffered_frames() and end up on the PSD queue. Frames
that mac80211 buffered itself are handed back through the regular tx path
and go out on the access category queue of the frame. Clearing the drop
mask for MT_TXQ_PSD alone therefore misses them, and the hardware keeps
discarding PS-Poll and U-APSD responses for a station that is still marked
as sleeping. The client polls again on the next TIM and never receives
anything, so its traffic stalls until it leaves powersave.
Key off the tx info flags instead, the same way mt7603_tx_prepare_skb()
does. This covers both release paths and any other frame that mac80211
marks as exempt from powersave buffering.
Signed-off-by: Felix Fietkau <[email protected]>
The driver fails to register with error -22 (EINVAL) due to a cfg80211
validation failure in wiphy_verify_iface_combinations().
Commit 5ef0e8e2653b ("wifi: mt76: mt7996: fix iface combination for
different chipsets") added beacon_int_min_gcd to if_comb_global and
if_comb_global_7992, but these combinations include ADHOC (IBSS)
interface type. This violates a cfg80211 rule from commit 56271da29c52
("cfg80211: disallow beacon_int_min_gcd with IBSS") that explicitly
forbids combining ADHOC with beacon_int_min_gcd.
The restriction exists because beacon_int_min_gcd requires static,
predictable beacon intervals to coordinate multiple beaconing interfaces,
but ADHOC interfaces have dynamic beacon intervals that change when
joining different networks, making the GCD constraint unenforceable.
Remove beacon_int_min_gcd from the interface combinations that include
ADHOC because they are not necessary for ADHOC operation. The if_comb
combination (AP/MESH/STA only, without ADHOC) correctly retains
beacon_int_min_gcd for multi-AP coordination.
Fixes: 5ef0e8e2653b ("wifi: mt76: mt7996: fix iface combination for different chipsets")
Signed-off-by: Jose Ignacio Tornos Martinez <[email protected]>
Tested-by: Alex Gavin <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
mt76_phy_init() sets NL80211_FEATURE_ACTIVE_MONITOR for every mt76 device,
but mt792x firmware does not honor it: entering active monitor mode stops
RX. Gate the feature behind a new per-phy no_active_monitor flag and set it
for mt792x.
Signed-off-by: Devin Wittmayer <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
The event TLV loops accept a zero-length TLV, which advances neither the
cursor nor the remaining length, so a malformed event hangs the caller.
mt7925_mcu_uni_roc_event() additionally walked past the end of the skb,
since it never checked the declared length against the remainder.
Replace the five open-coded loops with a shared iterator that rejects
lengths below the TLV header and beyond the remaining buffer, and check
the per-tag payload sizes before dereferencing them.
While here, make the RSSI monitor event read from the current TLV rather
than from the start of the list.
Signed-off-by: Felix Fietkau <[email protected]>
mt7996_mmio_wed_init() set dev->mt76.hwrro_mode and rx_token_size while
building the WED configuration, before knowing whether the WED attach
can succeed. A failed attach left the enlarged rx_token_size behind and
reset hwrro_mode to MT76_HWRRO_OFF, clobbering the values that another
RX datapath owner may have configured earlier in probe: on Airoha
platforms with the wed_enable module parameter set, this broke the NPU
offload configuration set up by mt76_npu_init() (NPU offload requires
HW-RRO and a larger rx token space, and the attach always fails there
since no SoC has both an Airoha NPU and MTK WED).
Move both assignments after a successful attach, next to the existing
success-only dma_dev/irq assignments. This is safe for the regular WED
attach case: the first consumer of either field runs after probe
continues (mtk_wed_device_attach() only invokes the init_buf callback;
rx buffers are allocated via init_rx_buf from mtk_wed_start(), long
after mt7996_mmio_wed_init() has returned).
Within the WED configuration the HW-RRO checks were constant: the mode
was assigned unconditionally right before them, and the hif2 path is
only reachable after a successful main attach has set it. Resolve them
to their constant values and drop the dead branches.
Fixes: 377aa17d2aed ("wifi: mt76: mt7996: Add NPU offload support to MT7996 driver")
Signed-off-by: Felix Fietkau <[email protected]>
The firmware does not support individual TWT agreements with non-AP MLDs,
and the driver only tracks TWT flow state on the default link, which may
not be the link the agreement was negotiated on. Reject TWT setup
requests from MLD stations instead of programming an unsupported
configuration.
Signed-off-by: Howard Hsu <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
Like deauth, a disassoc frame sent to a client in powersave mode can get
stuck in a tx queue along with other buffered frames, filling up hardware
queues with frames that are only released after the WTBL slot is reused
for another client.
Move disassoc packets to the ALTX queue, matching the existing deauth
handling.
Fixes: dedf2ec30fe4 ("wifi: mt76: fix queue assignment for deauth packets")
Signed-off-by: Peter Chiu <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
Single-adie mt7986 binds its only phy to band 1. The eeprom parse
stores that phy's chainmask unshifted (chainshift is still 0 at that
point) but then sets chainshift to the mask width, so every consumer
that shifts by band_idx * chainshift disagrees with the storage:
mt7915_mcu_set_chan_info() sends rx_path 0 to the firmware with the
default mask, and mt7915_set_antenna() stores a band-shifted mask
inconsistent with the parse-time default.
Derive chainshift only from a band-0 main phy. In the single-phy
band-1 configuration the chains are numbered from 0 like a band-0 phy,
so with chainshift kept at 0 the stored mask, the set_antenna path, the
channel switch command and the RX chain report all agree on unshifted
masks. Drop the now-redundant empty-mask fallback in the RX path.
Dual-phy DBDC configurations parse the band-0 phy first and are
unaffected.
Fixes: 006b9d4ad5bf ("mt76: mt7915: introduce band_idx in mt7915_phy")
Signed-off-by: Felix Fietkau <[email protected]>
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]>
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]>
The per-station DRR config value packs the BSS group into bits 0-3;
the bit 4-5 AC priority and bit 6-7 WMM ID fields follow. The group
mask covered bits 0-5, overlapping the AC priority field, and the BWC
group value was written as a bare constant that ignored the station's
group. Narrow the group mask and derive the BWC group from it.
Signed-off-by: Felix Fietkau <[email protected]>
The EFUSE_ACCESS response carries a valid flag that was ignored, so
reading an unwritten efuse block copied garbage into the eeprom data.
Return -ENODATA for invalid blocks and leave the corresponding eeprom
range untouched (zero-initialised) when loading the full eeprom from
efuse.
Fixes: e57b7901469f ("mt76: add mac80211 driver for MT7915 PCIe-based chipsets")
Signed-off-by: Felix Fietkau <[email protected]>
Changing the antenna configuration updates the stream capabilities but
left the per-path SKU power limits and path delta compensation stale
until the next channel switch. Reapply the SKU table like mt7996
already does.
Signed-off-by: Felix Fietkau <[email protected]>
status->chains was set from the antenna mask, which is derived from
the number of spatial streams, while the chain_signal array is filled
from all RCPI fields. On boards where the number of RX paths exceeds
the stream count, e.g. the 3T3R mt7916/mt7981 variant with 2 streams
on the 5 GHz band, the RSSI of the extra chains was never reported.
Derive the chain mask from the RX path chainmask instead, shifted by
the band index of the phy owning the frame. On single-adie mt7986 the
main phy is bound to band 1 but its default chainmask is stored
without the band shift, unlike the mask set by mt7915_set_antenna();
fall back to the raw mask when the band group is empty to cover both
stored forms.
Fixes: e57b7901469f ("mt76: add mac80211 driver for MT7915 PCIe-based chipsets")
Signed-off-by: Felix Fietkau <[email protected]>
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]>
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]>
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]>
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]>
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]>
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]>
The hif2 reference obtained by mt7915_pci_init_hif2() is only released on
error paths that key off dev->hif2, which is not assigned until after the
IRQ setup. If pci_alloc_irq_vectors() or the primary devm_request_irq()
fails, the reference leaks. Drop it explicitly on those paths via
mt7915_put_hif2().
Fixes: f68d67623dec ("mt76: mt7915: add Wireless Ethernet Dispatch support")
Signed-off-by: Felix Fietkau <[email protected]>
After mt7915_register_ext_phy() succeeded, a failure of the main PHY
mt7915_init_debugfs() or mt7915_coredump_register() unwound through
free_phy2, which called ieee80211_free_hw() on the ext PHY hw while it
was still registered with mac80211, since mt76_unregister_device() only
unregisters the main hw. Unregister the ext PHY (thermal + phy + hw)
first and skip the redundant free.
Fixes: 7b8e1ae886e4 ("mt76: mt7915: rework hardware/phy initialization")
Signed-off-by: Felix Fietkau <[email protected]>
mt7915_thermal_init() registered the thermal cooling device and its sysfs
link, then returned the hwmon registration error without undoing them.
The cooling device (not devm-managed) and the link then leaked, and its
callbacks referenced the freed phy. Unregister the cooling device before
returning the error.
Fixes: 0ae3ff568451 ("mt76: mt7915: fix hwmon temp sensor mem use-after-free")
Signed-off-by: Felix Fietkau <[email protected]>
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]>
mt7915_eeprom_load_default() copied mt7915_eeprom_size() bytes from the
firmware blob after only checking that it was non-NULL. A truncated
default bin caused an out-of-bounds read past the firmware buffer into
the EEPROM image. Reject a blob smaller than the EEPROM size.
Fixes: beed8bea8d74 ("mt76: mt7915: add mt7916 calibrated data support")
Signed-off-by: Felix Fietkau <[email protected]>
mt7915_mcu_get_eeprom() copied a 16-byte block out of the firmware
response skb without checking that the response was long enough to hold
it. A short or malformed response could read past the end of the skb.
Reject a response shorter than the response header.
Fixes: 888208d1ccc4 ("wifi: mt76: mt7915: set correct background radar capability")
Signed-off-by: Felix Fietkau <[email protected]>
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]>
mt7915_pci_init_hif2() was called unconditionally and again inside the
WED-inactive branch. The helper increments the global hif_idx, writes the
PCIe RECOG_ID register and takes a get_device() reference via
mt7915_pci_get_hif2(), while removal only drops one reference. On non-WED
dual-hif hardware this double-incremented hif_idx, wrote RECOG_ID twice and
leaked a device reference. Only the call inside the WED-inactive branch is
correct; drop the unconditional one. hif2 is already initialised to NULL.
Fixes: cacdd67812c6 ("mt76: mt7915: add mt7915_mmio_probe() as a common probing function")
Signed-off-by: Felix Fietkau <[email protected]>
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]>
mt76_vif_link() indexes mvif->link[] without validating link_id, but
callers pass mvif->deflink_id / msta->deflink_id, which hold
IEEE80211_LINK_UNSPECIFIED (0xf) until the first link has been added.
Since IEEE80211_MLD_MAX_NUM_LINKS is 15, that reads one element past the
end of the array, aliasing mt76_vif_data.offchannel_link.
Reachable via mt7996_set_tsf()/mt7996_offset_tsf() and
mt7996_net_fill_forward_path(). Bounds check link_id and return NULL,
matching mt7996_sta_link() and mt7996_sta_link_protected().
Fixes: a9384b36a42a ("wifi: mt76: mt7996: rework set/get_tsf callabcks to support MLO")
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
The PS queue filed redirected frames under the TID taken from the TXD,
while mac80211 was told about the TID taken from the QoS header, or TID 0
for anything that is not a QoS data frame. When the two disagree,
mt7603_release_buffered_frames() skips the frame because it does not
match the requested TIDs, so it stays in the PS queue until the station
wakes up. Buffered MMPDUs hit this whenever they were sent on a
non-zero TID.
Use one TID for both.
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
Releasing buffered frames has to turn off the PSE redirect for the
station, otherwise the released frames are looped straight back into the
driver PS queue. Nothing ever turns it back on: mt7603_sta_ps() only runs
on an observed PM bit transition, and MT_WCID_FLAG_PS keeps mt76 from
reporting the same state twice. After the first service period the
hardware therefore treats a dozing station as awake and transmits at it
directly, which is where the retry storms and the packet loss reported
against U-APSD clients come from.
Re-arm hardware buffering from mt7603_mac_work() for every station that
is still known to be asleep, once the PSD queue has drained and the
released frames have passed the redirect stage. Frames that are still
queued belong to the service period that was just served, so unlike on a
sleep transition they must not be pulled back with mt7603_filter_tx().
Track the sleep state separately from the WTBL state, so a station that
wakes up while the re-arm is pending is not put back to sleep.
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
mt7603_rx_loopback_skb() marks a TID as buffered when the hardware
redirects a frame into the driver PS queue, but nothing ever clears that
state again. mac80211 therefore keeps the TIM bit set for the station and
keeps routing every service period to the driver, which also prevents it
from releasing frames it has buffered itself.
Clear the buffered state for every requested TID that has no frames left
in the PS queue.
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
Frames released from the driver PS queue were all tagged with MORE_DATA
and none of them ever carried the EOSP bit, so from the client's point of
view a U-APSD service period was started but never finished. Clients that
keep their receiver on until EOSP arrives stop sending trigger frames,
and all downlink traffic for that station stalls until they give up.
ieee80211_sta_eosp() only cleared the service period state inside
mac80211, which is why the mismatch went unnoticed.
Assign MORE_DATA per frame and set the wire EOSP bit on the last one. If
the last released frame is a bufferable MMPDU it has no QoS control field
to carry EOSP, so let mac80211 append a QoS-Null frame instead.
Also stop handing the remaining frame budget to
mt76_release_buffered_frames() once frames have been released from the PS
queue: both would signal the end of the same service period. Releasing
fewer frames than requested is allowed, and MORE_DATA tells the client to
trigger again.
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
When the driver implements .release_buffered_frames, mac80211 leaves the
U-APSD signalling entirely to the driver: "In this case it is also
responsible for setting the EOSP flag in the QoS header of the frames"
(include/net/mac80211.h). Only IEEE80211_TX_STATUS_EOSP was being set,
which merely ends the service period inside mac80211, so on air the
service period was never terminated. Clients that wait for EOSP before
going back to doze keep the SP open and stop triggering, which stalls all
downlink traffic for that station.
Set the wire EOSP bit on the last frame of a U-APSD service period.
EOSP has no meaning for a PS-Poll response, so pass the release reason
down and leave those frames alone.
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
Per IEEE 802.11be, the Beamformee SS <= 80/160/320 MHz 3-bit subfields
in the EHT PHY Capabilities are encoded as (Nss - 1) and are required
to be >= 3 (i.e. at least 4 SS receive capability) whenever SU
Beamformee is advertised.
MT7925 is a 2x2 STA (sts = 2), so directly filling (sts - 1) = 1
violates the spec minimum. Clamp the encoded value to 3 when sts <= 3,
otherwise use (sts - 1). This is applied consistently to the
BEAMFORMEE_SS <= 80 MHz (split across phy_cap_info[0]/[1]), <= 160 MHz
and <= 320 MHz (6 GHz only) subfields.
Fixes: c948b5da6bbe ("wifi: mt76: mt7925: add Mediatek Wi-Fi7 driver for mt7925 chips")
Signed-off-by: shengwei.lu <[email protected]>
Link: https://patch.msgid.link/[email protected]
Signed-off-by: Felix Fietkau <[email protected]>
__mt7915_mcu_add_sta() issued the SET_DRR_CTRL command that assigns the
VoW BSS group before sending the STA_REC that instantiates the station
in the firmware, and dropped the STA_REC skb unsent if that command was
rejected. On mt7996 the same ordering made client mode association fail
once the command occupying that slot started to depend on the station
record already existing.
Signed-off-by: Felix Fietkau <[email protected]>
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]>
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]>
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]>
The offchannel scan link is allocated in mt76_hw_scan() under
dev->mutex, but torn down without it: mt76_scan_complete() runs from
mt76_scan_work() on the mac80211 workqueue, or from mt76_abort_scan(),
and calls mt76_put_vif_phy_link(), whose vif_link_remove clears the
per-phy omac_mask and the device-wide vif_mask/mld_idx_mask with plain
read-modify-write. A vif link add or remove for another interface,
running concurrently under dev->mutex, can interleave with these
unlocked writes and lose an update: a cleared bit belonging to a live
link gets handed out again (two links sharing an omac/bss/wcid index,
breaking own-MAC unicast RX for the first one), or a freed bit stays
set until reboot and eventually exhausts the index space.
Take dev->mutex around the scan completion, mirroring the ROC teardown
in mt76_roc_complete_work()/mt76_abort_roc(), and switch the channel
restore to __mt76_set_channel() since the caller now holds the lock.
mt76_abort_scan() keeps cancelling the scan work before taking the
mutex, so the work-vs-abort ordering is unchanged.
Signed-off-by: Chad Monroe <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
The scan state bit is cleared by mt76_scan_complete(), but nothing ever
sets it: mt76_sw_scan() is only called for drivers without hw scan
support. As a result, all MT76_SCANNING checks are inert for drivers
using mt76_hw_scan(), including the DFS state handling in
mt76_phy_dfs_state() and the guard against manually triggered radar
detection while scanning.
Set the bit when the scan request is accepted. Since every channel
programmed while scanning now evaluates the DFS state as disabled and
stops the radar detector, re-program the operating channel at scan
completion regardless of the off-channel state, after the scanning bit
has been cleared. Otherwise a scan whose last visited channel was the
operating channel, or one that returned to it early because of
associated stations, would leave radar detection stopped until the
next channel switch.
Fixes: 31083e38548f ("wifi: mt76: add code for emulating hardware scanning")
Signed-off-by: Felix Fietkau <[email protected]>
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]>
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]>
WM firmware can enter a partial failure state where RX is hung.
Detect this condition by monitoring SER_PLE_ERR_1 for MDP_RIOC_HANG_ERR
and trigger L1 SER to restore operation. Use transition detection on the
error bit to fire only once per new occurrence, preventing an infinite
SER loop when the bit remains set across checks.
Signed-off-by: Chad Monroe <[email protected]>
Suggested-by: Ryder Lee <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>