* [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes
@ 2026-11-13 23:52 Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 01/10] wifi: rtw89: avoid NULL vif dereference in rtw89_ops_tx() Enver Ikromov
` (10 more replies)
0 siblings, 11 replies; 15+ messages in thread
From: Enver Ikromov @ 2026-11-13 23:52 UTC (permalink / raw)
To: Ping-Ke Shih; +Cc: linux-wireless, linux-kernel, Enver Ikromov
This series fixes a NULL pointer dereference and a negative rate index
bug on the rtw89 TX path for injected frames, makes monitor mode
receive frames that are currently dropped by the hardware RX filter
without disabling hardware Auto-ACK on concurrent active interfaces,
enables raw 802.11 frame injection on standalone and concurrent
MONITOR_FLAG_ACTIVE monitor interfaces, and restores the operating
channel when leaving idle on devices using mac80211 chanctx emulation.
Patches 1-2 are standalone bug fixes with Fixes: and Cc: stable tags:
1. drop frames without a vif instead of dereferencing NULL in
rtw89_ops_tx() (reachable when injecting on a passive monitor
interface while a station interface is up)
2. treat the radiotap "no rate" index (-1) as signed in
rtw89_core_tx_update_injection()
Patch 3 retains FIF_CONTROL | FIF_PSPOLL, tracks FIF_OTHER_BSS in
rtwdev->hal.rx_fltr_other_bss, and clears target-address, multicast,
CAM, beacon check, and UID filter drop bits whenever B_AX_SNIFFER_MODE
or rx_fltr_other_bss is active (including across scan/ROC/MAC reinit
restores) while keeping B_AX_SNIFFER_MODE restricted to pure passive
monitor mode so hardware Auto-ACK remains intact for concurrent STA/AP
and MONITOR_FLAG_ACTIVE interfaces.
Patches 4-9 enable raw frame injection on standalone and active monitor
interfaces:
4. RCU protection and sole-monitor tracking for pure_monitor_mode_vif
with optional deferred RCU synchronization
5. RTW89_SELF_ROLE_AP for monitor interfaces so the JoinInfo H2C
initializes the MAC ID's CMAC control entry without arming client
TBTT tracking or AP beacon transmission
6. resolve standalone NULL-vif TX via pure_monitor_mode_vif and direct
MONITOR_FLAG_ACTIVE vif TX via rtwvif->mon_tx_ready with coalesced
synchronize_rcu(), track rtwdev->monitor_vifs for radiotap/PHYSTS
enablement, parse frequency IEs before pushing VHT/HE/EHT radiotap
headers during concurrent scans, and validate linear 802.11 header
lengths via skb_headlen()
7. route injected control frames through the management queue and
guard hdr->seq_ctrl reads on short/control frames
8. skip host-side IP/UDP traffic stats, WoWLAN AKM parsing, BT-coex,
HE HTC, and A-MPDU/TXQ aggregation hooks on injected frames
9. honor IEEE80211_TX_CTL_ASSIGN_SEQ, IEEE80211_TX_RC_USE_RTS_CTS,
IEEE80211_RADIOTAP_DATA_RETRIES (hw->max_rate_tries = 63), and
IEEE80211_TX_CTL_NO_ACK across AX/BE TX descriptors and PCIe/RPQ
TX completion status
Patch 10 restores hw->conf.chandef when leaving idle or toggling
monitor mode on devices without assign_vif_chanctx while RTW89_PHY_0 is
inactive after rtw89_ops_stop() / rtw89_enter_ips().
Verification:
- Firmware behavior in patches 3, 5, and 10 was verified against
RTL8852AE firmware 0.13.36.2 (JoinInfo H2C role/CCTL handling,
scan-offload RX filter pause/restore, and absence of BEACON_FILTER
forcing no_chanctx even with support_chanctx_num == 1).
- Each patch builds cleanly in isolation on rtw-next (Linux 7.4-rc1)
with W=1, C=1 (sparse), and CONFIG_PROVE_LOCKING=y, and passes
checkpatch.pl --strict without warnings.
- Runtime hardware validation was conducted on RTL8852AE (10ec:8852,
firmware rtw89/rtw8852a_fw-1.bin 0.13.36.2, Linux 7.1.5): promiscuous
RX across down/up restart (ftrace confirmed channel/RFK programming),
NULL-vif drop on passive monitor while a station interface is up vs
concurrent MONITOR_FLAG_ACTIVE raw TX + Auto-ACK preservation,
10B ACK / 16B RTS / SN=1337 Data & AssocReq raw TX, NO_ACK vs
DATA_RETRIES tx_retry_lmt telemetry verification, and 25 concurrent
del/add RCU stress cycles (0 dmesg alerts).
RTL8852B/C, RTL8851B, RTL8922A (BE), USB devices, and DBCC setups were
not runtime-tested.
Changes in v5:
- Split the NULL vif fix and signed rate index fix out as standalone
patches 1-2 with Fixes: and Cc: stable tags.
- Split monitor injection into focused patches 5-9 and support
concurrent MONITOR_FLAG_ACTIVE interfaces alongside standalone
passive monitors while coalescing synchronize_rcu() on teardown.
- Route only injected control frames through the management path so
mac80211-generated BlockAckReq frames keep the normal data path.
- Separate FIF_OTHER_BSS drop-mask clearing from B_AX_SNIFFER_MODE so
arbitrary-BSS RX works on MONITOR_FLAG_ACTIVE without suppressing
hardware Auto-ACK on active interfaces.
- Advertise hw->max_rate_tries = 63, honor rates[0].count, and avoid
false tx_retry_lmt increments on single-shot NO_ACK completions.
- Gate channel restoration on leaving idle / monitor changes with
!rtwdev->ops->assign_vif_chanctx so non-chanctx devices (such as
RTL8852AE) activate RTW89_PHY_0 for both standalone and active
monitor interfaces.
Changes in v4:
- Use full legal name in From/Signed-off-by.
- Retain FIF_CONTROL and FIF_PSPOLL and clear B_AX_A_MC and
B_AX_A_MC_LIST_CAM_MATCH in monitor mode.
- Split RCU conversion of pure_monitor_mode_vif into its own patch.
- Handle injected control frames, negative rate indices, NO_ACK, and
sequence number preservation.
- Move monitor restart channel restoration into rtw89_ops_config().
Changes in v3:
- Split into a patch series.
- Dropped direct register writes in favor of driver abstractions.
- Added RCU synchronization around pure_monitor_mode_vif.
v4: not sent to the list
v3: https://lore.kernel.org/linux-wireless/20261104203051.564-1-owner@ph4ntom-rev.uz/
v2: https://lore.kernel.org/linux-wireless/179371849554.20972.16232816164394690660@ph4ntom-rev.uz/
v1 (RFC): https://lore.kernel.org/linux-wireless/1a196d6dfbc.35537d221913104450.3720060455831933789@zoho.com/
Enver Ikromov (10):
wifi: rtw89: avoid NULL vif dereference in rtw89_ops_tx()
wifi: rtw89: handle negative rate index for injected frames
wifi: rtw89: fix RX filter configuration for monitor mode
wifi: rtw89: protect pure_monitor_mode_vif with RCU
wifi: rtw89: use AP self role for monitor interfaces
wifi: rtw89: transmit frames from monitor interfaces
wifi: rtw89: send injected control frames through the management path
wifi: rtw89: skip host-side TX hooks for injected frames
wifi: rtw89: honor ASSIGN_SEQ, retries, and NO_ACK for injected frames
wifi: rtw89: restore channel when leaving idle on non-chanctx devices
drivers/net/wireless/realtek/rtw89/core.c | 144 ++++++++++++++----
drivers/net/wireless/realtek/rtw89/core.h | 17 ++-
drivers/net/wireless/realtek/rtw89/mac.c | 3 +-
drivers/net/wireless/realtek/rtw89/mac.h | 18 +++
drivers/net/wireless/realtek/rtw89/mac80211.c | 131 +++++++++++++++-
drivers/net/wireless/realtek/rtw89/mac_be.c | 3 +-
drivers/net/wireless/realtek/rtw89/pci.c | 3 +-
drivers/net/wireless/realtek/rtw89/phy.c | 2 +-
8 files changed, 278 insertions(+), 43 deletions(-)
base-commit: 61a5eb87b2d9b4d5e353780b781cf691f39ba9e1
--
2.56.0.windows.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH rtw-next v5 01/10] wifi: rtw89: avoid NULL vif dereference in rtw89_ops_tx()
2026-11-13 23:52 [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes Enver Ikromov
@ 2026-11-13 23:52 ` Enver Ikromov
2026-11-15 3:23 ` Ping-Ke Shih
2026-11-13 23:52 ` [PATCH rtw-next v5 02/10] wifi: rtw89: handle negative rate index for injected frames Enver Ikromov
` (9 subsequent siblings)
10 siblings, 1 reply; 15+ messages in thread
From: Enver Ikromov @ 2026-11-13 23:52 UTC (permalink / raw)
To: Ping-Ke Shih; +Cc: linux-wireless, linux-kernel, Enver Ikromov
rtw89 sets IEEE80211_HW_WANT_MONITOR_VIF but not
IEEE80211_HW_QUEUE_CONTROL. For frames transmitted on a monitor
interface, ieee80211_tx_frags() therefore passes
info->control.vif == NULL to the driver whenever local->monitor_sdata
does not exist, e.g. when a raw frame is sent on a monitor interface
while a station interface is also up and the frame's addr2 does not
match any running interface.
rtw89_ops_tx() unconditionally converts the vif with vif_to_rtwvif()
and dereferences rtwvif->offchan, so such a frame makes the kernel
access memory at a small offset from NULL.
Drop frames without a vif, as there is no MAC ID or port they could
be transmitted on.
Fixes: a0e97ae3f332 ("wifi: rtw89: add ieee80211::remain_on_channel ops")
Cc: stable@vger.kernel.org
Signed-off-by: Enver Ikromov <owner@ph4ntom-rev.uz>
---
drivers/net/wireless/realtek/rtw89/mac80211.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index 9134cdc..5a12639 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -23,11 +23,18 @@ static void rtw89_ops_tx(struct ieee80211_hw *hw,
struct rtw89_dev *rtwdev = hw->priv;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_vif *vif = info->control.vif;
- struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
struct ieee80211_sta *sta = control->sta;
u32 flags = IEEE80211_SKB_CB(skb)->flags;
+ struct rtw89_vif *rtwvif;
int ret, qsel;
+ if (unlikely(!vif)) {
+ ieee80211_free_txskb(hw, skb);
+ return;
+ }
+
+ rtwvif = vif_to_rtwvif(vif);
+
if (rtwvif->offchan && !(flags & IEEE80211_TX_CTL_TX_OFFCHAN) && sta) {
struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
--
2.56.0.windows.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH rtw-next v5 02/10] wifi: rtw89: handle negative rate index for injected frames
2026-11-13 23:52 [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 01/10] wifi: rtw89: avoid NULL vif dereference in rtw89_ops_tx() Enver Ikromov
@ 2026-11-13 23:52 ` Enver Ikromov
2026-11-15 3:38 ` Ping-Ke Shih
2026-11-13 23:52 ` [PATCH rtw-next v5 03/10] wifi: rtw89: fix RX filter configuration for monitor mode Enver Ikromov
` (8 subsequent siblings)
10 siblings, 1 reply; 15+ messages in thread
From: Enver Ikromov @ 2026-11-13 23:52 UTC (permalink / raw)
To: Ping-Ke Shih; +Cc: linux-wireless, linux-kernel, Enver Ikromov
When the radiotap header of an injected frame carries no rate,
info->control.rates[0].idx is -1. rtw89_core_tx_update_injection()
stores the index in a u8, so the value becomes 0xff and is added to
the CCK1/OFDM6 base, programming an invalid hardware rate into the TX
descriptor.
Use a signed index. If it is negative, keep the rate already selected
by rtw89_core_tx_update_mgmt_info() for management frames, and fall
back to data_retry_lowest_rate (or OFDM6 when
IEEE80211_TX_CTL_NO_CCK_RATE is set) for data frames.
Fixes: e96abe4fd7cd ("wifi: rtw89: consider data rate/bandwidth/GI for injected packets")
Cc: stable@vger.kernel.org
Signed-off-by: Enver Ikromov <owner@ph4ntom-rev.uz>
---
drivers/net/wireless/realtek/rtw89/core.c | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index b7df97e..527593e 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -1239,12 +1239,25 @@ static void rtw89_core_tx_update_injection(struct rtw89_dev *rtwdev,
enum mac80211_rate_control_flags flags = info->control.rates[0].flags;
struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
const struct rtw89_chan *chan;
- u8 idx = info->control.rates[0].idx;
+ s8 idx = info->control.rates[0].idx;
u8 nss, mcs;
desc_info->use_rate = true;
desc_info->dis_data_fb = true;
+ /* No rate was given in the radiotap header. Management frames
+ * already carry the rate from rtw89_core_tx_update_mgmt_info(), so
+ * only data frames need a fallback.
+ */
+ if (idx < 0) {
+ if (tx_req->tx_type == RTW89_CORE_TX_TYPE_DATA)
+ desc_info->data_rate =
+ info->flags & IEEE80211_TX_CTL_NO_CCK_RATE ?
+ RTW89_HW_RATE_OFDM6 :
+ desc_info->data_retry_lowest_rate;
+ return;
+ }
+
if (flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
desc_info->data_bw = 3;
else if (flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
--
2.56.0.windows.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH rtw-next v5 03/10] wifi: rtw89: fix RX filter configuration for monitor mode
2026-11-13 23:52 [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 01/10] wifi: rtw89: avoid NULL vif dereference in rtw89_ops_tx() Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 02/10] wifi: rtw89: handle negative rate index for injected frames Enver Ikromov
@ 2026-11-13 23:52 ` Enver Ikromov
2026-11-15 3:48 ` Ping-Ke Shih
2026-11-13 23:52 ` [PATCH rtw-next v5 04/10] wifi: rtw89: protect pure_monitor_mode_vif with RCU Enver Ikromov
` (7 subsequent siblings)
10 siblings, 1 reply; 15+ messages in thread
From: Enver Ikromov @ 2026-11-13 23:52 UTC (permalink / raw)
To: Ping-Ke Shih; +Cc: linux-wireless, linux-kernel, Enver Ikromov
When entering monitor mode or enabling FIF_OTHER_BSS,
rtw89_ops_configure_filter() updates B_AX_SNIFFER_MODE or clears
B_AX_A_A1_MATCH in hal.rx_fltr, but leaves hardware target-address,
multicast, address CAM, beacon check, and UID drop masks active unless
specific FIF_* flags happen to toggle:
- B_AX_A_UC_CAM_MATCH and B_AX_A_BC_CAM_MATCH are only cleared when
FIF_PROBE_REQ changes, dropping unicast and broadcast frames from
arbitrary BSSs without a CAM entry in hardware.
- B_AX_A_MC is only cleared when FIF_ALLMULTI is set, and
B_AX_A_MC_LIST_CAM_MATCH is never cleared, dropping multicast frames
when a monitor socket is opened without IFF_PROMISC.
- B_AX_UID_FILTER_MASK is initialized in DEFAULT_AX_RX_FLTR and
DEFAULT_BE_RX_FLTR via mac->default_rx_fltr and is never cleared by
any FIF_* flag.
- B_AX_A_A1_MATCH, B_AX_A_BC, and B_AX_A_BCN_CHK_EN must stay cleared
whenever B_AX_SNIFFER_MODE or FIF_OTHER_BSS is active, including
after rtw89_hw_scan_complete_cb(), rtw89_roc_end(), or MAC reinit
writes rtwdev->hal.rx_fltr back to R_AX_RX_FLTR_OPT /
R_BE_RX_FLTR_OPT.
- FIF_CONTROL and FIF_PSPOLL are masked out of *new_flags even though
rx_fltr_init_ax() and rx_fltr_init_be() already forward control
frames to the host via R_AX_CTRL_FLTR / R_BE_CTRL_FLTR.
Retain FIF_CONTROL and FIF_PSPOLL in *new_flags, record FIF_OTHER_BSS
in hal.rx_fltr_other_bss so active monitor interfaces with
MONITOR_FLAG_OTHER_BSS (and concurrent passive monitors) receive
arbitrary-BSS frames without setting B_AX_SNIFFER_MODE, and add
rtw89_mac_refine_rx_fltr() to clear the drop masks without mutating
baseline rtwdev->hal.rx_fltr across mode transitions. The bit positions
in R_AX_RX_FLTR_OPT and R_BE_RX_FLTR_OPT are identical.
Signed-off-by: Enver Ikromov <owner@ph4ntom-rev.uz>
---
drivers/net/wireless/realtek/rtw89/core.h | 1 +
drivers/net/wireless/realtek/rtw89/mac.c | 3 ++-
drivers/net/wireless/realtek/rtw89/mac.h | 16 ++++++++++++++++
drivers/net/wireless/realtek/rtw89/mac80211.c | 5 ++++-
drivers/net/wireless/realtek/rtw89/mac_be.c | 3 ++-
5 files changed, 25 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 7f84ee5..7be8810 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -6499,6 +6499,7 @@ struct rtw89_hal {
u8 cv;
u8 cid; /* enum rtw89_core_chip_cid */
u8 acv;
+ bool rx_fltr_other_bss;
u16 aid; /* enum rtw89_core_chip_aid */
u32 antenna_tx;
u32 antenna_rx;
diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
index 41796bf..06fb263 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.c
+++ b/drivers/net/wireless/realtek/rtw89/mac.c
@@ -2681,6 +2681,7 @@ void rtw89_mac_set_rx_fltr(struct rtw89_dev *rtwdev, u8 mac_idx, u32 rx_fltr)
u32 reg;
u32 val;
+ rx_fltr = rtw89_mac_refine_rx_fltr(rtwdev, rx_fltr);
reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, mac_idx);
val = rtw89_read32(rtwdev, reg);
@@ -2706,7 +2707,7 @@ static int rx_fltr_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
if (ret)
return ret;
}
- mac_ftlr = rtwdev->hal.rx_fltr;
+ mac_ftlr = rtw89_mac_refine_rx_fltr(rtwdev, rtwdev->hal.rx_fltr);
plcp_ftlr = B_AX_CCK_CRC_CHK | B_AX_CCK_SIG_CHK |
B_AX_LSIG_PARITY_CHK_EN | B_AX_SIGA_CRC_CHK |
B_AX_VHT_SU_SIGB_CRC_CHK | B_AX_VHT_MU_SIGB_CRC_CHK |
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index db42e33..b4a7cb7 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -1494,6 +1494,22 @@ void rtw89_mac_set_edcca_mode_bands(struct rtw89_dev *rtwdev, bool normal)
rtw89_mac_set_edcca_mode(rtwdev, RTW89_MAC_1, normal);
}
+static inline u32 rtw89_mac_refine_rx_fltr(struct rtw89_dev *rtwdev,
+ u32 rx_fltr)
+{
+ if ((rx_fltr & B_AX_SNIFFER_MODE) || rtwdev->hal.rx_fltr_other_bss)
+ rx_fltr &= ~(B_AX_A_A1_MATCH |
+ B_AX_A_BC |
+ B_AX_A_MC |
+ B_AX_A_UC_CAM_MATCH |
+ B_AX_A_BC_CAM_MATCH |
+ B_AX_A_MC_LIST_CAM_MATCH |
+ B_AX_A_BCN_CHK_EN |
+ B_AX_UID_FILTER_MASK);
+
+ return rx_fltr;
+}
+
void rtw89_mac_set_rx_fltr(struct rtw89_dev *rtwdev, u8 mac_idx, u32 rx_fltr);
void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev);
void rtw89_mac_flush_txq(struct rtw89_dev *rtwdev, u32 queues, bool drop);
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index 5a12639..2a3adf0 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -335,7 +335,10 @@ static void rtw89_ops_configure_filter(struct ieee80211_hw *hw,
rtw89_leave_ps_mode(rtwdev);
*new_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_FCSFAIL |
- FIF_BCN_PRBRESP_PROMISC | FIF_PROBE_REQ;
+ FIF_BCN_PRBRESP_PROMISC | FIF_PROBE_REQ |
+ FIF_CONTROL | FIF_PSPOLL;
+
+ rtwdev->hal.rx_fltr_other_bss = !!(*new_flags & FIF_OTHER_BSS);
if (changed_flags & FIF_ALLMULTI) {
if (*new_flags & FIF_ALLMULTI)
diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c b/drivers/net/wireless/realtek/rtw89/mac_be.c
index fa35caf..7147679 100644
--- a/drivers/net/wireless/realtek/rtw89/mac_be.c
+++ b/drivers/net/wireless/realtek/rtw89/mac_be.c
@@ -1328,7 +1328,8 @@ static int rx_fltr_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
rtw89_mac_typ_fltr_opt_be(rtwdev, RTW89_DATA, RTW89_FWD_TO_HOST, mac_idx);
reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_RX_FLTR_OPT, mac_idx);
- rtw89_write32(rtwdev, reg, rtwdev->hal.rx_fltr);
+ rtw89_write32(rtwdev, reg,
+ rtw89_mac_refine_rx_fltr(rtwdev, rtwdev->hal.rx_fltr));
reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_PLCP_HDR_FLTR, mac_idx);
val = B_BE_HE_SIGB_CRC_CHK | B_BE_VHT_MU_SIGB_CRC_CHK |
--
2.56.0.windows.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH rtw-next v5 04/10] wifi: rtw89: protect pure_monitor_mode_vif with RCU
2026-11-13 23:52 [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes Enver Ikromov
` (2 preceding siblings ...)
2026-11-13 23:52 ` [PATCH rtw-next v5 03/10] wifi: rtw89: fix RX filter configuration for monitor mode Enver Ikromov
@ 2026-11-13 23:52 ` Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 05/10] wifi: rtw89: use AP self role for monitor interfaces Enver Ikromov
` (6 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Enver Ikromov @ 2026-11-13 23:52 UTC (permalink / raw)
To: Ping-Ke Shih; +Cc: linux-wireless, linux-kernel, Enver Ikromov
A following patch reads rtwdev->pure_monitor_mode_vif from
rtw89_ops_tx(), which runs without the wiphy lock, while interface
add/remove updates the pointer under the wiphy lock.
Annotate pure_monitor_mode_vif with __rcu, convert existing readers to
rcu_access_pointer() and rcu_dereference_protected(), and recompute
the pointer via rtw89_recalc_pure_monitor_vif() and
rtw89_set_pure_monitor_vif().
Whereas mac80211 only creates local->monitor_sdata while no other
interface is open, a monitor interface opened with MONITOR_FLAG_ACTIVE
is passed directly to drv_add_interface() even alongside an active
station or AP interface. Walking rtwdev->rtwvifs_list ensures
pure_monitor_mode_vif is published if and only if a single monitor
interface is the sole active driver vif, and unpublishes it with
synchronize_rcu() before its link, port, and MAC ID are released.
Signed-off-by: Enver Ikromov <owner@ph4ntom-rev.uz>
---
drivers/net/wireless/realtek/rtw89/core.c | 9 +++-
drivers/net/wireless/realtek/rtw89/core.h | 2 +-
drivers/net/wireless/realtek/rtw89/mac80211.c | 49 +++++++++++++++++--
3 files changed, 53 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 527593e..3447f0e 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -530,7 +530,7 @@ void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev,
struct rtw89_vif_link *rtwvif_link)
{
const struct rtw89_chip_info *chip = rtwdev->chip;
- bool mon = !!rtwdev->pure_monitor_mode_vif;
+ bool mon = !!rcu_access_pointer(rtwdev->pure_monitor_mode_vif);
bool prehdl_link = false;
if (chip->chip_gen != RTW89_CHIP_AX &&
@@ -560,8 +560,13 @@ void rtw89_chip_rfk_channel(struct rtw89_dev *rtwdev,
static void rtw89_chip_rfk_channel_for_pure_mon_vif(struct rtw89_dev *rtwdev,
enum rtw89_phy_idx phy_idx)
{
- struct rtw89_vif *rtwvif = rtwdev->pure_monitor_mode_vif;
+ struct wiphy *wiphy = rtwdev->hw->wiphy;
struct rtw89_vif_link *rtwvif_link;
+ struct rtw89_vif *rtwvif;
+
+ lockdep_assert_wiphy(wiphy);
+ rtwvif = rcu_dereference_protected(rtwdev->pure_monitor_mode_vif,
+ lockdep_is_held(&wiphy->mtx));
if (!rtwvif)
return;
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 7be8810..78f6ef0 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -7832,7 +7832,7 @@ struct rtw89_dev {
int napi_budget_countdown;
struct rtw89_debugfs *debugfs;
- struct rtw89_vif *pure_monitor_mode_vif;
+ struct rtw89_vif __rcu *pure_monitor_mode_vif;
struct rtw89_led led;
/* HCI related data, keep last */
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index 2a3adf0..b38e04f 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -183,6 +183,47 @@ static void __rtw89_ops_remove_iface_link(struct rtw89_dev *rtwdev,
rtw89_mac_remove_vif(rtwdev, rtwvif_link);
}
+static bool rtw89_set_pure_monitor_vif(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *rtwvif, bool sync)
+{
+ struct wiphy *wiphy = rtwdev->hw->wiphy;
+ struct rtw89_vif *old;
+
+ lockdep_assert_wiphy(wiphy);
+
+ old = rcu_dereference_protected(rtwdev->pure_monitor_mode_vif,
+ lockdep_is_held(&wiphy->mtx));
+ if (old == rtwvif)
+ return false;
+
+ rcu_assign_pointer(rtwdev->pure_monitor_mode_vif, rtwvif);
+
+ /* wait for lockless readers still using the previous vif */
+ if (old && sync)
+ synchronize_rcu();
+
+ return !!old;
+}
+
+static bool rtw89_recalc_pure_monitor_vif(struct rtw89_dev *rtwdev,
+ struct rtw89_vif *exclude, bool sync)
+{
+ struct rtw89_vif *sole = NULL;
+ struct rtw89_vif *iter;
+
+ rtw89_for_each_rtwvif(rtwdev, iter) {
+ if (iter == exclude)
+ continue;
+ if (sole || rtwvif_to_vif(iter)->type != NL80211_IFTYPE_MONITOR) {
+ sole = NULL;
+ break;
+ }
+ sole = iter;
+ }
+
+ return rtw89_set_pure_monitor_vif(rtwdev, sole, sync);
+}
+
static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
struct ieee80211_vif *vif)
{
@@ -241,8 +282,7 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
if (ret)
goto unset_link;
- rtwdev->pure_monitor_mode_vif = vif->type == NL80211_IFTYPE_MONITOR ?
- rtwvif : NULL;
+ rtw89_recalc_pure_monitor_vif(rtwdev, NULL, true);
rtw89_recalc_lps(rtwdev);
return 0;
@@ -271,6 +311,9 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw,
rtw89_debug(rtwdev, RTW89_DBG_STATE, "remove vif %pM type %d p2p %d\n",
vif->addr, vif->type, vif->p2p);
+ /* unpublish before tearing down the link, port and MAC ID */
+ rtw89_recalc_pure_monitor_vif(rtwdev, rtwvif, true);
+
wiphy_delayed_work_cancel(hw->wiphy, &rtwvif->roc.roc_work);
rtwvif_link = rtwvif->links[RTW89_VIF_IDLE_LINK_ID];
@@ -290,8 +333,6 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw,
rtw89_core_release_bit_map(rtwdev->hw_port, port);
rtw89_release_mac_id(rtwdev, macid);
- rtwdev->pure_monitor_mode_vif = NULL;
-
rtw89_recalc_lps(rtwdev);
rtw89_enter_ips_by_hwflags(rtwdev);
}
--
2.56.0.windows.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH rtw-next v5 05/10] wifi: rtw89: use AP self role for monitor interfaces
2026-11-13 23:52 [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes Enver Ikromov
` (3 preceding siblings ...)
2026-11-13 23:52 ` [PATCH rtw-next v5 04/10] wifi: rtw89: protect pure_monitor_mode_vif with RCU Enver Ikromov
@ 2026-11-13 23:52 ` Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 06/10] wifi: rtw89: transmit frames from " Enver Ikromov
` (5 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Enver Ikromov @ 2026-11-13 23:52 UTC (permalink / raw)
To: Ping-Ke Shih; +Cc: linux-wireless, linux-kernel, Enver Ikromov
rtw89_vif_type_mapping() leaves net_type and self_role zero for
NL80211_IFTYPE_MONITOR, i.e. RTW89_NET_TYPE_NO_LINK and
RTW89_SELF_ROLE_CLIENT. When rtw89_mac_add_vif() initializes the
interface, rtw89_mac_vif_init() first creates the role via H2C
ROLE_MAINTAIN and then sends JoinInfo with disassoc set (op == 1) and
this client role.
In firmware (verified on RTL8852AE firmware 0.13.36.2), the JoinInfo
H2C handler treats (self_role != RTW89_SELF_ROLE_AP && op == 1) as a
station disconnect request (HAL8852A_Role_Disconnect), which clears the
newly created role's active bit in the firmware role table and skips
initializing its CMAC control table entry (CCTL_ResetByMacid). Frames
queued on that MAC ID are then silently dropped instead of transmitted.
With self_role set to RTW89_SELF_ROLE_AP and net_type kept at
RTW89_NET_TYPE_NO_LINK, the JoinInfo H2C handler initializes the
MAC ID's CMAC control entry and connects the role without enabling
client TBTT tracking (gated on RTW89_SELF_ROLE_CLIENT) or AP beacon
transmission (gated on RTW89_NET_TYPE_AP_MODE). Set both fields
explicitly for monitor interfaces.
Signed-off-by: Enver Ikromov <owner@ph4ntom-rev.uz>
---
drivers/net/wireless/realtek/rtw89/core.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 3447f0e..9cf2b03 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -5756,6 +5756,8 @@ void rtw89_vif_type_mapping(struct rtw89_vif_link *rtwvif_link, bool assoc)
rtwvif_link->self_role = RTW89_SELF_ROLE_CLIENT;
break;
case NL80211_IFTYPE_MONITOR:
+ rtwvif_link->net_type = RTW89_NET_TYPE_NO_LINK;
+ rtwvif_link->self_role = RTW89_SELF_ROLE_AP;
break;
default:
WARN_ON(1);
--
2.56.0.windows.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH rtw-next v5 06/10] wifi: rtw89: transmit frames from monitor interfaces
2026-11-13 23:52 [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes Enver Ikromov
` (4 preceding siblings ...)
2026-11-13 23:52 ` [PATCH rtw-next v5 05/10] wifi: rtw89: use AP self role for monitor interfaces Enver Ikromov
@ 2026-11-13 23:52 ` Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 07/10] wifi: rtw89: send injected control frames through the management path Enver Ikromov
` (4 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Enver Ikromov @ 2026-11-13 23:52 UTC (permalink / raw)
To: Ping-Ke Shih; +Cc: linux-wireless, linux-kernel, Enver Ikromov
Frames injected on a monitor interface reach the driver either through
rtw89_ops_tx() (with info->control.vif == NULL for a passive monitor,
info->control.vif == &sdata->vif for MONITOR_FLAG_ACTIVE, or a running
interface matched by addr2) or, for injected data frames whose addr2
matches an active interface, via wake_tx_queue and
rtw89_core_txq_push().
Passing local->monitor_sdata directly is racy because
ieee80211_del_virtual_monitor() calls drv_remove_interface() before
clearing local->monitor_sdata, so mac80211 may still pass a tearing-down
monitor vif to rtw89_ops_tx() after the driver has released its MAC ID
and port.
In rtw89_ops_tx(), require an active PHY entity and resolve passive
monitor TX through rtwdev->pure_monitor_mode_vif under rcu_read_lock(),
while permitting concurrent MONITOR_FLAG_ACTIVE interfaces to transmit
through their own driver vif while rtwvif->mon_tx_ready is set (clearing
mon_tx_ready and coalescing synchronize_rcu() before teardown). Track
active driver monitor vifs in rtwdev->monitor_vifs via
rtw89_is_monitoring() so concurrent MONITOR_FLAG_ACTIVE interfaces
reserve radiotap headroom and enable PHY status parsing (parsing scan
channel IEs before pushing radiotap headers), and verify skb_headlen()
in rtw89_core_tx_write_link() before reading skb->data.
Signed-off-by: Enver Ikromov <owner@ph4ntom-rev.uz>
---
drivers/net/wireless/realtek/rtw89/core.c | 22 ++++--
drivers/net/wireless/realtek/rtw89/core.h | 10 ++-
drivers/net/wireless/realtek/rtw89/mac80211.c | 71 ++++++++++++++++---
drivers/net/wireless/realtek/rtw89/phy.c | 2 +-
4 files changed, 88 insertions(+), 17 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 9cf2b03..54605f7 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -1450,6 +1450,14 @@ static int rtw89_core_tx_write_link(struct rtw89_dev *rtwdev,
struct rtw89_core_tx_request tx_req = {};
int ret;
+ if (unlikely(IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_INJECTED)) {
+ struct ieee80211_hdr *hdr = (void *)skb->data;
+
+ if (skb_headlen(skb) < sizeof(struct ieee80211_cts) ||
+ skb_headlen(skb) < ieee80211_hdrlen(hdr->frame_control))
+ return -EINVAL;
+ }
+
tx_req.skb = skb;
tx_req.vif = vif;
tx_req.sta = sta;
@@ -2258,7 +2266,7 @@ static int rtw89_core_process_phy_status_ie(struct rtw89_dev *rtwdev,
* scanning that needs to get chan_idx in IE01.
*/
accept = phy_ppdu->to_self || ie == RTW89_PHYSTS_IE01_CMN_OFDM ||
- rtwdev->hw->conf.flags & IEEE80211_CONF_MONITOR;
+ rtw89_is_monitoring(rtwdev);
if (!accept)
return 0;
@@ -2341,8 +2349,7 @@ static int rtw89_core_rx_parse_phy_sts(struct rtw89_dev *rtwdev,
u16 ie_len;
/* for normal mode, mark invalid reports and bypass them */
- accept = phy_ppdu->ie >= RTW89_CCK_PKT ||
- rtwdev->hw->conf.flags & IEEE80211_CONF_MONITOR;
+ accept = phy_ppdu->ie >= RTW89_CCK_PKT || rtw89_is_monitoring(rtwdev);
if (!accept)
return -EINVAL;
@@ -3231,7 +3238,7 @@ void rtw89_core_update_rx_status_by_ppdu(struct rtw89_dev *rtwdev,
struct ieee80211_rx_status *rx_status,
struct rtw89_rx_phy_ppdu *phy_ppdu)
{
- if (!(rtwdev->hw->conf.flags & IEEE80211_CONF_MONITOR))
+ if (!rtw89_is_monitoring(rtwdev))
return;
if (!phy_ppdu)
@@ -3803,7 +3810,7 @@ static void rtw89_core_update_radiotap(struct rtw89_dev *rtwdev,
struct ieee80211_rx_status *rx_status,
struct rtw89_rx_phy_ppdu *phy_ppdu)
{
- if (!(rtwdev->hw->conf.flags & IEEE80211_CONF_MONITOR))
+ if (!rtw89_is_monitoring(rtwdev))
return;
/*
@@ -4029,9 +4036,9 @@ static void rtw89_core_rx_to_mac80211(struct rtw89_dev *rtwdev,
rtw89_core_hw_to_sband_rate(rx_status);
rtw89_core_rx_stats(rtwdev, phy_ppdu, desc_info, skb);
rtw89_core_update_rx_status_by_ppdu(rtwdev, rx_status, phy_ppdu);
- rtw89_core_update_radiotap(rtwdev, desc_info, skb, rx_status, phy_ppdu);
rtw89_core_validate_rx_signal(rx_status);
rtw89_core_update_rx_freq_from_ie(rtwdev, skb, rx_status);
+ rtw89_core_update_radiotap(rtwdev, desc_info, skb, rx_status, phy_ppdu);
rtw89_core_correct_mcc_chan(rtwdev, desc_info, rx_status, phy_ppdu);
/* In low power mode, it does RX in thread context. */
@@ -7577,7 +7584,8 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
hw->wiphy->num_iftype_ext_capab = ARRAY_SIZE(rtw89_iftypes_ext_capa);
}
- hw->wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR;
+ hw->wiphy->features |= NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR |
+ NL80211_FEATURE_ACTIVE_MONITOR;
hw->wiphy->max_scan_ssids = RTW89_SCANOFLD_MAX_SSID;
hw->wiphy->max_scan_ie_len = RTW89_SCANOFLD_MAX_IE_LEN;
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 78f6ef0..7b03154 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -7833,6 +7833,7 @@ struct rtw89_dev {
struct rtw89_debugfs *debugfs;
struct rtw89_vif __rcu *pure_monitor_mode_vif;
+ unsigned int monitor_vifs;
struct rtw89_led led;
/* HCI related data, keep last */
@@ -7870,6 +7871,7 @@ struct rtw89_vif {
struct rtw89_roc roc;
bool offchan;
bool burst_active;
+ bool mon_tx_ready;
enum rtw89_mlo_mode mlo_mode;
struct rtw89_vif_ml_trans ml_trans;
@@ -9323,12 +9325,18 @@ static inline struct rtw89_fw_suit *rtw89_fw_suit_get(struct rtw89_dev *rtwdev,
return &fw_info->normal;
}
+static inline bool rtw89_is_monitoring(struct rtw89_dev *rtwdev)
+{
+ return (rtwdev->hw->conf.flags & IEEE80211_CONF_MONITOR) ||
+ READ_ONCE(rtwdev->monitor_vifs);
+}
+
static inline struct sk_buff *rtw89_alloc_skb_for_rx(struct rtw89_dev *rtwdev,
unsigned int length)
{
struct sk_buff *skb;
- if (rtwdev->hw->conf.flags & IEEE80211_CONF_MONITOR) {
+ if (rtw89_is_monitoring(rtwdev)) {
skb = dev_alloc_skb(length + RTW89_RADIOTAP_ROOM);
if (!skb)
return NULL;
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index b38e04f..c8a6003 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -16,6 +16,12 @@
#include "util.h"
#include "wow.h"
+static bool rtw89_has_active_entity(struct rtw89_dev *rtwdev)
+{
+ return rtw89_get_entity_state(rtwdev, RTW89_PHY_0) ||
+ (rtwdev->dbcc_en && rtw89_get_entity_state(rtwdev, RTW89_PHY_1));
+}
+
static void rtw89_ops_tx(struct ieee80211_hw *hw,
struct ieee80211_tx_control *control,
struct sk_buff *skb)
@@ -28,28 +34,56 @@ static void rtw89_ops_tx(struct ieee80211_hw *hw,
struct rtw89_vif *rtwvif;
int ret, qsel;
- if (unlikely(!vif)) {
- ieee80211_free_txskb(hw, skb);
- return;
- }
+ rcu_read_lock();
- rtwvif = vif_to_rtwvif(vif);
+ if (unlikely(!vif || vif->type == NL80211_IFTYPE_MONITOR)) {
+ if (!rtw89_has_active_entity(rtwdev)) {
+ ieee80211_free_txskb(hw, skb);
+ goto out;
+ }
+
+ /* Passive monitors pass vif == NULL and are only permitted to
+ * transmit when a standalone monitor vif is the sole active
+ * interface; active monitors (MONITOR_FLAG_ACTIVE) pass their
+ * own driver vif and may transmit concurrently while
+ * mon_tx_ready is set. Both paths unpublish and wait for an
+ * RCU grace period before releasing link, port, and MAC ID.
+ */
+ rtwvif = rcu_dereference(rtwdev->pure_monitor_mode_vif);
+ if (!rtwvif && vif) {
+ rtwvif = vif_to_rtwvif(vif);
+ if (!READ_ONCE(rtwvif->mon_tx_ready))
+ rtwvif = NULL;
+ }
+ if (!rtwvif) {
+ ieee80211_free_txskb(hw, skb);
+ goto out;
+ }
+
+ vif = rtwvif_to_vif(rtwvif);
+ info->control.vif = vif;
+ } else {
+ rtwvif = vif_to_rtwvif(vif);
+ }
if (rtwvif->offchan && !(flags & IEEE80211_TX_CTL_TX_OFFCHAN) && sta) {
struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
rtw89_debug(rtwdev, RTW89_DBG_TXRX, "ops_tx during offchan\n");
skb_queue_tail(&rtwsta->roc_queue, skb);
- return;
+ goto out;
}
ret = rtw89_core_tx_write(rtwdev, vif, sta, skb, &qsel);
if (ret) {
rtw89_err(rtwdev, "failed to transmit skb: %d\n", ret);
ieee80211_free_txskb(hw, skb);
- return;
+ goto out;
}
rtw89_core_tx_kick_off(rtwdev, qsel);
+
+out:
+ rcu_read_unlock();
}
static void rtw89_ops_wake_tx_queue(struct ieee80211_hw *hw,
@@ -282,6 +316,13 @@ static int rtw89_ops_add_interface(struct ieee80211_hw *hw,
if (ret)
goto unset_link;
+ if (vif->type == NL80211_IFTYPE_MONITOR) {
+ WRITE_ONCE(rtwvif->mon_tx_ready, true);
+ WRITE_ONCE(rtwdev->monitor_vifs, rtwdev->monitor_vifs + 1);
+ if (rtwdev->monitor_vifs == 1 &&
+ test_bit(RTW89_FLAG_POWERON, rtwdev->flags))
+ rtw89_physts_parsing_init(rtwdev);
+ }
rtw89_recalc_pure_monitor_vif(rtwdev, NULL, true);
rtw89_recalc_lps(rtwdev);
return 0;
@@ -305,6 +346,7 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw,
u8 macid = rtw89_vif_get_main_macid(rtwvif);
u8 port = rtw89_vif_get_main_port(rtwvif);
struct rtw89_vif_link *rtwvif_link;
+ bool need_sync;
lockdep_assert_wiphy(hw->wiphy);
@@ -312,7 +354,13 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw,
vif->addr, vif->type, vif->p2p);
/* unpublish before tearing down the link, port and MAC ID */
- rtw89_recalc_pure_monitor_vif(rtwdev, rtwvif, true);
+ need_sync = rtw89_recalc_pure_monitor_vif(rtwdev, rtwvif, false);
+ if (vif->type == NL80211_IFTYPE_MONITOR && rtwvif->mon_tx_ready) {
+ WRITE_ONCE(rtwvif->mon_tx_ready, false);
+ need_sync = true;
+ }
+ if (need_sync)
+ synchronize_rcu();
wiphy_delayed_work_cancel(hw->wiphy, &rtwvif->roc.roc_work);
@@ -333,6 +381,13 @@ static void rtw89_ops_remove_interface(struct ieee80211_hw *hw,
rtw89_core_release_bit_map(rtwdev->hw_port, port);
rtw89_release_mac_id(rtwdev, macid);
+ if (vif->type == NL80211_IFTYPE_MONITOR && rtwdev->monitor_vifs) {
+ WRITE_ONCE(rtwdev->monitor_vifs, rtwdev->monitor_vifs - 1);
+ if (!rtwdev->monitor_vifs &&
+ test_bit(RTW89_FLAG_POWERON, rtwdev->flags))
+ rtw89_physts_parsing_init(rtwdev);
+ }
+
rtw89_recalc_lps(rtwdev);
rtw89_enter_ips_by_hwflags(rtwdev);
}
diff --git a/drivers/net/wireless/realtek/rtw89/phy.c b/drivers/net/wireless/realtek/rtw89/phy.c
index 795920b..c04fbcf 100644
--- a/drivers/net/wireless/realtek/rtw89/phy.c
+++ b/drivers/net/wireless/realtek/rtw89/phy.c
@@ -7183,7 +7183,7 @@ static void __rtw89_physts_parsing_init(struct rtw89_dev *rtwdev,
u32 val;
u8 i;
- if (rtwdev->hw->conf.flags & IEEE80211_CONF_MONITOR) {
+ if (rtw89_is_monitoring(rtwdev)) {
monitor_mode_mu_ies = BIT(RTW89_PHYSTS_IE09_FTR_0);
if (phy->physt_gen < 2)
monitor_mode_mu_ies |= BIT(RTW89_PHYSTS_IE10_FTR_PLCP_EXT);
--
2.56.0.windows.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH rtw-next v5 07/10] wifi: rtw89: send injected control frames through the management path
2026-11-13 23:52 [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes Enver Ikromov
` (5 preceding siblings ...)
2026-11-13 23:52 ` [PATCH rtw-next v5 06/10] wifi: rtw89: transmit frames from " Enver Ikromov
@ 2026-11-13 23:52 ` Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 08/10] wifi: rtw89: skip host-side TX hooks for injected frames Enver Ikromov
` (3 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Enver Ikromov @ 2026-11-13 23:52 UTC (permalink / raw)
To: Ping-Ke Shih; +Cc: linux-wireless, linux-kernel, Enver Ikromov
rtw89_core_get_tx_type() classifies every frame that is neither a
management nor a null-data frame as data. Injected control frames
such as a 10-byte ACK or 16-byte RTS therefore go through
rtw89_core_tx_update_data_info(), which derives a TID and data queue
from skb->priority and enables AMPDU/QoS related descriptor fields
that make no sense for them.
Classify injected non-data frames as management frames. Frames
generated by mac80211 itself, such as BlockAckReq, are not affected.
In addition, rtw89_core_tx_update_desc_info() reads hdr->seq_ctrl at
offset 22 for every frame. Control frames have no sequence control
field and are shorter than 24 bytes, so only read hdr->seq_ctrl from
non-control frames whose linear header is long enough to carry it.
Signed-off-by: Enver Ikromov <owner@ph4ntom-rev.uz>
---
drivers/net/wireless/realtek/rtw89/core.c | 16 ++++++++++++++--
1 file changed, 14 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 54605f7..7003c24 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -637,12 +637,21 @@ static enum rtw89_core_tx_type
rtw89_core_get_tx_type(struct rtw89_dev *rtwdev,
struct sk_buff *skb)
{
+ struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_hdr *hdr = (void *)skb->data;
__le16 fc = hdr->frame_control;
if (ieee80211_is_mgmt(fc) || ieee80211_is_any_nullfunc(fc))
return RTW89_CORE_TX_TYPE_MGMT;
+ /* Injected control frames have no QoS/TID and no data payload, so
+ * send them through the management path. Control frames built by
+ * mac80211 itself (e.g. BlockAckReq) keep using the data path.
+ */
+ if (unlikely(info->flags & IEEE80211_TX_CTL_INJECTED) &&
+ !ieee80211_is_data(fc))
+ return RTW89_CORE_TX_TYPE_MGMT;
+
return RTW89_CORE_TX_TYPE_DATA;
}
@@ -1299,7 +1308,7 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
enum btc_pkt_type pkt_type;
bool upd_wlan_hdr = false;
bool is_bmc;
- u16 seq;
+ u16 seq = 0;
desc_info->pkt_size = skb->len;
@@ -1315,7 +1324,10 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
else if (tx_req->vif)
desc_info->mlo = ieee80211_vif_is_mld(tx_req->vif);
- seq = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
+ /* control frames (e.g. 10-byte ACK/CTS) have no sequence control */
+ if (!ieee80211_is_ctl(hdr->frame_control) &&
+ skb_headlen(skb) >= sizeof(struct ieee80211_hdr_3addr))
+ seq = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
addr_cam = rtw89_get_addr_cam_of(tx_req->rtwvif_link,
tx_req->rtwsta_link);
if (addr_cam->valid && desc_info->mlo)
--
2.56.0.windows.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH rtw-next v5 08/10] wifi: rtw89: skip host-side TX hooks for injected frames
2026-11-13 23:52 [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes Enver Ikromov
` (6 preceding siblings ...)
2026-11-13 23:52 ` [PATCH rtw-next v5 07/10] wifi: rtw89: send injected control frames through the management path Enver Ikromov
@ 2026-11-13 23:52 ` Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 09/10] wifi: rtw89: honor ASSIGN_SEQ, retries, and NO_ACK " Enver Ikromov
` (2 subsequent siblings)
10 siblings, 0 replies; 15+ messages in thread
From: Enver Ikromov @ 2026-11-13 23:52 UTC (permalink / raw)
To: Ping-Ke Shih; +Cc: linux-wireless, linux-kernel, Enver Ikromov
Several TX hooks assume frames that were built by the local network
stack for an associated link:
- rtw89_traffic_stats_accu() and rtw89_core_tx_btc_spec_pkt_notify()
inspect ip_hdr()/udp_hdr(). For frames injected on a monitor
interface the network header points into the 802.11 header, so
traffic statistics and BT-coexistence notifications are derived
from unrelated bytes.
- rtw89_wow_parse_akm() records the AKM from (Re)Association Request
frames for WoWLAN, which an injected frame must not change.
- rtw89_core_tx_update_he_qos_htc(), rtw89_core_tx_update_ampdu_info(),
and rtw89_core_txq_check_agg() mutate QoS/HTC headers, enable A-MPDU
aggregation, or start/stop BA sessions based on link state, while
injected frames are expected to be sent as supplied.
Skip these hooks when IEEE80211_TX_CTL_INJECTED is set.
Signed-off-by: Enver Ikromov <owner@ph4ntom-rev.uz>
---
drivers/net/wireless/realtek/rtw89/core.c | 17 ++++++++++++-----
1 file changed, 12 insertions(+), 5 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 7003c24..84c12c6 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -1351,9 +1351,11 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
break;
case RTW89_CORE_TX_TYPE_DATA:
rtw89_core_tx_update_data_info(rtwdev, tx_req);
- pkt_type = rtw89_core_tx_btc_spec_pkt_notify(rtwdev, tx_req);
- rtw89_core_tx_update_he_qos_htc(rtwdev, tx_req, pkt_type);
- rtw89_core_tx_update_ampdu_info(rtwdev, tx_req, pkt_type);
+ if (likely(!(info->flags & IEEE80211_TX_CTL_INJECTED))) {
+ pkt_type = rtw89_core_tx_btc_spec_pkt_notify(rtwdev, tx_req);
+ rtw89_core_tx_update_he_qos_htc(rtwdev, tx_req, pkt_type);
+ rtw89_core_tx_update_ampdu_info(rtwdev, tx_req, pkt_type);
+ }
rtw89_core_tx_update_llc_hdr(rtwdev, desc_info, skb);
break;
default:
@@ -1477,8 +1479,10 @@ static int rtw89_core_tx_write_link(struct rtw89_dev *rtwdev,
tx_req.rtwsta_link = rtwsta_link;
tx_req.with_wait = !!wait;
- rtw89_traffic_stats_accu(rtwdev, rtwvif, skb, true, true);
- rtw89_wow_parse_akm(rtwdev, skb);
+ if (likely(!(IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_INJECTED))) {
+ rtw89_traffic_stats_accu(rtwdev, rtwvif, skb, true, true);
+ rtw89_wow_parse_akm(rtwdev, skb);
+ }
rtw89_core_tx_update_desc_info(rtwdev, &tx_req);
rtw89_core_tx_wake(rtwdev, &tx_req);
@@ -4740,6 +4744,9 @@ static void rtw89_core_txq_check_agg(struct rtw89_dev *rtwdev,
struct ieee80211_sta *sta = txq->sta;
struct rtw89_sta *rtwsta = sta_to_rtwsta_safe(sta);
+ if (unlikely(IEEE80211_SKB_CB(skb)->flags & IEEE80211_TX_CTL_INJECTED))
+ return;
+
if (test_bit(RTW89_TXQ_F_FORBID_BA, rtwtxq->flags))
return;
--
2.56.0.windows.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH rtw-next v5 09/10] wifi: rtw89: honor ASSIGN_SEQ, retries, and NO_ACK for injected frames
2026-11-13 23:52 [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes Enver Ikromov
` (7 preceding siblings ...)
2026-11-13 23:52 ` [PATCH rtw-next v5 08/10] wifi: rtw89: skip host-side TX hooks for injected frames Enver Ikromov
@ 2026-11-13 23:52 ` Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 10/10] wifi: rtw89: restore channel when leaving idle on non-chanctx devices Enver Ikromov
2026-11-15 3:12 ` [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes Ping-Ke Shih
10 siblings, 0 replies; 15+ messages in thread
From: Enver Ikromov @ 2026-11-13 23:52 UTC (permalink / raw)
To: Ping-Ke Shih; +Cc: linux-wireless, linux-kernel, Enver Ikromov
For injected frames, rtw89_core_tx_update_injection() only applies
the radiotap rate and leaves several TX descriptor and completion
settings mismatched with the radiotap flags:
- The management path sets hw_ssn_sel/hw_seq_mode (and MLO links set
upd_wlan_hdr), overwriting user-supplied sequence numbers when
IEEE80211_TX_CTL_ASSIGN_SEQ is not set, and leaving hw_seq_mode
enabled even on injected control frames that have no seq_ctrl field.
Conversely, injected data frames leave hw_seq_mode unset when
ASSIGN_SEQ is requested on a monitor interface.
- Unicast frames unconditionally set RTS_EN = 1 and HW_RTS_EN = 1 in
txwd_info4. On normal traffic HW_RTS_EN = 1 gates RTS on the MAC
length/duration threshold (4080B / 2816us), whereas for injected
frames RTS_EN must follow IEEE80211_TX_RC_USE_RTS_CTS with
HW_RTS_EN = 0 so short frames requesting RTS/CTS actually emit RTS.
- IEEE80211_TX_CTL_NO_ACK (e.g. IEEE80211_RADIOTAP_F_TX_NOACK) neither
sets BE_TXD_BODY6_NO_ACK on Wi-Fi 7 descriptors nor bounds retries,
causing unacknowledged frames to be retransmitted up to the retry
limit. Note that Wi-Fi 6 TXWD v0 chips (RTL8852A/B, RTL8851B) have
no dedicated per-packet NO_ACK descriptor bit and rely on
tx_cnt_lmt = 1 to suppress retransmissions; when that single attempt
completes with RTW89_TX_RETRY_LIMIT, suppress false tx_retry_lmt
accounting in rtw89_pci_tx_status() and set
IEEE80211_TX_STAT_NOACK_TRANSMITTED in rtw89_tx_rpt_tx_status() too.
- hw->max_rate_tries is left at the mac80211 default (4), truncating
IEEE80211_RADIOTAP_DATA_RETRIES, and info->control.rates[0].count is
ignored when a radiotap rate is specified.
- Positive radiotap HT/VHT/legacy rate indices are added to the table
base without clamping to the chip's valid MCS or legacy rate bounds.
Configure hardware sequence assignment according to
IEEE80211_TX_CTL_ASSIGN_SEQ (and never on control frames), drive
rts_en and hw_rts_en for radiotap RTS/CTS, advertise
RTW89_TX_DATA_CNT_LMT_MAX (63) in hw->max_rate_tries, honor
rates[0].count and NO_ACK descriptor/status semantics, and clamp
positive radiotap rate indices to valid hardware ranges.
Signed-off-by: Enver Ikromov <owner@ph4ntom-rev.uz>
---
drivers/net/wireless/realtek/rtw89/core.c | 63 ++++++++++++++++++-----
drivers/net/wireless/realtek/rtw89/core.h | 4 ++
drivers/net/wireless/realtek/rtw89/mac.h | 2 +
drivers/net/wireless/realtek/rtw89/pci.c | 3 +-
4 files changed, 58 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
index 84c12c6..7d174d2 100644
--- a/drivers/net/wireless/realtek/rtw89/core.c
+++ b/drivers/net/wireless/realtek/rtw89/core.c
@@ -1252,12 +1252,43 @@ static void rtw89_core_tx_update_injection(struct rtw89_dev *rtwdev,
const struct rtw89_hw_rate_def *hw_rate = &rtw89_hw_rate[rtwdev->chip->chip_gen];
enum mac80211_rate_control_flags flags = info->control.rates[0].flags;
struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
+ struct ieee80211_hdr *hdr = (void *)tx_req->skb->data;
const struct rtw89_chan *chan;
s8 idx = info->control.rates[0].idx;
- u8 nss, mcs;
+ u8 nss, mcs, max_mcs;
desc_info->use_rate = true;
desc_info->dis_data_fb = true;
+ desc_info->hw_rts_en = false;
+ desc_info->rts_en = (flags & IEEE80211_TX_RC_USE_RTS_CTS) &&
+ !desc_info->is_bmc &&
+ !(info->flags & IEEE80211_TX_CTL_NO_ACK);
+
+ /* Control frames have no seq_ctrl field; otherwise keep the
+ * sequence number supplied by user space unless ASSIGN_SEQ is set.
+ */
+ if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) ||
+ ieee80211_is_ctl(hdr->frame_control)) {
+ desc_info->upd_wlan_hdr = false;
+ desc_info->hw_ssn_sel = 0;
+ desc_info->hw_seq_mode = 0;
+ } else {
+ desc_info->hw_ssn_sel = RTW89_MGMT_HW_SSN_SEL;
+ desc_info->hw_seq_mode = RTW89_MGMT_HW_SEQ_MODE;
+ }
+
+ /* Suppress hardware retransmissions (and ACK waiting on BE) for NO_ACK;
+ * otherwise honor explicit radiotap retry limits when a rate is set.
+ */
+ if (info->flags & IEEE80211_TX_CTL_NO_ACK) {
+ desc_info->no_ack = true;
+ desc_info->tx_cnt_lmt_en = true;
+ desc_info->tx_cnt_lmt = 1;
+ } else if (info->control.rates[0].count) {
+ desc_info->tx_cnt_lmt_en = true;
+ desc_info->tx_cnt_lmt = umin(info->control.rates[0].count,
+ RTW89_TX_DATA_CNT_LMT_MAX);
+ }
/* No rate was given in the radiotap header. Management frames
* already carry the rate from rtw89_core_tx_update_mgmt_info(), so
@@ -1283,16 +1314,20 @@ static void rtw89_core_tx_update_injection(struct rtw89_dev *rtwdev,
desc_info->gi_ltf = 1;
if (flags & IEEE80211_TX_RC_VHT_MCS) {
+ max_mcs = rtwdev->chip->chip_gen == RTW89_CHIP_BE ? 11 : 9;
nss = umin(idx >> 4, ARRAY_SIZE(hw_rate->vht) - 1);
- mcs = idx & 0xf;
+ mcs = umin(idx & 0xf, max_mcs);
desc_info->data_rate = hw_rate->vht[nss] + mcs;
} else if (flags & IEEE80211_TX_RC_MCS) {
- desc_info->data_rate = hw_rate->ht + idx;
+ desc_info->data_rate = hw_rate->ht + umin(idx, 31);
} else {
chan = rtw89_chan_get(rtwdev, tx_req->rtwvif_link->chanctx_idx);
-
- desc_info->data_rate = idx + (chan->band_type == RTW89_BAND_2G ?
- RTW89_HW_RATE_CCK1 : RTW89_HW_RATE_OFDM6);
+ if (chan->band_type == RTW89_BAND_2G)
+ desc_info->data_rate = RTW89_HW_RATE_CCK1 +
+ umin(idx, 11);
+ else
+ desc_info->data_rate = RTW89_HW_RATE_OFDM6 +
+ umin(idx, 7);
}
}
@@ -1341,6 +1376,8 @@ rtw89_core_tx_update_desc_info(struct rtw89_dev *rtwdev,
desc_info->seq = seq;
desc_info->is_bmc = is_bmc;
+ desc_info->rts_en = !is_bmc;
+ desc_info->hw_rts_en = true;
desc_info->wd_page = true;
desc_info->hiq = info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM;
desc_info->upd_wlan_hdr = upd_wlan_hdr;
@@ -1676,9 +1713,8 @@ static __le32 rtw89_build_txwd_info3(struct rtw89_tx_desc_info *desc_info)
static __le32 rtw89_build_txwd_info4(struct rtw89_tx_desc_info *desc_info)
{
- bool rts_en = !desc_info->is_bmc;
- u32 dword = FIELD_PREP(RTW89_TXWD_INFO4_RTS_EN, rts_en) |
- FIELD_PREP(RTW89_TXWD_INFO4_HW_RTS_EN, 1) |
+ u32 dword = FIELD_PREP(RTW89_TXWD_INFO4_RTS_EN, desc_info->rts_en) |
+ FIELD_PREP(RTW89_TXWD_INFO4_HW_RTS_EN, desc_info->hw_rts_en) |
FIELD_PREP(RTW89_TXWD_INFO4_SW_DEFINE, desc_info->sn);
return cpu_to_le32(dword);
@@ -1819,7 +1855,8 @@ static __le32 rtw89_build_txwd_body5_v2(struct rtw89_tx_desc_info *desc_info)
static __le32 rtw89_build_txwd_body6_v2(struct rtw89_tx_desc_info *desc_info)
{
- u32 dword = FIELD_PREP(BE_TXD_BODY6_UPD_WLAN_HDR, desc_info->upd_wlan_hdr);
+ u32 dword = FIELD_PREP(BE_TXD_BODY6_NO_ACK, desc_info->no_ack) |
+ FIELD_PREP(BE_TXD_BODY6_UPD_WLAN_HDR, desc_info->upd_wlan_hdr);
return cpu_to_le32(dword);
}
@@ -1881,9 +1918,8 @@ static __le32 rtw89_build_txwd_info2_v3(struct rtw89_tx_desc_info *desc_info)
static __le32 rtw89_build_txwd_info4_v2(struct rtw89_tx_desc_info *desc_info)
{
- bool rts_en = !desc_info->is_bmc;
- u32 dword = FIELD_PREP(BE_TXD_INFO4_RTS_EN, rts_en) |
- FIELD_PREP(BE_TXD_INFO4_HW_RTS_EN, 1);
+ u32 dword = FIELD_PREP(BE_TXD_INFO4_RTS_EN, desc_info->rts_en) |
+ FIELD_PREP(BE_TXD_INFO4_HW_RTS_EN, desc_info->hw_rts_en);
return cpu_to_le32(dword);
}
@@ -7542,6 +7578,7 @@ static int rtw89_core_register_hw(struct rtw89_dev *rtwdev)
hw->queues = IEEE80211_NUM_ACS;
hw->max_rx_aggregation_subframes = chip->max_rx_agg_num;
hw->max_tx_aggregation_subframes = chip->max_tx_agg_num;
+ hw->max_rate_tries = RTW89_TX_DATA_CNT_LMT_MAX;
hw->uapsd_max_sp_len = IEEE80211_WMM_IE_STA_QOSINFO_SP_ALL;
hw->radiotap_mcs_details |= IEEE80211_RADIOTAP_MCS_HAVE_FEC |
diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
index 7b03154..3754ab6 100644
--- a/drivers/net/wireless/realtek/rtw89/core.h
+++ b/drivers/net/wireless/realtek/rtw89/core.h
@@ -1278,6 +1278,7 @@ struct rtw89_tx_desc_info {
bool tx_cnt_lmt_en;
u8 sn: 4;
u8 tx_cnt_lmt: 6;
+#define RTW89_TX_DATA_CNT_LMT_MAX 0x3f
u8 addr_info_nr;
u8 sec_keyid;
u8 sec_type;
@@ -1300,6 +1301,9 @@ struct rtw89_tx_desc_info {
bool stbc;
bool ldpc;
bool upd_wlan_hdr;
+ bool no_ack;
+ bool rts_en;
+ bool hw_rts_en;
bool mlo;
bool sw_mld;
};
diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
index b4a7cb7..6870cc2 100644
--- a/drivers/net/wireless/realtek/rtw89/mac.h
+++ b/drivers/net/wireless/realtek/rtw89/mac.h
@@ -1888,6 +1888,8 @@ void rtw89_tx_rpt_tx_status(struct rtw89_dev *rtwdev, struct sk_buff *skb,
info = IEEE80211_SKB_CB(skb);
ieee80211_tx_info_clear_status(info);
+ if (info->flags & IEEE80211_TX_CTL_NO_ACK)
+ info->flags |= IEEE80211_TX_STAT_NOACK_TRANSMITTED;
if (tx_status == RTW89_TX_DONE)
info->flags |= IEEE80211_TX_STAT_ACK;
else
diff --git a/drivers/net/wireless/realtek/rtw89/pci.c b/drivers/net/wireless/realtek/rtw89/pci.c
index 6d19e75..6c4d6c0 100644
--- a/drivers/net/wireless/realtek/rtw89/pci.c
+++ b/drivers/net/wireless/realtek/rtw89/pci.c
@@ -475,7 +475,8 @@ static void rtw89_pci_tx_status(struct rtw89_dev *rtwdev,
if (tx_status == RTW89_TX_DONE) {
info->flags |= IEEE80211_TX_STAT_ACK;
tx_ring->tx_acked++;
- } else {
+ } else if (!(info->flags & IEEE80211_TX_CTL_NO_ACK) ||
+ tx_status != RTW89_TX_RETRY_LIMIT) {
if (info->flags & IEEE80211_TX_CTL_REQ_TX_STATUS)
rtw89_debug(rtwdev, RTW89_DBG_FW,
"failed to TX of status %x\n", tx_status);
--
2.56.0.windows.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* [PATCH rtw-next v5 10/10] wifi: rtw89: restore channel when leaving idle on non-chanctx devices
2026-11-13 23:52 [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes Enver Ikromov
` (8 preceding siblings ...)
2026-11-13 23:52 ` [PATCH rtw-next v5 09/10] wifi: rtw89: honor ASSIGN_SEQ, retries, and NO_ACK " Enver Ikromov
@ 2026-11-13 23:52 ` Enver Ikromov
2026-11-15 3:12 ` [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes Ping-Ke Shih
10 siblings, 0 replies; 15+ messages in thread
From: Enver Ikromov @ 2026-11-13 23:52 UTC (permalink / raw)
To: Ping-Ke Shih; +Cc: linux-wireless, linux-kernel, Enver Ikromov
rtw89_alloc_ieee80211_hw() disables native chanctx callbacks
(ops->assign_vif_chanctx = NULL) and relies on mac80211 chanctx
emulation via hw->conf.chandef and rtw89_ops_config() whenever
chip->support_chanctx_num == 0 or the loaded firmware lacks
SCAN_OFFLOAD or BEACON_FILTER (for example on RTL8852AE with firmware
0.13.36.2, where support_chanctx_num == 1 but BEACON_FILTER is absent).
When the last monitor interface is brought down or deleted (or all
interfaces become idle), rtw89_ops_stop() / rtw89_enter_ips() powers
down the MAC/BB/RF and clears the RTW89_PHY_0 entity state while
mac80211 retains local->hw.conf.chandef. When a monitor interface
(including a concurrent MONITOR_FLAG_ACTIVE interface alongside an
unassociated STA, where __ieee80211_recalc_idle() clears
IEEE80211_CONF_IDLE without setting IEEE80211_CONF_MONITOR) is brought
up on the same channel, rtw89_ops_start() sets RTW89_FLAG_POWERON
without programming the channel (so rtw89_leave_ips() returns early),
and ieee80211_hw_conf_chan() omits IEEE80211_CONF_CHANGE_CHANNEL
because chandef is unchanged, leaving RX/TX silent until a manual
channel change.
In rtw89_ops_config(), when IEEE80211_CONF_CHANGE_IDLE or
IEEE80211_CONF_CHANGE_MONITOR leaves the device non-idle on hardware
without assign_vif_chanctx and RTW89_PHY_0 is not yet active, apply
hw->conf.chandef and call rtw89_set_channel(). When
IEEE80211_CONF_CHANGE_CHANNEL has already configured RTW89_PHY_0, the
entity state check avoids redundant RF calibration.
Signed-off-by: Enver Ikromov <owner@ph4ntom-rev.uz>
---
drivers/net/wireless/realtek/rtw89/mac80211.c | 11 +++++++++++
1 file changed, 11 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c b/drivers/net/wireless/realtek/rtw89/mac80211.c
index c8a6003..3649a7a 100644
--- a/drivers/net/wireless/realtek/rtw89/mac80211.c
+++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
@@ -152,6 +152,17 @@ static int rtw89_ops_config(struct ieee80211_hw *hw, int radio_idx, u32 changed)
if (changed & IEEE80211_CONF_CHANGE_MONITOR)
rtw89_physts_parsing_init(rtwdev);
+ if ((changed & (IEEE80211_CONF_CHANGE_IDLE |
+ IEEE80211_CONF_CHANGE_MONITOR)) &&
+ !(hw->conf.flags & IEEE80211_CONF_IDLE) &&
+ !rtwdev->ops->assign_vif_chanctx &&
+ !rtw89_get_entity_state(rtwdev, RTW89_PHY_0) &&
+ cfg80211_chandef_valid(&hw->conf.chandef)) {
+ rtw89_config_entity_chandef(rtwdev, RTW89_CHANCTX_0,
+ &hw->conf.chandef);
+ rtw89_set_channel(rtwdev);
+ }
+
return 0;
}
--
2.56.0.windows.4
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes
2026-11-13 23:52 [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes Enver Ikromov
` (9 preceding siblings ...)
2026-11-13 23:52 ` [PATCH rtw-next v5 10/10] wifi: rtw89: restore channel when leaving idle on non-chanctx devices Enver Ikromov
@ 2026-11-15 3:12 ` Ping-Ke Shih
10 siblings, 0 replies; 15+ messages in thread
From: Ping-Ke Shih @ 2026-11-15 3:12 UTC (permalink / raw)
To: Enver Ikromov; +Cc: linux-wireless, linux-kernel
Enver Ikromov <owner@ph4ntom-rev.uz> wrote:
> v4: not sent to the list
What's wrong?
At first glance, I saw v5. I was confused, because I don't remember I have
seen v4. Please not count your local version.
> v3: https://lore.kernel.org/linux-wireless/20261104203051.564-1-owner@ph4ntom-rev.uz/
> v2: https://lore.kernel.org/linux-wireless/179371849554.20972.16232816164394690660@ph4ntom-rev.uz/
> v1 (RFC):
> https://lore.kernel.org/linux-wireless/1a196d6dfbc.35537d221913104450.3720060455831933789@zoho.com
> /
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH rtw-next v5 01/10] wifi: rtw89: avoid NULL vif dereference in rtw89_ops_tx()
2026-11-13 23:52 ` [PATCH rtw-next v5 01/10] wifi: rtw89: avoid NULL vif dereference in rtw89_ops_tx() Enver Ikromov
@ 2026-11-15 3:23 ` Ping-Ke Shih
0 siblings, 0 replies; 15+ messages in thread
From: Ping-Ke Shih @ 2026-11-15 3:23 UTC (permalink / raw)
To: Enver Ikromov; +Cc: linux-wireless, linux-kernel
Enver Ikromov <owner@ph4ntom-rev.uz> wrote:
> rtw89 sets IEEE80211_HW_WANT_MONITOR_VIF but not
> IEEE80211_HW_QUEUE_CONTROL.
Will this cause vif = NULL? What is their relation?
> For frames transmitted on a monitor
> interface, ieee80211_tx_frags() therefore passes
> info->control.vif == NULL to the driver whenever local->monitor_sdata
> does not exist, e.g. when a raw frame is sent on a monitor interface
> while a station interface is also up and the frame's addr2 does not
> match any running interface.
>
> rtw89_ops_tx() unconditionally converts the vif with vif_to_rtwvif()
> and dereferences rtwvif->offchan, so such a frame makes the kernel
> access memory at a small offset from NULL.
>
> Drop frames without a vif, as there is no MAC ID or port they could
> be transmitted on.
>
> Fixes: a0e97ae3f332 ("wifi: rtw89: add ieee80211::remain_on_channel ops")
> Cc: stable@vger.kernel.org
> Signed-off-by: Enver Ikromov <owner@ph4ntom-rev.uz>
> ---
> drivers/net/wireless/realtek/rtw89/mac80211.c | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c
> b/drivers/net/wireless/realtek/rtw89/mac80211.c
> index 9134cdc..5a12639 100644
> --- a/drivers/net/wireless/realtek/rtw89/mac80211.c
> +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
> @@ -23,11 +23,18 @@ static void rtw89_ops_tx(struct ieee80211_hw *hw,
> struct rtw89_dev *rtwdev = hw->priv;
> struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> struct ieee80211_vif *vif = info->control.vif;
> - struct rtw89_vif *rtwvif = vif_to_rtwvif(vif);
Use vif_to_rtwvif_safe().
> struct ieee80211_sta *sta = control->sta;
> u32 flags = IEEE80211_SKB_CB(skb)->flags;
> + struct rtw89_vif *rtwvif;
> int ret, qsel;
>
> + if (unlikely(!vif)) {
> + ieee80211_free_txskb(hw, skb);
> + return;
> + }
> +
> + rtwvif = vif_to_rtwvif(vif);
> +
> if (rtwvif->offchan && !(flags & IEEE80211_TX_CTL_TX_OFFCHAN) && sta) {
> struct rtw89_sta *rtwsta = sta_to_rtwsta(sta);
>
> --
> 2.56.0.windows.4
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH rtw-next v5 02/10] wifi: rtw89: handle negative rate index for injected frames
2026-11-13 23:52 ` [PATCH rtw-next v5 02/10] wifi: rtw89: handle negative rate index for injected frames Enver Ikromov
@ 2026-11-15 3:38 ` Ping-Ke Shih
0 siblings, 0 replies; 15+ messages in thread
From: Ping-Ke Shih @ 2026-11-15 3:38 UTC (permalink / raw)
To: Enver Ikromov; +Cc: linux-wireless, linux-kernel
Enver Ikromov <owner@ph4ntom-rev.uz> wrote:
> When the radiotap header of an injected frame carries no rate,
> info->control.rates[0].idx is -1.
> rtw89_core_tx_update_injection()
> stores the index in a u8, so the value becomes 0xff and is added to
> the CCK1/OFDM6 base, programming an invalid hardware rate into the TX
> descriptor.
I don't prefer to describe function name in commit message. Just
describe the problem you encountered and how to fix it.
For this patch, you want to handle the rate idx < 0 case, and solution
is set rate to 1M and 6M for 2GHz band and others respectively, right?
I guess LLM help to generate this. Code flow is not important to
commit message. The patch should explain the flow itself.
>
> Use a signed index. If it is negative, keep the rate already selected
> by rtw89_core_tx_update_mgmt_info() for management frames, and fall
> back to data_retry_lowest_rate (or OFDM6 when
> IEEE80211_TX_CTL_NO_CCK_RATE is set) for data frames.
>
> Fixes: e96abe4fd7cd ("wifi: rtw89: consider data rate/bandwidth/GI for injected packets")
> Cc: stable@vger.kernel.org
> Signed-off-by: Enver Ikromov <owner@ph4ntom-rev.uz>
> ---
> drivers/net/wireless/realtek/rtw89/core.c | 15 ++++++++++++++-
> 1 file changed, 14 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/net/wireless/realtek/rtw89/core.c b/drivers/net/wireless/realtek/rtw89/core.c
> index b7df97e..527593e 100644
> --- a/drivers/net/wireless/realtek/rtw89/core.c
> +++ b/drivers/net/wireless/realtek/rtw89/core.c
> @@ -1239,12 +1239,25 @@ static void rtw89_core_tx_update_injection(struct rtw89_dev *rtwdev,
> enum mac80211_rate_control_flags flags = info->control.rates[0].flags;
> struct rtw89_tx_desc_info *desc_info = &tx_req->desc_info;
> const struct rtw89_chan *chan;
> - u8 idx = info->control.rates[0].idx;
> + s8 idx = info->control.rates[0].idx;
> u8 nss, mcs;
>
> desc_info->use_rate = true;
> desc_info->dis_data_fb = true;
>
> + /* No rate was given in the radiotap header. Management frames
> + * already carry the rate from rtw89_core_tx_update_mgmt_info(), so
> + * only data frames need a fallback.
> + */
> + if (idx < 0) {
> + if (tx_req->tx_type == RTW89_CORE_TX_TYPE_DATA)
> + desc_info->data_rate =
> + info->flags & IEEE80211_TX_CTL_NO_CCK_RATE ?
> + RTW89_HW_RATE_OFDM6 :
> + desc_info->data_retry_lowest_rate;
> + return;
> + }
> +
How about just set idx = 0 if idx < 0? The existing code can select valid rate,
since any rate is well for the case idx < 0.
> if (flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
> desc_info->data_bw = 3;
> else if (flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
> --
> 2.56.0.windows.4
>
^ permalink raw reply [flat|nested] 15+ messages in thread
* RE: [PATCH rtw-next v5 03/10] wifi: rtw89: fix RX filter configuration for monitor mode
2026-11-13 23:52 ` [PATCH rtw-next v5 03/10] wifi: rtw89: fix RX filter configuration for monitor mode Enver Ikromov
@ 2026-11-15 3:48 ` Ping-Ke Shih
0 siblings, 0 replies; 15+ messages in thread
From: Ping-Ke Shih @ 2026-11-15 3:48 UTC (permalink / raw)
To: Enver Ikromov; +Cc: linux-wireless, linux-kernel
Enver Ikromov <owner@ph4ntom-rev.uz> wrote:
> When entering monitor mode or enabling FIF_OTHER_BSS,
> rtw89_ops_configure_filter() updates B_AX_SNIFFER_MODE or clears
> B_AX_A_A1_MATCH in hal.rx_fltr, but leaves hardware target-address,
> multicast, address CAM, beacon check, and UID drop masks active unless
> specific FIF_* flags happen to toggle:
Please describe your purpose. For example, describe which kind of
packets you want to capture, but current settings misbehavior. Then,
I can ask internally to know if you patch is necessary or not.
>
> - B_AX_A_UC_CAM_MATCH and B_AX_A_BC_CAM_MATCH are only cleared when
> FIF_PROBE_REQ changes, dropping unicast and broadcast frames from
> arbitrary BSSs without a CAM entry in hardware.
> - B_AX_A_MC is only cleared when FIF_ALLMULTI is set, and
> B_AX_A_MC_LIST_CAM_MATCH is never cleared, dropping multicast frames
> when a monitor socket is opened without IFF_PROMISC.
> - B_AX_UID_FILTER_MASK is initialized in DEFAULT_AX_RX_FLTR and
> DEFAULT_BE_RX_FLTR via mac->default_rx_fltr and is never cleared by
> any FIF_* flag.
> - B_AX_A_A1_MATCH, B_AX_A_BC, and B_AX_A_BCN_CHK_EN must stay cleared
> whenever B_AX_SNIFFER_MODE or FIF_OTHER_BSS is active, including
> after rtw89_hw_scan_complete_cb(), rtw89_roc_end(), or MAC reinit
> writes rtwdev->hal.rx_fltr back to R_AX_RX_FLTR_OPT /
> R_BE_RX_FLTR_OPT.
> - FIF_CONTROL and FIF_PSPOLL are masked out of *new_flags even though
> rx_fltr_init_ax() and rx_fltr_init_be() already forward control
> frames to the host via R_AX_CTRL_FLTR / R_BE_CTRL_FLTR.
>
> Retain FIF_CONTROL and FIF_PSPOLL in *new_flags, record FIF_OTHER_BSS
> in hal.rx_fltr_other_bss so active monitor interfaces with
> MONITOR_FLAG_OTHER_BSS (and concurrent passive monitors) receive
> arbitrary-BSS frames without setting B_AX_SNIFFER_MODE, and add
> rtw89_mac_refine_rx_fltr() to clear the drop masks without mutating
> baseline rtwdev->hal.rx_fltr across mode transitions. The bit positions
> in R_AX_RX_FLTR_OPT and R_BE_RX_FLTR_OPT are identical.
Can you reword commit message generated by LLM? Just point the key
point. Reading lots of stuff spends my time.
>
> Signed-off-by: Enver Ikromov <owner@ph4ntom-rev.uz>
> ---
> drivers/net/wireless/realtek/rtw89/core.h | 1 +
> drivers/net/wireless/realtek/rtw89/mac.c | 3 ++-
> drivers/net/wireless/realtek/rtw89/mac.h | 16 ++++++++++++++++
> drivers/net/wireless/realtek/rtw89/mac80211.c | 5 ++++-
> drivers/net/wireless/realtek/rtw89/mac_be.c | 3 ++-
> 5 files changed, 25 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/net/wireless/realtek/rtw89/core.h b/drivers/net/wireless/realtek/rtw89/core.h
> index 7f84ee5..7be8810 100644
> --- a/drivers/net/wireless/realtek/rtw89/core.h
> +++ b/drivers/net/wireless/realtek/rtw89/core.h
> @@ -6499,6 +6499,7 @@ struct rtw89_hal {
> u8 cv;
> u8 cid; /* enum rtw89_core_chip_cid */
> u8 acv;
> + bool rx_fltr_other_bss;
> u16 aid; /* enum rtw89_core_chip_aid */
> u32 antenna_tx;
> u32 antenna_rx;
> diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
> index 41796bf..06fb263 100644
> --- a/drivers/net/wireless/realtek/rtw89/mac.c
> +++ b/drivers/net/wireless/realtek/rtw89/mac.c
> @@ -2681,6 +2681,7 @@ void rtw89_mac_set_rx_fltr(struct rtw89_dev *rtwdev, u8 mac_idx, u32 rx_fltr)
> u32 reg;
> u32 val;
>
> + rx_fltr = rtw89_mac_refine_rx_fltr(rtwdev, rx_fltr);
> reg = rtw89_mac_reg_by_idx(rtwdev, mac->rx_fltr, mac_idx);
>
> val = rtw89_read32(rtwdev, reg);
> @@ -2706,7 +2707,7 @@ static int rx_fltr_init_ax(struct rtw89_dev *rtwdev, u8 mac_idx)
> if (ret)
> return ret;
> }
> - mac_ftlr = rtwdev->hal.rx_fltr;
> + mac_ftlr = rtw89_mac_refine_rx_fltr(rtwdev, rtwdev->hal.rx_fltr);
> plcp_ftlr = B_AX_CCK_CRC_CHK | B_AX_CCK_SIG_CHK |
> B_AX_LSIG_PARITY_CHK_EN | B_AX_SIGA_CRC_CHK |
> B_AX_VHT_SU_SIGB_CRC_CHK | B_AX_VHT_MU_SIGB_CRC_CHK |
> diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
> index db42e33..b4a7cb7 100644
> --- a/drivers/net/wireless/realtek/rtw89/mac.h
> +++ b/drivers/net/wireless/realtek/rtw89/mac.h
> @@ -1494,6 +1494,22 @@ void rtw89_mac_set_edcca_mode_bands(struct rtw89_dev *rtwdev, bool normal)
> rtw89_mac_set_edcca_mode(rtwdev, RTW89_MAC_1, normal);
> }
>
> +static inline u32 rtw89_mac_refine_rx_fltr(struct rtw89_dev *rtwdev,
> + u32 rx_fltr)
> +{
> + if ((rx_fltr & B_AX_SNIFFER_MODE) || rtwdev->hal.rx_fltr_other_bss)
Can we just do additional in rtw89_ops_configure_filter() under the
condition
rtwdev->hw->conf.flags & IEEE80211_CONF_MONITOR
?
> + rx_fltr &= ~(B_AX_A_A1_MATCH |
> + B_AX_A_BC |
> + B_AX_A_MC |
> + B_AX_A_UC_CAM_MATCH |
> + B_AX_A_BC_CAM_MATCH |
> + B_AX_A_MC_LIST_CAM_MATCH |
> + B_AX_A_BCN_CHK_EN |
> + B_AX_UID_FILTER_MASK);
> +
> + return rx_fltr;
> +}
> +
> void rtw89_mac_set_rx_fltr(struct rtw89_dev *rtwdev, u8 mac_idx, u32 rx_fltr);
> void rtw89_mac_update_rts_threshold(struct rtw89_dev *rtwdev);
> void rtw89_mac_flush_txq(struct rtw89_dev *rtwdev, u32 queues, bool drop);
> diff --git a/drivers/net/wireless/realtek/rtw89/mac80211.c
> b/drivers/net/wireless/realtek/rtw89/mac80211.c
> index 5a12639..2a3adf0 100644
> --- a/drivers/net/wireless/realtek/rtw89/mac80211.c
> +++ b/drivers/net/wireless/realtek/rtw89/mac80211.c
> @@ -335,7 +335,10 @@ static void rtw89_ops_configure_filter(struct ieee80211_hw *hw,
> rtw89_leave_ps_mode(rtwdev);
>
> *new_flags &= FIF_ALLMULTI | FIF_OTHER_BSS | FIF_FCSFAIL |
> - FIF_BCN_PRBRESP_PROMISC | FIF_PROBE_REQ;
> + FIF_BCN_PRBRESP_PROMISC | FIF_PROBE_REQ |
> + FIF_CONTROL | FIF_PSPOLL;
> +
> + rtwdev->hal.rx_fltr_other_bss = !!(*new_flags & FIF_OTHER_BSS);
>
> if (changed_flags & FIF_ALLMULTI) {
> if (*new_flags & FIF_ALLMULTI)
> diff --git a/drivers/net/wireless/realtek/rtw89/mac_be.c
> b/drivers/net/wireless/realtek/rtw89/mac_be.c
> index fa35caf..7147679 100644
> --- a/drivers/net/wireless/realtek/rtw89/mac_be.c
> +++ b/drivers/net/wireless/realtek/rtw89/mac_be.c
> @@ -1328,7 +1328,8 @@ static int rx_fltr_init_be(struct rtw89_dev *rtwdev, u8 mac_idx)
> rtw89_mac_typ_fltr_opt_be(rtwdev, RTW89_DATA, RTW89_FWD_TO_HOST, mac_idx);
>
> reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_RX_FLTR_OPT, mac_idx);
> - rtw89_write32(rtwdev, reg, rtwdev->hal.rx_fltr);
> + rtw89_write32(rtwdev, reg,
> + rtw89_mac_refine_rx_fltr(rtwdev, rtwdev->hal.rx_fltr));
This is just initial state. I suppose rtw89_ops_configure_filter() can change
to proper setting by *new_flags passed from mac80211.
>
> reg = rtw89_mac_reg_by_idx(rtwdev, R_BE_PLCP_HDR_FLTR, mac_idx);
> val = B_BE_HE_SIGB_CRC_CHK | B_BE_VHT_MU_SIGB_CRC_CHK |
> --
> 2.56.0.windows.4
>
^ permalink raw reply [flat|nested] 15+ messages in thread
end of thread, other threads:[~2026-11-15 3:48 UTC | newest]
Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-11-13 23:52 [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 01/10] wifi: rtw89: avoid NULL vif dereference in rtw89_ops_tx() Enver Ikromov
2026-11-15 3:23 ` Ping-Ke Shih
2026-11-13 23:52 ` [PATCH rtw-next v5 02/10] wifi: rtw89: handle negative rate index for injected frames Enver Ikromov
2026-11-15 3:38 ` Ping-Ke Shih
2026-11-13 23:52 ` [PATCH rtw-next v5 03/10] wifi: rtw89: fix RX filter configuration for monitor mode Enver Ikromov
2026-11-15 3:48 ` Ping-Ke Shih
2026-11-13 23:52 ` [PATCH rtw-next v5 04/10] wifi: rtw89: protect pure_monitor_mode_vif with RCU Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 05/10] wifi: rtw89: use AP self role for monitor interfaces Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 06/10] wifi: rtw89: transmit frames from " Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 07/10] wifi: rtw89: send injected control frames through the management path Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 08/10] wifi: rtw89: skip host-side TX hooks for injected frames Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 09/10] wifi: rtw89: honor ASSIGN_SEQ, retries, and NO_ACK " Enver Ikromov
2026-11-13 23:52 ` [PATCH rtw-next v5 10/10] wifi: rtw89: restore channel when leaving idle on non-chanctx devices Enver Ikromov
2026-11-15 3:12 ` [PATCH rtw-next v5 00/10] wifi: rtw89: monitor mode RX filter and raw frame injection fixes Ping-Ke Shih
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®