* [PATCH rtw-next v2 5/5] wifi: rtw89: 8912au: Add support for Mercusys MA37BEH
From: Zenm Chen @ 2026-05-31 23:29 UTC (permalink / raw)
To: linux-wireless, pkshih, rtl8821cerfe2; +Cc: zenmchen
In-Reply-To: <20260531232914.4406-1-zenmchen@gmail.com>
Add the id 2c4e:0125 into the device table to support Mercusys MA37BEH,
a new 8912au-based adapter.
Compile tested only.
Link: https://github.com/morrownr/rtw89/commit/73cd715afee2dda3f670cdae5e40fbeba7d9be36
Signed-off-by: Zenm Chen <zenmchen@gmail.com>
---
v2:
- Add missing "Link: "
---
drivers/net/wireless/realtek/rtw89/rtw8922au.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8922au.c b/drivers/net/wireless/realtek/rtw89/rtw8922au.c
index 347bde171..8d22bb387 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8922au.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8922au.c
@@ -56,6 +56,8 @@ static const struct usb_device_id rtw_8922au_id_table[] = {
.driver_info = (kernel_ulong_t)&rtw89_8922au_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x2001, 0x332b, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8922au_info },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0125, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&rtw89_8922au_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x3625, 0x010a, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8922au_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x37ad, 0x0100, 0xff, 0xff, 0xff),
--
2.53.0
^ permalink raw reply related
* [PATCH rtw-next v2 4/5] wifi: rtw89: 8832cu: Add support for Mercusys MA86XH
From: Zenm Chen @ 2026-05-31 23:29 UTC (permalink / raw)
To: linux-wireless, pkshih, rtl8821cerfe2; +Cc: zenmchen
In-Reply-To: <20260531232914.4406-1-zenmchen@gmail.com>
Add the id 2c4e:0127 into the device table to support Mercusys MA86XH,
a new 8832cu-based adapter.
This also deletes the id 35b2:0502 which doesn't actually exist and was
wrongly added into the driver.
Compile tested only.
Link: https://github.com/morrownr/rtw89/commit/40149484a9db41a4146d2fb4980c92017c5f552c
Link: https://github.com/morrownr/rtw89/commit/c82b4b42a93c2d189a11306701552d4732dc9fb0
Signed-off-by: Zenm Chen <zenmchen@gmail.com>
---
v2:
- Fix a typo in the commit message (actaully -> actually)
- Add missing "Link: "
---
drivers/net/wireless/realtek/rtw89/rtw8852cu.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c
index 790fd1dec..2162dabbb 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852cu.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852cu.c
@@ -53,9 +53,9 @@ static const struct usb_device_id rtw_8852cu_id_table[] = {
.driver_info = (kernel_ulong_t)&rtw89_8852cu_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x28de, 0x2432, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852cu_info },
- { USB_DEVICE_AND_INTERFACE_INFO(0x2c7c, 0x8206, 0xff, 0xff, 0xff),
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0127, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852cu_info },
- { USB_DEVICE_AND_INTERFACE_INFO(0x35b2, 0x0502, 0xff, 0xff, 0xff),
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2c7c, 0x8206, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852cu_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x35bc, 0x0101, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852cu_info },
--
2.53.0
^ permalink raw reply related
* [PATCH rtw-next v2 3/5] wifi: rtw89: 8832bu: Add support for I-O DATA WN-DAX1200U
From: Zenm Chen @ 2026-05-31 23:29 UTC (permalink / raw)
To: linux-wireless, pkshih, rtl8821cerfe2; +Cc: zenmchen
In-Reply-To: <20260531232914.4406-1-zenmchen@gmail.com>
Add the id 04bb:095b into the device table to support I-O DATA WN-DAX1200U,
an 8832bu-based adapter.
Compile tested only.
Link: https://github.com/morrownr/rtw89/commit/b22949056cfccf85a96540b2c0bd4d32e76cab0f
Signed-off-by: Zenm Chen <zenmchen@gmail.com>
---
v2:
- Add missing "Link: "
---
drivers/net/wireless/realtek/rtw89/rtw8852bu.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852bu.c b/drivers/net/wireless/realtek/rtw89/rtw8852bu.c
index 37111fed2..35fdde1cf 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852bu.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852bu.c
@@ -37,6 +37,8 @@ static const struct rtw89_driver_info rtw89_8852bu_info = {
};
static const struct usb_device_id rtw_8852bu_id_table[] = {
+ { USB_DEVICE_AND_INTERFACE_INFO(0x04bb, 0x095b, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&rtw89_8852bu_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xb832, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852bu_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xb83a, 0xff, 0xff, 0xff),
--
2.53.0
^ permalink raw reply related
* [PATCH rtw-next v2 2/5] wifi: rtw89: 8832au: Support two additional devices
From: Zenm Chen @ 2026-05-31 23:29 UTC (permalink / raw)
To: linux-wireless, pkshih, rtl8821cerfe2; +Cc: zenmchen
In-Reply-To: <20260531232914.4406-1-zenmchen@gmail.com>
Add two new ids into the device table to support the following 8832au-based
adapters:
- Mercusys MA72XH (2c4e:0124)
- TP-Link Archer TX23U (37ad:0102)
Compile tested only.
Link: https://github.com/morrownr/rtw89/commit/82b789a0f1f41e3148ecf302b4dd8f11d2d68713
Link: https://github.com/morrownr/rtw89/commit/f2e2a70eef253b4d3fc8906c99311dbc4d9f6aab
Signed-off-by: Zenm Chen <zenmchen@gmail.com>
---
v2:
- No change.
---
drivers/net/wireless/realtek/rtw89/rtw8852au.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852au.c b/drivers/net/wireless/realtek/rtw89/rtw8852au.c
index 4cced4619..b3f2690cd 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8852au.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8852au.c
@@ -63,10 +63,14 @@ static const struct usb_device_id rtw_8852au_id_table[] = {
.driver_info = (kernel_ulong_t)&rtw89_8852au_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x2357, 0x0141, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852au_info },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x2c4e, 0x0124, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&rtw89_8852au_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x3625, 0x010d, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852au_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x3625, 0x010f, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8852au_info },
+ { USB_DEVICE_AND_INTERFACE_INFO(0x37ad, 0x0102, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&rtw89_8852au_info },
{},
};
MODULE_DEVICE_TABLE(usb, rtw_8852au_id_table);
--
2.53.0
^ permalink raw reply related
* [PATCH rtw-next v2 1/5] wifi: rtw89: 8831bu: Add support for ELECOM WD{B,C}-X600DU2M-B
From: Zenm Chen @ 2026-05-31 23:29 UTC (permalink / raw)
To: linux-wireless, pkshih, rtl8821cerfe2; +Cc: zenmchen
Add the ids 056e:4027 and 056e:4028 into the device table to support
ELECOM WD{B,C}-X600DU2M-B, two new 8831bu-based adapters.
Compile tested only.
Link: https://github.com/morrownr/rtw89/commit/9e2db2834b37c6adfc4b872a9ef56c927df22bea
Signed-off-by: Zenm Chen <zenmchen@gmail.com>
---
v2:
- Add missing "Link: "
---
drivers/net/wireless/realtek/rtw89/rtw8851bu.c | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/drivers/net/wireless/realtek/rtw89/rtw8851bu.c b/drivers/net/wireless/realtek/rtw89/rtw8851bu.c
index 6a8d31544..343941ccb 100644
--- a/drivers/net/wireless/realtek/rtw89/rtw8851bu.c
+++ b/drivers/net/wireless/realtek/rtw89/rtw8851bu.c
@@ -37,6 +37,12 @@ static const struct rtw89_driver_info rtw89_8851bu_info = {
};
static const struct usb_device_id rtw_8851bu_id_table[] = {
+ /* ELECOM WDC-X600DU2M-B */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x4027, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&rtw89_8851bu_info },
+ /* ELECOM WDB-X600DU2M-B */
+ { USB_DEVICE_AND_INTERFACE_INFO(0x056e, 0x4028, 0xff, 0xff, 0xff),
+ .driver_info = (kernel_ulong_t)&rtw89_8851bu_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xb831, 0xff, 0xff, 0xff),
.driver_info = (kernel_ulong_t)&rtw89_8851bu_info },
{ USB_DEVICE_AND_INTERFACE_INFO(0x0bda, 0xb851, 0xff, 0xff, 0xff),
--
2.53.0
^ permalink raw reply related
* [PATCH] wifi: rtw88: extend USB TX report timeout to RTL8822BU
From: VolcomIlluminated @ 2026-05-31 22:33 UTC (permalink / raw)
To: pkshih
Cc: kvalo, luka.gejak, linux-wireless, linux-kernel, stable,
VolcomIlluminated
Luka Gejak's patch increased the TX report timeout for RTL8723DU to
accommodate off-channel dwell time during background scans. The same
issue affects RTL8822BU (tested on Edimax EW-7822ULC) where background
scans cause the firmware to stay off-channel for periods exceeding the
default 500ms timeout, causing the purge timer to fire prematurely and
drop TX tracking skbs.
Extend the 2500ms timeout to also cover RTL8822BU USB devices.
Tested on RTL8822BU (Edimax EW-7822ULC) with 17,706 packets over 24+
hours with zero drops.
Fixes: a82dfd33d123 ("wifi: rtw88: Add common USB chip support")
Cc: stable@vger.kernel.org
Signed-off-by: VolcomIlluminated <Volcomilluminated@airmail.cc>
---
--- /tmp/linux-6.18/drivers/net/wireless/realtek/rtw88/tx.c 2025-11-30 17:42:10.000000000 -0500
+++ /home/ptpx86mm1/kernelbuild/linux-6.18/drivers/net/wireless/realtek/rtw88/tx.c 2026-05-31 16:00:37.125645594 -0400
@@ -196,6 +196,7 @@
void rtw_tx_report_enqueue(struct rtw_dev *rtwdev, struct sk_buff *skb, u8 sn)
{
struct rtw_tx_report *tx_report = &rtwdev->tx_report;
+ unsigned long timeout = RTW_TX_PROBE_TIMEOUT;
unsigned long flags;
u8 *drv_data;
@@ -207,7 +208,12 @@
__skb_queue_tail(&tx_report->queue, skb);
spin_unlock_irqrestore(&tx_report->q_lock, flags);
- mod_timer(&tx_report->purge_timer, jiffies + RTW_TX_PROBE_TIMEOUT);
+ if ((rtwdev->chip->id == RTW_CHIP_TYPE_8723D ||
+ rtwdev->chip->id == RTW_CHIP_TYPE_8822B) &&
+ rtwdev->hci.type == RTW_HCI_TYPE_USB)
+ timeout = msecs_to_jiffies(2500);
+
+ mod_timer(&tx_report->purge_timer, jiffies + timeout);
}
EXPORT_SYMBOL(rtw_tx_report_enqueue);
^ permalink raw reply
* Re: [PATCH v2] wifi: mt76: mt7996: fix reading zeroed info->control.flags after mt76_tx_status_skb_add()
From: Ryder Lee @ 2026-05-31 19:52 UTC (permalink / raw)
To: lorenzo@kernel.org
Cc: Shayne Chen (陳軒丞), nbd@nbd.name, Roy-CH Luo,
Chui-hao Chiu (邱垂浩),
AngeloGioacchino Del Regno, linux-kernel@vger.kernel.org,
linux-wireless@vger.kernel.org, Sean Wang,
Bo Jiao (焦波), linux-mediatek@lists.infradead.org,
matthias.bgg@gmail.com, linux-arm-kernel@lists.infradead.org
In-Reply-To: <ahwzwHDF7fT9t7hP@lore-desk>
On Sun, 2026-05-31 at 15:12 +0200, lorenzo@kernel.org wrote:
> On May 31, Ryder Lee wrote:
> > On Sun, 2026-05-31 at 14:11 +0200, lorenzo@kernel.org wrote:
> > > > On Sun, 2026-05-31 at 10:55 +0200, Lorenzo Bianconi wrote:
> > > > > mt76_tx_status_skb_add() zeroes the mt76_tx_cb struct stored
> > > > > at
> > > > > info->status.status_driver_data via memset(). Since info-
> > > > > >control
> > > > > and
> > > > > info->status are members of the same union in
> > > > > ieee80211_tx_info,
> > > > > this overwrites info->control.flags.
> > > > > In mt7996_tx_prepare_skb(), mt76_tx_status_skb_add() is
> > > > > called
> > > > > before
> > > > > mt7996_mac_write_txwi(), which re-reads info->control.flags
> > > > > to
> > > > > extract
> > > > > IEEE80211_TX_CTRL_MLO_LINK. Because the field has been
> > > > > zeroed,
> > > > > the
> > > > > link_id always resolves to 0 for frames using global_wcid,
> > > > > leading to
> > > > > incorrect TXWI configuration.
> > > > > Fix this by passing link_id as an explicit parameter to
> > > > > mt7996_mac_write_txwi(). In mt7996_tx_prepare_skb(), the
> > > > > link_id
> > > > > is
> > > > > already extracted from info->control.flags before the
> > > > > destructive
> > > > > mt76_tx_status_skb_add() call. For the beacon and inband
> > > > > discovery
> > > > > callers in mcu.c, use link_conf->link_id directly.
> > > > >
> > > > > Fixes: f0b0b239b8f36 ("wifi: mt76: mt7996: rework
> > > > > mt7996_mac_write_txwi() for MLO support")
> > > > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > > ---
> > > > > Changes in v2:
> > > > > - Do not use link_id in mt7996_mac_write_txwi if it is
> > > > > IEEE80211_LINK_UNSPECIFIED
> > > > > - In mt7996_mac_write_txwi() rely on link_id calculated in
> > > > > mt7996_tx_prepare_skb().
> > > > > - Link to v1:
> > > > > https://lore.kernel.org/r/20260530-mt76_tx_status_skb_add-overwrite-fix-v1-1-e2c3151c391a@kernel.org
> > > > >
> > > > > ---
> > > > > drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 14
> > > > > ++++----
> > > > > ----
> > > > > --
> > > > > drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 5 +++-
> > > > > -
> > > > > drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 3 ++-
> > > > > 3 files changed, 9 insertions(+), 13 deletions(-)
> > > > >
> > > > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > > > b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > > > index c98446057282..95b3078d9667 100644
> > > > > --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > > > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > > > @@ -856,7 +856,8 @@ mt7996_mac_write_txwi_80211(struct
> > > > > mt7996_dev
> > > > > *dev, __le32 *txwi,
> > > > > void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32
> > > > > *txwi,
> > > > > struct sk_buff *skb, struct
> > > > > mt76_wcid
> > > > > *wcid,
> > > > > struct ieee80211_key_conf *key,
> > > > > int
> > > > > pid,
> > > > > - enum mt76_txq_id qid, u32
> > > > > changed)
> > > > > + enum mt76_txq_id qid, u32
> > > > > changed,
> > > > > + unsigned int link_id)
> > > > > {
> > > > > struct ieee80211_hdr *hdr = (struct ieee80211_hdr
> > > > > *)skb-
> > > > > > data;
> > > > > struct ieee80211_tx_info *info =
> > > > > IEEE80211_SKB_CB(skb);
> > > > > @@ -866,7 +867,6 @@ void mt7996_mac_write_txwi(struct
> > > > > mt7996_dev
> > > > > *dev, __le32 *txwi,
> > > > > bool is_8023 = info->flags &
> > > > > IEEE80211_TX_CTL_HW_80211_ENCAP;
> > > > > struct mt76_vif_link *mlink = NULL;
> > > > > struct mt7996_vif *mvif;
> > > > > - unsigned int link_id;
> > > > > u16 tx_count = 15;
> > > > > u32 val;
> > > > > bool inband_disc = !!(changed &
> > > > > (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
> > > > > @@ -874,17 +874,11 @@ void mt7996_mac_write_txwi(struct
> > > > > mt7996_dev
> > > > > *dev, __le32 *txwi,
> > > > > bool beacon = !!(changed & (BSS_CHANGED_BEACON |
> > > > >
> > > > > BSS_CHANGED_BEACON_ENABLED))
> > > > > &&
> > > > > (!inband_disc);
> > > > >
> > > > > - if (wcid != &dev->mt76.global_wcid)
> > > > > - link_id = wcid->link_id;
> > > > > - else
> > > > > - link_id = u32_get_bits(info->control.flags,
> > > > > -
> > > > > IEEE80211_TX_CTRL_MLO_LINK);
> > > > > -
> > > > > mvif = vif ? (struct mt7996_vif *)vif->drv_priv :
> > > > > NULL;
> > > > > if (mvif) {
> > > > > if (wcid->offchannel)
> > > > > mlink = rcu_dereference(mvif-
> > > > > > mt76.offchannel_link);
> > > > > - if (!mlink)
> > > > > + if (!mlink && link_id !=
> > > > > IEEE80211_LINK_UNSPECIFIED)
> > > > > mlink = rcu_dereference(mvif-
> > > > > > mt76.link[link_id]);
> > > > > }
> > > > >
> > > > > @@ -1096,7 +1090,7 @@ int mt7996_tx_prepare_skb(struct
> > > > > mt76_dev
> > > > > *mdev, void *txwi_ptr,
> > > > > /* Transmit non qos data by 802.11 header and need
> > > > > to
> > > > > fill
> > > > > txd by host*/
> > > > > if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
> > > > > mt7996_mac_write_txwi(dev, txwi_ptr,
> > > > > tx_info-
> > > > > > skb,
> > > > > wcid, key,
> > > > > - pid, qid, 0);
> > > > > + pid, qid, 0, link_id);
> > > > >
> > > > > /* MT7996 and MT7992 require driver to provide the
> > > > > MAC
> > > > > TXP
> > > > > for AddBA
> > > > > * req
> > > > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > > > b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > > > index 8be40d60ad29..a14c63438923 100644
> > > > > --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > > > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > > > @@ -3103,7 +3103,7 @@ mt7996_mcu_beacon_cont(struct
> > > > > mt7996_dev
> > > > > *dev,
> > > > >
> > > > > buf = (u8 *)bcn + sizeof(*bcn);
> > > > > mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid,
> > > > > NULL,
> > > > > 0, 0,
> > > > > - BSS_CHANGED_BEACON);
> > > > > + BSS_CHANGED_BEACON, link_conf-
> > > > > > link_id);
> > > > >
> > > > > memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
> > > > > }
> > > > > @@ -3249,7 +3249,8 @@ int
> > > > > mt7996_mcu_beacon_inband_discov(struct
> > > > > mt7996_dev *dev,
> > > > >
> > > > > buf = (u8 *)tlv + sizeof(*discov);
> > > > >
> > > > > - mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid,
> > > > > NULL,
> > > > > 0, 0, changed);
> > > > > + mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid,
> > > > > NULL,
> > > > > 0, 0,
> > > > > + changed, link_conf->link_id);
> > > > >
> > > > > memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
> > > > >
> > > > > diff --git
> > > > > a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > > > b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > > > index 0dc4198fcf8b..0d6488522ba7 100644
> > > > > --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > > > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > > > @@ -874,7 +874,8 @@ void mt7996_mac_enable_nf(struct
> > > > > mt7996_dev
> > > > > *dev,
> > > > > u8 band);
> > > > > void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32
> > > > > *txwi,
> > > > > struct sk_buff *skb, struct
> > > > > mt76_wcid
> > > > > *wcid,
> > > > > struct ieee80211_key_conf *key,
> > > > > int
> > > > > pid,
> > > > > - enum mt76_txq_id qid, u32
> > > > > changed);
> > > > > + enum mt76_txq_id qid, u32
> > > > > changed,
> > > > > + unsigned int link_id);
> > > > > void mt7996_mac_update_beacons(struct mt7996_phy *phy);
> > > > > void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
> > > > > void mt7996_mac_work(struct work_struct *work);
> > > > >
> > > > > ---
> > > > > base-commit: 4913f44167cf35a9536e9eec7352e15b2de0c573
> > > > > change-id: 20260530-mt76_tx_status_skb_add-overwrite-fix-
> > > > > 85818a9bb31f
> > > > >
> > > > > Best regards,
> > > > >
> > > > >
> > > > We might expand flags further so this still doesn't solve the
> > > > issue
> > > > of
> > > > flags being cleared - it only works for MLO flag. And the
> > > > developers
> > > > still won't easily notice that the flags are being cleared.
> > >
> > > My opinion is we should consider just upstream code and then
> > > change
> > > it as soon
> > > as you post this new feature upstream, but I will let Felix
> > > comments
> > > on it.
> > > Moreover, the proposed approach aligns link_id used in
> > > mt7996_tx_prepare_skb()
> > > to the one used in mt7996_mac_write_txwi() and fix a possible OOB
> > > bug
> > > in
> > > mt7996_mac_write_txwi().
> > >
> > > Regards,
> > > Lorenzo
> > >
> > > >
> >
> > Just to tie in with this patch subject - I'm just thinking of a way
> > to
> > solve this once and for all. If the problem is reading zeroed info-
> > > control.flags, wouldn't it be better to just pass a u32 flags,
> > something like this:
> >
> > u32 flags = info->control.flags
> >
> > mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0,
> > changed, flags);
> >
> > We can use all flags then.
>
> what about link_id? Should it be the same between
> mt7996_tx_prepare_skb()
> and mt7996_mac_write_txwi()?
>
>
I mean the link_id is only corresponds to one specific flags bit of
mac80211_tx_control_flags. But there are other bits that aren't
handled. Wouldn't u32 flags make it more cleaner?
Ryder
^ permalink raw reply
* [PATCH wireless] wifi: qtnfmac: topaz: defer IRQ enabling until IPC init
From: Runyu Xiao @ 2026-05-31 14:54 UTC (permalink / raw)
To: Kalle Valo, Igor Mitsyanko
Cc: Sergey Matyukevich, Andrey Shevchenko, linux-wireless,
linux-kernel, jianhao.xu, runyu.xiao, stable
qtnf_pcie_topaz_probe() currently calls devm_request_irq() and only then
disable_irq(). request_irq() installs the action in the irq core
immediately, so qtnf_pcie_topaz_interrupt() can run before the Topaz
private IRQ consumers are initialized.
This window is reachable on a running system as soon as probe has
successfully registered pdev->irq but before qtnf_pcie_init_shm_ipc()
sets shm_ipc_ep_in/out.irq_handler. If an interrupt is delivered in
this interval, qtnf_pcie_topaz_interrupt() calls
qtnf_shm_ipc_irq_handler() for shm_ipc_ep_in/out while their irq_handler
callbacks are still unset, so the driver can observe an early IRQ
before its IPC consumer state is ready.
The issue was found on Linux v6.18.21 by our static analysis tool while
scanning request_irq()/disable_irq() registration-order bugs in
wireless PCIe drivers, and then manually reviewed. It was validated
with a QEMU no-device harness using
IRQ_SIM and a directed generic_handle_irq_safe() injection between
request_irq() and qtnf_pcie_init_shm_ipc(). The harness reported:
has_action=1 shm_in=0000000000000000 shm_out=0000000000000000
reached handler before shm_ipc init
irq_count=1
This is family-level runtime evidence for the same early-IRQ window. No
Topaz hardware was available to exercise the real device path end-to-end.
Request the IRQ with IRQF_NO_AUTOEN instead and keep the existing
enable_irq() in qtnf_post_init_ep() as the point where interrupts
become visible. This closes the early-IRQ window while preserving the
intended bring-up order.
Build-tested by compiling topaz_pcie.o on x86_64.
Fixes: e401fa25cfa2 ("qtnfmac: add support for Topaz chipsets")
Cc: stable@vger.kernel.org
Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn>
---
drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
index ef5c069542d4..a3a285f17dca 100644
--- a/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
+++ b/drivers/net/wireless/quantenna/qtnfmac/pcie/topaz_pcie.c
@@ -1132,9 +1132,9 @@ static int qtnf_pcie_topaz_probe(struct qtnf_bus *bus,
/* assign host msi irq before card init */
if (ts->base.msi_enabled)
- irqflags = IRQF_NOBALANCING;
+ irqflags = IRQF_NOBALANCING | IRQF_NO_AUTOEN;
else
- irqflags = IRQF_NOBALANCING | IRQF_SHARED;
+ irqflags = IRQF_NOBALANCING | IRQF_SHARED | IRQF_NO_AUTOEN;
ret = devm_request_irq(&pdev->dev, pdev->irq,
&qtnf_pcie_topaz_interrupt,
@@ -1144,8 +1144,6 @@ static int qtnf_pcie_topaz_probe(struct qtnf_bus *bus,
return ret;
}
- disable_irq(pdev->irq);
-
ret = qtnf_pre_init_ep(bus);
if (ret) {
pr_err("failed to init card\n");
--
2.34.1
^ permalink raw reply related
* pull-request: wifi: iwlwifi-next - 2026-05-31
From: Korenblit, Miriam Rachel @ 2026-05-31 14:27 UTC (permalink / raw)
To: linux-wireless
The following changes since commit 6f5dc19f46f4bd0e104c9a4da2f0a912cdf3bd86:
Merge tag 'ath-next-20260526' of git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath (2026-05-28 10:23:15 +0200)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.git/ tags/iwlwifi-next-2026-05-31
for you to fetch changes up to 933c7e591e4112dc3d664374c6a62d7153df1d16:
wifi: iwlwifi: bump maximum core version for BZ/SC/DR to 106 (2026-05-31 17:22:55 +0300)
----------------------------------------------------------------
wifi: iwlwifi-next - 2026-05-31
This contains features, cleanups and fixes.
Thanks,
Miri
---
----------------------------------------------------------------
Avinash Bhatt (3):
wifi: iwlwifi: mld: add KUnit tests for duplicated beacon RSSI adjustment
wifi: iwlwifi: mld: add KUnit tests for PSD/EIRP RSSI adjustment
wifi: iwlwifi: mld: add KUnit tests for link grading
Emmanuel Grumbach (2):
wifi: iwlwifi: add support for AX231
wifi: iwlwifi: bump maximum core version for BZ/SC/DR to 106
Ilan Peer (1):
wifi: iwlwifi: mld: Require HT support for NAN
Israel Kozitz (1):
wifi: iwlwifi: mld: support FW TLV for NAN max channel switch time
Johannes Berg (6):
wifi: iwlwifi: fw: cut down NIC wakeups during dump
wifi: iwlwifi: mvm: rename iwl_mvm_mac80211_idx_to_hwrate()
wifi: iwlwifi: move iwl_fw_rate_idx_to_plcp() to mvm
wifi: iwlwifi: mld: don't WARN on WoWLAN suspend w/o netdetect
wifi: iwlwifi: mvm: fix P2P-Device binding handling
wifi: iwlwifi: pcie: fix write pointer move detection
Miri Korenblit (7):
wifi: iwlwifi: remove stale comment
wifi: iwlwifi: remove mvm prefix from marker command
wifi: iwlwifi: mld: fix smatch warning
wifi: iwlwifi: mld: always allow mimo in NAN
wifi: iwlwifi: fix a typo
wifi: iwlwifi: trans: export the maximum supported hcmd size
wifi: iwlwifi: mvm: remove __must_check annotation from command sending
Moriya Itzchaki (1):
wifi: iwlwifi: fix STEP_URM register address for SC devices
Pagadala Yesu Anjaneyulu (1):
wifi: iwlwifi: mld: set fast-balance scan for active EMLSR
Shahar Tzarfati (4):
wifi: iwlwifi: cfg: Revert "wifi: iwlwifi: cfg: move the MODULE_FIRMWARE to the per-rf file"
wifi: iwlwifi: remove orphaned DC2DC config enum
wifi: iwlwifi: stop supporting core101
wifi: iwlwifi: mld: drop TLC config cmd v4/v5 compat code
drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 16 +-
drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 4 +-
drivers/net/wireless/intel/iwlwifi/cfg/rf-fm.c | 12 -
drivers/net/wireless/intel/iwlwifi/cfg/rf-gf.c | 3 +-
drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 4 +-
.../net/wireless/intel/iwlwifi/fw/api/commands.h | 4 +-
drivers/net/wireless/intel/iwlwifi/fw/api/config.h | 11 +-
.../net/wireless/intel/iwlwifi/fw/api/datapath.h | 2 +-
drivers/net/wireless/intel/iwlwifi/fw/api/debug.h | 16 +-
drivers/net/wireless/intel/iwlwifi/fw/api/rs.h | 34 +-
drivers/net/wireless/intel/iwlwifi/fw/dbg.c | 96 ++---
drivers/net/wireless/intel/iwlwifi/fw/file.h | 1 +
drivers/net/wireless/intel/iwlwifi/fw/img.h | 1 +
drivers/net/wireless/intel/iwlwifi/fw/rs.c | 27 --
drivers/net/wireless/intel/iwlwifi/iwl-config.h | 6 +-
drivers/net/wireless/intel/iwlwifi/iwl-drv.c | 6 +
drivers/net/wireless/intel/iwlwifi/iwl-prph.h | 3 +-
drivers/net/wireless/intel/iwlwifi/iwl-trans.c | 5 +
drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 15 +
drivers/net/wireless/intel/iwlwifi/mld/d3.c | 7 +-
drivers/net/wireless/intel/iwlwifi/mld/link.c | 15 +-
drivers/net/wireless/intel/iwlwifi/mld/link.h | 6 +
drivers/net/wireless/intel/iwlwifi/mld/mac80211.c | 9 +-
drivers/net/wireless/intel/iwlwifi/mld/nan.c | 3 +-
drivers/net/wireless/intel/iwlwifi/mld/scan.c | 8 +-
drivers/net/wireless/intel/iwlwifi/mld/sta.c | 6 +
.../intel/iwlwifi/mld/tests/link-selection.c | 280 ++++++++++--
.../net/wireless/intel/iwlwifi/mld/tests/link.c | 474 ++++++++++++++++++++-
.../net/wireless/intel/iwlwifi/mld/tests/utils.c | 60 +++
.../net/wireless/intel/iwlwifi/mld/tests/utils.h | 9 +-
drivers/net/wireless/intel/iwlwifi/mld/tlc.c | 74 ----
drivers/net/wireless/intel/iwlwifi/mld/tx.c | 3 +-
drivers/net/wireless/intel/iwlwifi/mvm/binding.c | 5 +-
drivers/net/wireless/intel/iwlwifi/mvm/mac-ctxt.c | 6 +-
drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c | 12 +-
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 26 +-
.../net/wireless/intel/iwlwifi/mvm/time-event.c | 3 +-
drivers/net/wireless/intel/iwlwifi/mvm/tx.c | 10 +-
drivers/net/wireless/intel/iwlwifi/mvm/utils.c | 32 +-
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 3 +-
.../wireless/intel/iwlwifi/pcie/gen1_2/internal.h | 1 +
.../intel/iwlwifi/pcie/gen1_2/trans-gen2.c | 12 +-
.../net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c | 7 +-
43 files changed, 1031 insertions(+), 306 deletions(-)
^ permalink raw reply
* pull-request: iwlwifi-fixes - 2026-05-31
From: Korenblit, Miriam Rachel @ 2026-05-31 14:22 UTC (permalink / raw)
To: linux-wireless
The following changes since commit 68993ced0f618e36cf33388f1e50223e5e6e78cc:
Merge tag 'net-7.1-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net (2026-05-21 14:39:12 -0700)
are available in the Git repository at:
https://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-next.git/ tags/iwlwifi-fixes-2026-05-31
for you to fetch changes up to 093305d801fae6ff9b8bb531fd78b579794c4f80:
wifi: iwlwifi: pcie: simplify the resume flow if fast resume is not used (2026-05-31 17:07:11 +0300)
----------------------------------------------------------------
wifi: iwlwifi: fixes - 2026-05-31
This contains a few fixes:
- Don't grab nic access in non-fast-resume
- Don't send a large hcmd than transport supports
- In AP mode, don't send tx power constraints command before activating
the link
- Don't do sw reset handshake on older firmwares.
----------------------------------------------------------------
Emmanuel Grumbach (3):
wifi: iwlwifi: mvm: don't support the reset handshake for old firmwares
wifi: iwlwifi: mvm: avoid oversized UATS command copy
wifi: iwlwifi: pcie: simplify the resume flow if fast resume is not used
Pagadala Yesu Anjaneyulu (1):
wifi: iwlwifi: mld: send tx power constraints before link activation
drivers/net/wireless/intel/iwlwifi/mld/ap.c | 4 --
drivers/net/wireless/intel/iwlwifi/mld/mac80211.c | 7 +++
drivers/net/wireless/intel/iwlwifi/mld/power.c | 2 +-
drivers/net/wireless/intel/iwlwifi/mvm/fw.c | 26 +++++++++--
drivers/net/wireless/intel/iwlwifi/mvm/ops.c | 6 +++
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 56 +++++++++++++----------
6 files changed, 67 insertions(+), 34 deletions(-)
^ permalink raw reply
* net: wireless: ralink: RT2X00: regression, hostapd do not work anymore on 6.18.33 (work on 6.18.26)
From: Corentin Labbe @ 2026-05-31 14:11 UTC (permalink / raw)
To: stf_xl, linux-wireless; +Cc: linux-kernel
Hello
I have an hostapd setup with a
01:00.0 Network controller: Ralink corp. RT2790 Wireless 802.11n 1T/2R PCIe
The setup work fine on 6.18.26-gentoo
It breaks on 6.18.33-gentoo
I found an hint in dmesg:
On 6.18.26-gentoo I see:
May 31 15:48:45 trash01 kernel: ieee80211 phy0: rt2x00_set_rf: Info - RF chipset 0003 detected
On 6.18.33-gentoo I see:
May 31 15:22:57 trash01 kernel: ieee80211 phy0: rt2x00_set_rf: Info - RF chipset 0006 detected
The RF chipset seems badly detected.
Regards
^ permalink raw reply
* Re: [PATCH v2] wifi: mt76: mt7996: fix reading zeroed info->control.flags after mt76_tx_status_skb_add()
From: lorenzo @ 2026-05-31 13:12 UTC (permalink / raw)
To: Ryder Lee
Cc: linux-mediatek@lists.infradead.org,
Shayne Chen (陳軒丞), nbd@nbd.name, Roy-CH Luo,
AngeloGioacchino Del Regno, linux-kernel@vger.kernel.org,
Chui-hao Chiu (邱垂浩), Sean Wang,
Bo Jiao (焦波), matthias.bgg@gmail.com,
linux-arm-kernel@lists.infradead.org,
linux-wireless@vger.kernel.org
In-Reply-To: <44c54ed4da0d294c567b3b0ad750f082a6f1be9f.camel@mediatek.com>
[-- Attachment #1: Type: text/plain, Size: 8556 bytes --]
On May 31, Ryder Lee wrote:
> On Sun, 2026-05-31 at 14:11 +0200, lorenzo@kernel.org wrote:
> > > On Sun, 2026-05-31 at 10:55 +0200, Lorenzo Bianconi wrote:
> > > > mt76_tx_status_skb_add() zeroes the mt76_tx_cb struct stored at
> > > > info->status.status_driver_data via memset(). Since info->control
> > > > and
> > > > info->status are members of the same union in ieee80211_tx_info,
> > > > this overwrites info->control.flags.
> > > > In mt7996_tx_prepare_skb(), mt76_tx_status_skb_add() is called
> > > > before
> > > > mt7996_mac_write_txwi(), which re-reads info->control.flags to
> > > > extract
> > > > IEEE80211_TX_CTRL_MLO_LINK. Because the field has been zeroed,
> > > > the
> > > > link_id always resolves to 0 for frames using global_wcid,
> > > > leading to
> > > > incorrect TXWI configuration.
> > > > Fix this by passing link_id as an explicit parameter to
> > > > mt7996_mac_write_txwi(). In mt7996_tx_prepare_skb(), the link_id
> > > > is
> > > > already extracted from info->control.flags before the destructive
> > > > mt76_tx_status_skb_add() call. For the beacon and inband
> > > > discovery
> > > > callers in mcu.c, use link_conf->link_id directly.
> > > >
> > > > Fixes: f0b0b239b8f36 ("wifi: mt76: mt7996: rework
> > > > mt7996_mac_write_txwi() for MLO support")
> > > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > ---
> > > > Changes in v2:
> > > > - Do not use link_id in mt7996_mac_write_txwi if it is
> > > > IEEE80211_LINK_UNSPECIFIED
> > > > - In mt7996_mac_write_txwi() rely on link_id calculated in
> > > > mt7996_tx_prepare_skb().
> > > > - Link to v1:
> > > > https://lore.kernel.org/r/20260530-mt76_tx_status_skb_add-overwrite-fix-v1-1-e2c3151c391a@kernel.org
> > > >
> > > > ---
> > > > drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 14 ++++----
> > > > ----
> > > > --
> > > > drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 5 +++--
> > > > drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 3 ++-
> > > > 3 files changed, 9 insertions(+), 13 deletions(-)
> > > >
> > > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > > b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > > index c98446057282..95b3078d9667 100644
> > > > --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > > @@ -856,7 +856,8 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev
> > > > *dev, __le32 *txwi,
> > > > void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
> > > > struct sk_buff *skb, struct mt76_wcid
> > > > *wcid,
> > > > struct ieee80211_key_conf *key, int
> > > > pid,
> > > > - enum mt76_txq_id qid, u32 changed)
> > > > + enum mt76_txq_id qid, u32 changed,
> > > > + unsigned int link_id)
> > > > {
> > > > struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb-
> > > > > data;
> > > > struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> > > > @@ -866,7 +867,6 @@ void mt7996_mac_write_txwi(struct mt7996_dev
> > > > *dev, __le32 *txwi,
> > > > bool is_8023 = info->flags &
> > > > IEEE80211_TX_CTL_HW_80211_ENCAP;
> > > > struct mt76_vif_link *mlink = NULL;
> > > > struct mt7996_vif *mvif;
> > > > - unsigned int link_id;
> > > > u16 tx_count = 15;
> > > > u32 val;
> > > > bool inband_disc = !!(changed &
> > > > (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
> > > > @@ -874,17 +874,11 @@ void mt7996_mac_write_txwi(struct
> > > > mt7996_dev
> > > > *dev, __le32 *txwi,
> > > > bool beacon = !!(changed & (BSS_CHANGED_BEACON |
> > > > BSS_CHANGED_BEACON_ENABLED))
> > > > &&
> > > > (!inband_disc);
> > > >
> > > > - if (wcid != &dev->mt76.global_wcid)
> > > > - link_id = wcid->link_id;
> > > > - else
> > > > - link_id = u32_get_bits(info->control.flags,
> > > > -
> > > > IEEE80211_TX_CTRL_MLO_LINK);
> > > > -
> > > > mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL;
> > > > if (mvif) {
> > > > if (wcid->offchannel)
> > > > mlink = rcu_dereference(mvif-
> > > > > mt76.offchannel_link);
> > > > - if (!mlink)
> > > > + if (!mlink && link_id !=
> > > > IEEE80211_LINK_UNSPECIFIED)
> > > > mlink = rcu_dereference(mvif-
> > > > > mt76.link[link_id]);
> > > > }
> > > >
> > > > @@ -1096,7 +1090,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev
> > > > *mdev, void *txwi_ptr,
> > > > /* Transmit non qos data by 802.11 header and need to
> > > > fill
> > > > txd by host*/
> > > > if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
> > > > mt7996_mac_write_txwi(dev, txwi_ptr, tx_info-
> > > > >skb,
> > > > wcid, key,
> > > > - pid, qid, 0);
> > > > + pid, qid, 0, link_id);
> > > >
> > > > /* MT7996 and MT7992 require driver to provide the MAC
> > > > TXP
> > > > for AddBA
> > > > * req
> > > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > > b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > > index 8be40d60ad29..a14c63438923 100644
> > > > --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > > @@ -3103,7 +3103,7 @@ mt7996_mcu_beacon_cont(struct mt7996_dev
> > > > *dev,
> > > >
> > > > buf = (u8 *)bcn + sizeof(*bcn);
> > > > mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid,
> > > > NULL,
> > > > 0, 0,
> > > > - BSS_CHANGED_BEACON);
> > > > + BSS_CHANGED_BEACON, link_conf-
> > > > > link_id);
> > > >
> > > > memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
> > > > }
> > > > @@ -3249,7 +3249,8 @@ int mt7996_mcu_beacon_inband_discov(struct
> > > > mt7996_dev *dev,
> > > >
> > > > buf = (u8 *)tlv + sizeof(*discov);
> > > >
> > > > - mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid,
> > > > NULL,
> > > > 0, 0, changed);
> > > > + mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid,
> > > > NULL,
> > > > 0, 0,
> > > > + changed, link_conf->link_id);
> > > >
> > > > memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
> > > >
> > > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > > b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > > index 0dc4198fcf8b..0d6488522ba7 100644
> > > > --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > > @@ -874,7 +874,8 @@ void mt7996_mac_enable_nf(struct mt7996_dev
> > > > *dev,
> > > > u8 band);
> > > > void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
> > > > struct sk_buff *skb, struct mt76_wcid
> > > > *wcid,
> > > > struct ieee80211_key_conf *key, int
> > > > pid,
> > > > - enum mt76_txq_id qid, u32 changed);
> > > > + enum mt76_txq_id qid, u32 changed,
> > > > + unsigned int link_id);
> > > > void mt7996_mac_update_beacons(struct mt7996_phy *phy);
> > > > void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
> > > > void mt7996_mac_work(struct work_struct *work);
> > > >
> > > > ---
> > > > base-commit: 4913f44167cf35a9536e9eec7352e15b2de0c573
> > > > change-id: 20260530-mt76_tx_status_skb_add-overwrite-fix-
> > > > 85818a9bb31f
> > > >
> > > > Best regards,
> > > >
> > > >
> > > We might expand flags further so this still doesn't solve the issue
> > > of
> > > flags being cleared - it only works for MLO flag. And the
> > > developers
> > > still won't easily notice that the flags are being cleared.
> >
> > My opinion is we should consider just upstream code and then change
> > it as soon
> > as you post this new feature upstream, but I will let Felix comments
> > on it.
> > Moreover, the proposed approach aligns link_id used in
> > mt7996_tx_prepare_skb()
> > to the one used in mt7996_mac_write_txwi() and fix a possible OOB bug
> > in
> > mt7996_mac_write_txwi().
> >
> > Regards,
> > Lorenzo
> >
> > >
>
> Just to tie in with this patch subject - I'm just thinking of a way to
> solve this once and for all. If the problem is reading zeroed info-
> >control.flags, wouldn't it be better to just pass a u32 flags,
> something like this:
>
> u32 flags = info->control.flags
>
> mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0,
> changed, flags);
>
> We can use all flags then.
what about link_id? Should it be the same between mt7996_tx_prepare_skb()
and mt7996_mac_write_txwi()?
Regards,
Lorenzo
>
> Ryder
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH v2] wifi: mt76: mt7996: fix reading zeroed info->control.flags after mt76_tx_status_skb_add()
From: Ryder Lee @ 2026-05-31 12:28 UTC (permalink / raw)
To: lorenzo@kernel.org
Cc: linux-mediatek@lists.infradead.org,
Shayne Chen (陳軒丞), nbd@nbd.name, Roy-CH Luo,
AngeloGioacchino Del Regno, linux-kernel@vger.kernel.org,
Chui-hao Chiu (邱垂浩), Sean Wang,
Bo Jiao (焦波), matthias.bgg@gmail.com,
linux-arm-kernel@lists.infradead.org,
linux-wireless@vger.kernel.org
In-Reply-To: <ahwla_obwnwr2cZo@lore-desk>
On Sun, 2026-05-31 at 14:11 +0200, lorenzo@kernel.org wrote:
> > On Sun, 2026-05-31 at 10:55 +0200, Lorenzo Bianconi wrote:
> > > mt76_tx_status_skb_add() zeroes the mt76_tx_cb struct stored at
> > > info->status.status_driver_data via memset(). Since info->control
> > > and
> > > info->status are members of the same union in ieee80211_tx_info,
> > > this overwrites info->control.flags.
> > > In mt7996_tx_prepare_skb(), mt76_tx_status_skb_add() is called
> > > before
> > > mt7996_mac_write_txwi(), which re-reads info->control.flags to
> > > extract
> > > IEEE80211_TX_CTRL_MLO_LINK. Because the field has been zeroed,
> > > the
> > > link_id always resolves to 0 for frames using global_wcid,
> > > leading to
> > > incorrect TXWI configuration.
> > > Fix this by passing link_id as an explicit parameter to
> > > mt7996_mac_write_txwi(). In mt7996_tx_prepare_skb(), the link_id
> > > is
> > > already extracted from info->control.flags before the destructive
> > > mt76_tx_status_skb_add() call. For the beacon and inband
> > > discovery
> > > callers in mcu.c, use link_conf->link_id directly.
> > >
> > > Fixes: f0b0b239b8f36 ("wifi: mt76: mt7996: rework
> > > mt7996_mac_write_txwi() for MLO support")
> > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > ---
> > > Changes in v2:
> > > - Do not use link_id in mt7996_mac_write_txwi if it is
> > > IEEE80211_LINK_UNSPECIFIED
> > > - In mt7996_mac_write_txwi() rely on link_id calculated in
> > > mt7996_tx_prepare_skb().
> > > - Link to v1:
> > > https://lore.kernel.org/r/20260530-mt76_tx_status_skb_add-overwrite-fix-v1-1-e2c3151c391a@kernel.org
> > >
> > > ---
> > > drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 14 ++++----
> > > ----
> > > --
> > > drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 5 +++--
> > > drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 3 ++-
> > > 3 files changed, 9 insertions(+), 13 deletions(-)
> > >
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > index c98446057282..95b3078d9667 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > @@ -856,7 +856,8 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev
> > > *dev, __le32 *txwi,
> > > void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
> > > struct sk_buff *skb, struct mt76_wcid
> > > *wcid,
> > > struct ieee80211_key_conf *key, int
> > > pid,
> > > - enum mt76_txq_id qid, u32 changed)
> > > + enum mt76_txq_id qid, u32 changed,
> > > + unsigned int link_id)
> > > {
> > > struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb-
> > > > data;
> > > struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> > > @@ -866,7 +867,6 @@ void mt7996_mac_write_txwi(struct mt7996_dev
> > > *dev, __le32 *txwi,
> > > bool is_8023 = info->flags &
> > > IEEE80211_TX_CTL_HW_80211_ENCAP;
> > > struct mt76_vif_link *mlink = NULL;
> > > struct mt7996_vif *mvif;
> > > - unsigned int link_id;
> > > u16 tx_count = 15;
> > > u32 val;
> > > bool inband_disc = !!(changed &
> > > (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
> > > @@ -874,17 +874,11 @@ void mt7996_mac_write_txwi(struct
> > > mt7996_dev
> > > *dev, __le32 *txwi,
> > > bool beacon = !!(changed & (BSS_CHANGED_BEACON |
> > > BSS_CHANGED_BEACON_ENABLED))
> > > &&
> > > (!inband_disc);
> > >
> > > - if (wcid != &dev->mt76.global_wcid)
> > > - link_id = wcid->link_id;
> > > - else
> > > - link_id = u32_get_bits(info->control.flags,
> > > -
> > > IEEE80211_TX_CTRL_MLO_LINK);
> > > -
> > > mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL;
> > > if (mvif) {
> > > if (wcid->offchannel)
> > > mlink = rcu_dereference(mvif-
> > > > mt76.offchannel_link);
> > > - if (!mlink)
> > > + if (!mlink && link_id !=
> > > IEEE80211_LINK_UNSPECIFIED)
> > > mlink = rcu_dereference(mvif-
> > > > mt76.link[link_id]);
> > > }
> > >
> > > @@ -1096,7 +1090,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev
> > > *mdev, void *txwi_ptr,
> > > /* Transmit non qos data by 802.11 header and need to
> > > fill
> > > txd by host*/
> > > if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
> > > mt7996_mac_write_txwi(dev, txwi_ptr, tx_info-
> > > >skb,
> > > wcid, key,
> > > - pid, qid, 0);
> > > + pid, qid, 0, link_id);
> > >
> > > /* MT7996 and MT7992 require driver to provide the MAC
> > > TXP
> > > for AddBA
> > > * req
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > index 8be40d60ad29..a14c63438923 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > @@ -3103,7 +3103,7 @@ mt7996_mcu_beacon_cont(struct mt7996_dev
> > > *dev,
> > >
> > > buf = (u8 *)bcn + sizeof(*bcn);
> > > mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid,
> > > NULL,
> > > 0, 0,
> > > - BSS_CHANGED_BEACON);
> > > + BSS_CHANGED_BEACON, link_conf-
> > > > link_id);
> > >
> > > memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
> > > }
> > > @@ -3249,7 +3249,8 @@ int mt7996_mcu_beacon_inband_discov(struct
> > > mt7996_dev *dev,
> > >
> > > buf = (u8 *)tlv + sizeof(*discov);
> > >
> > > - mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid,
> > > NULL,
> > > 0, 0, changed);
> > > + mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid,
> > > NULL,
> > > 0, 0,
> > > + changed, link_conf->link_id);
> > >
> > > memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
> > >
> > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > index 0dc4198fcf8b..0d6488522ba7 100644
> > > --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > @@ -874,7 +874,8 @@ void mt7996_mac_enable_nf(struct mt7996_dev
> > > *dev,
> > > u8 band);
> > > void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
> > > struct sk_buff *skb, struct mt76_wcid
> > > *wcid,
> > > struct ieee80211_key_conf *key, int
> > > pid,
> > > - enum mt76_txq_id qid, u32 changed);
> > > + enum mt76_txq_id qid, u32 changed,
> > > + unsigned int link_id);
> > > void mt7996_mac_update_beacons(struct mt7996_phy *phy);
> > > void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
> > > void mt7996_mac_work(struct work_struct *work);
> > >
> > > ---
> > > base-commit: 4913f44167cf35a9536e9eec7352e15b2de0c573
> > > change-id: 20260530-mt76_tx_status_skb_add-overwrite-fix-
> > > 85818a9bb31f
> > >
> > > Best regards,
> > >
> > >
> > We might expand flags further so this still doesn't solve the issue
> > of
> > flags being cleared - it only works for MLO flag. And the
> > developers
> > still won't easily notice that the flags are being cleared.
>
> My opinion is we should consider just upstream code and then change
> it as soon
> as you post this new feature upstream, but I will let Felix comments
> on it.
> Moreover, the proposed approach aligns link_id used in
> mt7996_tx_prepare_skb()
> to the one used in mt7996_mac_write_txwi() and fix a possible OOB bug
> in
> mt7996_mac_write_txwi().
>
> Regards,
> Lorenzo
>
> >
Just to tie in with this patch subject - I'm just thinking of a way to
solve this once and for all. If the problem is reading zeroed info-
>control.flags, wouldn't it be better to just pass a u32 flags,
something like this:
u32 flags = info->control.flags
mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL, 0, 0,
changed, flags);
We can use all flags then.
Ryder
^ permalink raw reply
* Re: [PATCH v2] wifi: mt76: mt7996: fix reading zeroed info->control.flags after mt76_tx_status_skb_add()
From: lorenzo @ 2026-05-31 12:11 UTC (permalink / raw)
To: Ryder Lee
Cc: Shayne Chen (陳軒丞), nbd@nbd.name,
AngeloGioacchino Del Regno,
Chui-hao Chiu (邱垂浩), Sean Wang,
Bo Jiao (焦波), matthias.bgg@gmail.com,
linux-wireless@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Roy-CH Luo,
linux-mediatek@lists.infradead.org, linux-kernel@vger.kernel.org
In-Reply-To: <ee0e584cb2ad1b536d327eb89342d1646fa96570.camel@mediatek.com>
[-- Attachment #1: Type: text/plain, Size: 7190 bytes --]
> On Sun, 2026-05-31 at 10:55 +0200, Lorenzo Bianconi wrote:
> > mt76_tx_status_skb_add() zeroes the mt76_tx_cb struct stored at
> > info->status.status_driver_data via memset(). Since info->control and
> > info->status are members of the same union in ieee80211_tx_info,
> > this overwrites info->control.flags.
> > In mt7996_tx_prepare_skb(), mt76_tx_status_skb_add() is called before
> > mt7996_mac_write_txwi(), which re-reads info->control.flags to
> > extract
> > IEEE80211_TX_CTRL_MLO_LINK. Because the field has been zeroed, the
> > link_id always resolves to 0 for frames using global_wcid, leading to
> > incorrect TXWI configuration.
> > Fix this by passing link_id as an explicit parameter to
> > mt7996_mac_write_txwi(). In mt7996_tx_prepare_skb(), the link_id is
> > already extracted from info->control.flags before the destructive
> > mt76_tx_status_skb_add() call. For the beacon and inband discovery
> > callers in mcu.c, use link_conf->link_id directly.
> >
> > Fixes: f0b0b239b8f36 ("wifi: mt76: mt7996: rework
> > mt7996_mac_write_txwi() for MLO support")
> > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > ---
> > Changes in v2:
> > - Do not use link_id in mt7996_mac_write_txwi if it is
> > IEEE80211_LINK_UNSPECIFIED
> > - In mt7996_mac_write_txwi() rely on link_id calculated in
> > mt7996_tx_prepare_skb().
> > - Link to v1:
> > https://lore.kernel.org/r/20260530-mt76_tx_status_skb_add-overwrite-fix-v1-1-e2c3151c391a@kernel.org
> >
> > ---
> > drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 14 ++++--------
> > --
> > drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 5 +++--
> > drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 3 ++-
> > 3 files changed, 9 insertions(+), 13 deletions(-)
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > index c98446057282..95b3078d9667 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > @@ -856,7 +856,8 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev
> > *dev, __le32 *txwi,
> > void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
> > struct sk_buff *skb, struct mt76_wcid
> > *wcid,
> > struct ieee80211_key_conf *key, int pid,
> > - enum mt76_txq_id qid, u32 changed)
> > + enum mt76_txq_id qid, u32 changed,
> > + unsigned int link_id)
> > {
> > struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb-
> > >data;
> > struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> > @@ -866,7 +867,6 @@ void mt7996_mac_write_txwi(struct mt7996_dev
> > *dev, __le32 *txwi,
> > bool is_8023 = info->flags &
> > IEEE80211_TX_CTL_HW_80211_ENCAP;
> > struct mt76_vif_link *mlink = NULL;
> > struct mt7996_vif *mvif;
> > - unsigned int link_id;
> > u16 tx_count = 15;
> > u32 val;
> > bool inband_disc = !!(changed &
> > (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
> > @@ -874,17 +874,11 @@ void mt7996_mac_write_txwi(struct mt7996_dev
> > *dev, __le32 *txwi,
> > bool beacon = !!(changed & (BSS_CHANGED_BEACON |
> > BSS_CHANGED_BEACON_ENABLED)) &&
> > (!inband_disc);
> >
> > - if (wcid != &dev->mt76.global_wcid)
> > - link_id = wcid->link_id;
> > - else
> > - link_id = u32_get_bits(info->control.flags,
> > - IEEE80211_TX_CTRL_MLO_LINK);
> > -
> > mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL;
> > if (mvif) {
> > if (wcid->offchannel)
> > mlink = rcu_dereference(mvif-
> > >mt76.offchannel_link);
> > - if (!mlink)
> > + if (!mlink && link_id != IEEE80211_LINK_UNSPECIFIED)
> > mlink = rcu_dereference(mvif-
> > >mt76.link[link_id]);
> > }
> >
> > @@ -1096,7 +1090,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev
> > *mdev, void *txwi_ptr,
> > /* Transmit non qos data by 802.11 header and need to fill
> > txd by host*/
> > if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
> > mt7996_mac_write_txwi(dev, txwi_ptr, tx_info->skb,
> > wcid, key,
> > - pid, qid, 0);
> > + pid, qid, 0, link_id);
> >
> > /* MT7996 and MT7992 require driver to provide the MAC TXP
> > for AddBA
> > * req
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > index 8be40d60ad29..a14c63438923 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > @@ -3103,7 +3103,7 @@ mt7996_mcu_beacon_cont(struct mt7996_dev *dev,
> >
> > buf = (u8 *)bcn + sizeof(*bcn);
> > mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL,
> > 0, 0,
> > - BSS_CHANGED_BEACON);
> > + BSS_CHANGED_BEACON, link_conf-
> > >link_id);
> >
> > memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
> > }
> > @@ -3249,7 +3249,8 @@ int mt7996_mcu_beacon_inband_discov(struct
> > mt7996_dev *dev,
> >
> > buf = (u8 *)tlv + sizeof(*discov);
> >
> > - mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL,
> > 0, 0, changed);
> > + mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid, NULL,
> > 0, 0,
> > + changed, link_conf->link_id);
> >
> > memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
> >
> > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > index 0dc4198fcf8b..0d6488522ba7 100644
> > --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > @@ -874,7 +874,8 @@ void mt7996_mac_enable_nf(struct mt7996_dev *dev,
> > u8 band);
> > void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
> > struct sk_buff *skb, struct mt76_wcid
> > *wcid,
> > struct ieee80211_key_conf *key, int pid,
> > - enum mt76_txq_id qid, u32 changed);
> > + enum mt76_txq_id qid, u32 changed,
> > + unsigned int link_id);
> > void mt7996_mac_update_beacons(struct mt7996_phy *phy);
> > void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
> > void mt7996_mac_work(struct work_struct *work);
> >
> > ---
> > base-commit: 4913f44167cf35a9536e9eec7352e15b2de0c573
> > change-id: 20260530-mt76_tx_status_skb_add-overwrite-fix-85818a9bb31f
> >
> > Best regards,
> >
> >
> We might expand flags further so this still doesn't solve the issue of
> flags being cleared - it only works for MLO flag. And the developers
> still won't easily notice that the flags are being cleared.
My opinion is we should consider just upstream code and then change it as soon
as you post this new feature upstream, but I will let Felix comments on it.
Moreover, the proposed approach aligns link_id used in mt7996_tx_prepare_skb()
to the one used in mt7996_mac_write_txwi() and fix a possible OOB bug in
mt7996_mac_write_txwi().
Regards,
Lorenzo
>
> Our current approach is to move memset after mt7996_mac_write_txwi().
> It's more flexible and we don't have to constantly change the function
> parameters just for the flags.
>
> Ryder
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* Re: [PATCH] wifi: mt76: mt7996: fix reading zeroed info->control.flags after mt76_tx_status_skb_add()
From: lorenzo @ 2026-05-31 12:02 UTC (permalink / raw)
To: Ryder Lee
Cc: linux-mediatek@lists.infradead.org,
Shayne Chen (陳軒丞), nbd@nbd.name, Roy-CH Luo,
AngeloGioacchino Del Regno,
Chui-hao Chiu (邱垂浩), Sean Wang,
Bo Jiao (焦波), matthias.bgg@gmail.com,
linux-arm-kernel@lists.infradead.org,
linux-wireless@vger.kernel.org
In-Reply-To: <d756865286a14cf8402510817bd702228013fe8a.camel@mediatek.com>
[-- Attachment #1: Type: text/plain, Size: 7475 bytes --]
On May 31, Ryder Lee wrote:
> On Sun, 2026-05-31 at 09:09 +0200, lorenzo@kernel.org wrote:
> > > On Sat, 2026-05-30 at 17:25 +0200, Lorenzo Bianconi wrote:
> > > > mt76_tx_status_skb_add() zeroes the mt76_tx_cb struct stored at
> > > > info->status.status_driver_data via memset(). Since info->control
> > > > and
> > > > info->status are members of the same union in ieee80211_tx_info,
> > > > this overwrites info->control.flags.
> > > > In mt7996_tx_prepare_skb(), mt76_tx_status_skb_add() is called
> > > > before
> > > > mt7996_mac_write_txwi(), which re-reads info->control.flags to
> > > > extract
> > > > IEEE80211_TX_CTRL_MLO_LINK. Because the field has been zeroed,
> > > > the
> > > > link_id always resolves to 0 for frames using global_wcid,
> > > > leading to
> > > > incorrect TXWI configuration.
> > > > Fix this by passing link_id as an explicit parameter to
> > > > mt7996_mac_write_txwi(). In mt7996_tx_prepare_skb(), the link_id
> > > > is
> > > > already extracted from info->control.flags before the destructive
> > > > mt76_tx_status_skb_add() call. For the beacon and inband
> > > > discovery
> > > > callers in mcu.c, use link_conf->link_id directly.
> > > >
> > > > Fixes: f0b0b239b8f36 ("wifi: mt76: mt7996: rework
> > > > mt7996_mac_write_txwi() for MLO support")
> > > > Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
> > > > ---
> > > > drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 9 +++------
> > > > drivers/net/wireless/mediatek/mt76/mt7996/mcu.c | 5 +++--
> > > > drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h | 3 ++-
> > > > 3 files changed, 8 insertions(+), 9 deletions(-)
> > > >
> > > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > > b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > > index c98446057282..2d3f80b3e41a 100644
> > > > --- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
> > > > @@ -856,7 +856,8 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev
> > > > *dev, __le32 *txwi,
> > > > void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
> > > > struct sk_buff *skb, struct mt76_wcid
> > > > *wcid,
> > > > struct ieee80211_key_conf *key, int
> > > > pid,
> > > > - enum mt76_txq_id qid, u32 changed)
> > > > + enum mt76_txq_id qid, u32 changed,
> > > > + unsigned int link_id)
> > > > {
> > > > struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb-
> > > > > data;
> > > > struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
> > > > @@ -866,7 +867,6 @@ void mt7996_mac_write_txwi(struct mt7996_dev
> > > > *dev, __le32 *txwi,
> > > > bool is_8023 = info->flags &
> > > > IEEE80211_TX_CTL_HW_80211_ENCAP;
> > > > struct mt76_vif_link *mlink = NULL;
> > > > struct mt7996_vif *mvif;
> > > > - unsigned int link_id;
> > > > u16 tx_count = 15;
> > > > u32 val;
> > > > bool inband_disc = !!(changed &
> > > > (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP |
> > > > @@ -876,9 +876,6 @@ void mt7996_mac_write_txwi(struct mt7996_dev
> > > > *dev, __le32 *txwi,
> > > >
> > > > if (wcid != &dev->mt76.global_wcid)
> > > > link_id = wcid->link_id;
> > > > - else
> > > > - link_id = u32_get_bits(info->control.flags,
> > > > -
> > > > IEEE80211_TX_CTRL_MLO_LINK);
> > > >
> > > > mvif = vif ? (struct mt7996_vif *)vif->drv_priv : NULL;
> > > > if (mvif) {
> > > > @@ -1096,7 +1093,7 @@ int mt7996_tx_prepare_skb(struct mt76_dev
> > > > *mdev, void *txwi_ptr,
> > > > /* Transmit non qos data by 802.11 header and need to
> > > > fill
> > > > txd by host*/
> > > > if (!is_8023 || pid >= MT_PACKET_ID_FIRST)
> > > > mt7996_mac_write_txwi(dev, txwi_ptr, tx_info-
> > > > >skb,
> > > > wcid, key,
> > > > - pid, qid, 0);
> > > > + pid, qid, 0, link_id);
> > > >
> > > > /* MT7996 and MT7992 require driver to provide the MAC
> > > > TXP
> > > > for AddBA
> > > > * req
> > > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > > b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > > index 8be40d60ad29..a14c63438923 100644
> > > > --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
> > > > @@ -3103,7 +3103,7 @@ mt7996_mcu_beacon_cont(struct mt7996_dev
> > > > *dev,
> > > >
> > > > buf = (u8 *)bcn + sizeof(*bcn);
> > > > mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid,
> > > > NULL,
> > > > 0, 0,
> > > > - BSS_CHANGED_BEACON);
> > > > + BSS_CHANGED_BEACON, link_conf-
> > > > > link_id);
> > > >
> > > > memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
> > > > }
> > > > @@ -3249,7 +3249,8 @@ int mt7996_mcu_beacon_inband_discov(struct
> > > > mt7996_dev *dev,
> > > >
> > > > buf = (u8 *)tlv + sizeof(*discov);
> > > >
> > > > - mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid,
> > > > NULL,
> > > > 0, 0, changed);
> > > > + mt7996_mac_write_txwi(dev, (__le32 *)buf, skb, wcid,
> > > > NULL,
> > > > 0, 0,
> > > > + changed, link_conf->link_id);
> > > >
> > > > memcpy(buf + MT_TXD_SIZE, skb->data, skb->len);
> > > >
> > > > diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > > b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > > index 0dc4198fcf8b..0d6488522ba7 100644
> > > > --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > > +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
> > > > @@ -874,7 +874,8 @@ void mt7996_mac_enable_nf(struct mt7996_dev
> > > > *dev,
> > > > u8 band);
> > > > void mt7996_mac_write_txwi(struct mt7996_dev *dev, __le32 *txwi,
> > > > struct sk_buff *skb, struct mt76_wcid
> > > > *wcid,
> > > > struct ieee80211_key_conf *key, int
> > > > pid,
> > > > - enum mt76_txq_id qid, u32 changed);
> > > > + enum mt76_txq_id qid, u32 changed,
> > > > + unsigned int link_id);
> > > > void mt7996_mac_update_beacons(struct mt7996_phy *phy);
> > > > void mt7996_mac_set_coverage_class(struct mt7996_phy *phy);
> > > > void mt7996_mac_work(struct work_struct *work);
> > >
> > > The reason we didn't make the same change is because we use other
> > > control flags (IEEE80211_TX_CTRL*) of info->control.flags not just
> > > MLO
> > > one. So with this change we still need to copy over the other flags
> > > and
> > > pass them in as well.
> >
> > Do you mean you are using info->control.flags in
> > mt7996_mac_write_txwi() in
> > some downstream code? If so, I guess you can use a similar approach
> > and
> > just pass the required field. Copy the full ieee80211_tx_info struct
> > on
> > per-packet basis seems unnecessary.
> >
> > Regards,
> > Lorenzo
> > >
> > >
>
> We will use 3 mac80211_tx_control_flags (i.e.
> IEEE80211_TX_CTRL_RATE_INJECT), so it's better to at least copy info-
> >control.flags directly and pass them in. If you pass each
> individually, the function will end up with 12 parameters, and if more
> flags are needed in the future, you will have to add even more.
But this is necessary for non-upstream code IIUC. Are you going to post it
upstream along with the fix?
I guess it is better to align the link_id used in mt7996_mac_write_txwi()
to the one used in mt7996_mac_write_txwi(). Please take a look to v3.
Regards,
Lorenzo
>
> Ryder
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH wireless-next 10/10] wifi: iwlwifi: bump maximum core version for BZ/SC/DR to 106
From: Miri Korenblit @ 2026-05-31 10:53 UTC (permalink / raw)
To: linux-wireless; +Cc: Emmanuel Grumbach
In-Reply-To: <20260531105309.125363-1-miriam.rachel.korenblit@intel.com>
From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Start supporting Core 106 FW on these devices.
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 2 +-
drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 2 +-
drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
index 1542cbc3bb22..606362463dc7 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
@@ -10,7 +10,7 @@
#include "fw/api/txq.h"
/* Highest firmware core release supported */
-#define IWL_BZ_UCODE_CORE_MAX 105
+#define IWL_BZ_UCODE_CORE_MAX 106
/* Lowest firmware core release supported */
#define IWL_BZ_UCODE_CORE_MIN 102
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
index 6a5870619411..946975294b4f 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
@@ -9,7 +9,7 @@
#include "fw/api/txq.h"
/* Highest firmware core release supported */
-#define IWL_DR_UCODE_CORE_MAX 105
+#define IWL_DR_UCODE_CORE_MAX 106
/* Lowest firmware core release supported */
#define IWL_DR_UCODE_CORE_MIN 102
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
index f8913293ccef..e8240c1782ac 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
@@ -10,7 +10,7 @@
#include "fw/api/txq.h"
/* Highest firmware core release supported */
-#define IWL_SC_UCODE_CORE_MAX 105
+#define IWL_SC_UCODE_CORE_MAX 106
/* Lowest firmware core release supported */
#define IWL_SC_UCODE_CORE_MIN 102
--
2.34.1
^ permalink raw reply related
* [PATCH wireless-next 09/10] wifi: iwlwifi: mld: add KUnit tests for link grading
From: Miri Korenblit @ 2026-05-31 10:53 UTC (permalink / raw)
To: linux-wireless; +Cc: Avinash Bhatt
In-Reply-To: <20260531105309.125363-1-miriam.rachel.korenblit@intel.com>
From: Avinash Bhatt <avinash.bhatt@intel.com>
Add tests for the link grading algorithm covering per-bandwidth
grading tables, channel load calculation, 6 GHz RSSI adjustments
including duplicated beacon and PSD/EIRP compensation, and
puncturing penalty.
Signed-off-by: Avinash Bhatt <avinash.bhatt@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mld/link.c | 8 +
.../intel/iwlwifi/mld/tests/link-selection.c | 280 +++++++++++++++---
2 files changed, 254 insertions(+), 34 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c
index 2b8b0196692e..96e06940b34c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c
@@ -3,6 +3,8 @@
* Copyright (C) 2024-2026 Intel Corporation
*/
+#include <kunit/static_stub.h>
+
#include "constants.h"
#include "link.h"
#include "iface.h"
@@ -1032,6 +1034,9 @@ iwl_mld_get_dup_beacon_rssi_adjust(struct iwl_mld *mld,
const struct cfg80211_bss_ies *beacon_ies;
const struct element *elem;
+ KUNIT_STATIC_STUB_REDIRECT(iwl_mld_get_dup_beacon_rssi_adjust,
+ mld, link_conf);
+
/* Duplicated beacon feature is only specific to 6 GHz */
if (WARN_ONCE(link_conf->chanreq.oper.chan->band != NL80211_BAND_6GHZ,
"Unexpected band %d\n",
@@ -1109,6 +1114,9 @@ iwl_mld_get_psd_eirp_rssi_adjust(struct ieee80211_bss_conf *link_conf)
int bw_mhz, num_subchans;
u8 bw_index;
+ KUNIT_STATIC_STUB_REDIRECT(iwl_mld_get_psd_eirp_rssi_adjust,
+ link_conf);
+
/* PSD/EIRP adjustment is only specific to 6 GHz */
if (WARN_ONCE(link_conf->chanreq.oper.chan->band != NL80211_BAND_6GHZ,
"PSD/EIRP adjustment called for non-6 GHz band %d\n",
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c
index 69d222a8194c..73c2b7b3c9de 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/link-selection.c
@@ -13,24 +13,39 @@
#include "phy.h"
#include "mlo.h"
+struct link_grading_input {
+ u8 link_id;
+ const struct cfg80211_chan_def *chandef;
+ bool active;
+ s32 signal;
+ bool has_chan_util_elem;
+ u8 chan_util;
+ u8 chan_load_by_us;
+ s8 dup_beacon_adj;
+ s8 psd_eirp_adj;
+ u16 punctured;
+};
+
static const struct link_grading_test_case {
const char *desc;
- struct {
- struct {
- u8 link_id;
- const struct cfg80211_chan_def *chandef;
- bool active;
- s32 signal;
- bool has_chan_util_elem;
- u8 chan_util; /* 0-255 , used only if has_chan_util_elem is true */
- u8 chan_load_by_us; /* 0-100, used only if active is true */;
- } link;
- } input;
+ struct link_grading_input link;
unsigned int expected_grade;
} link_grading_cases[] = {
+ /* Per-bandwidth grading table tests */
{
- .desc = "channel util of 128 (50%)",
- .input.link = {
+ .desc = "20 MHz grading table: -75 dBm",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_2ghz_20mhz,
+ .active = false,
+ .signal = -75,
+ },
+ /* 137 * 0.7 (default 2.4GHz channel load 30%) */
+ .expected_grade = 96,
+ },
+ {
+ .desc = "20 MHz with channel util 128 (50%): -70 dBm",
+ .link = {
.link_id = 0,
.chandef = &chandef_2ghz_20mhz,
.active = false,
@@ -41,8 +56,8 @@ static const struct link_grading_test_case {
.expected_grade = 86,
},
{
- .desc = "channel util of 180 (70%)",
- .input.link = {
+ .desc = "20 MHz with channel util 180 (70%): -70 dBm",
+ .link = {
.link_id = 0,
.chandef = &chandef_2ghz_20mhz,
.active = false,
@@ -53,32 +68,222 @@ static const struct link_grading_test_case {
.expected_grade = 51,
},
{
- .desc = "channel util of 180 (70%), channel load by us of 10%",
- .input.link = {
+ .desc = "20 MHz active link with chan load by us 10%: -70 dBm",
+ .link = {
.link_id = 0,
.chandef = &chandef_2ghz_20mhz,
+ .active = true,
.signal = -70,
.has_chan_util_elem = true,
.chan_util = 180,
- .active = true,
.chan_load_by_us = 10,
},
.expected_grade = 67,
},
- {
- .desc = "no channel util element",
- .input.link = {
+ {
+ .desc = "40 MHz grading table: -80 dBm",
+ .link = {
.link_id = 0,
- .chandef = &chandef_2ghz_20mhz,
+ .chandef = &chandef_5ghz_40mhz,
+ .active = false,
+ .signal = -80,
+ },
+ /* 206 * 0.85 (default 5GHz channel load 15%) */
+ .expected_grade = 175,
+ },
+ {
+ .desc = "80 MHz grading table: -70 dBm",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_5ghz_80mhz,
+ .active = false,
.signal = -70,
- .active = true,
},
- .expected_grade = 120,
+ /* 548 * 0.85 (default 5GHz channel load 15%) */
+ .expected_grade = 466,
+ },
+ {
+ .desc = "160 MHz grading table: -65 dBm",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_5ghz_160mhz,
+ .active = false,
+ .signal = -65,
+ },
+ /* 1240 * 0.85 (default 5GHz channel load 15%) */
+ .expected_grade = 1055,
+ },
+ {
+ .desc = "320 MHz grading table: -60 dBm",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_6ghz_320mhz,
+ .active = false,
+ .signal = -60,
+ },
+ /* 3680 at -56 dBm (-60 + 4 dBm 6 GHz) */
+ .expected_grade = 3680,
+ },
+ /* 6 GHz RSSI adjustment integration tests */
+ {
+ .desc = "6 GHz 160 MHz with fixed +4 dBm adjustment",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_6ghz_160mhz,
+ .active = false,
+ .signal = -69,
+ },
+ /* -69 + 4 dBm = -65, grade 1240 */
+ .expected_grade = 1240,
+ },
+ {
+ .desc = "6 GHz 80 MHz with fixed +4 dBm adjustment",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_6ghz_80mhz,
+ .active = false,
+ .signal = -74,
+ },
+ /* -74 + 4 dBm = -70, grade 548 */
+ .expected_grade = 548,
+ },
+ {
+ .desc = "6 GHz 40 MHz with fixed +4 dBm adjustment",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_6ghz_40mhz,
+ .active = false,
+ .signal = -84,
+ },
+ /* -84 + 4 dBm = -80, grade 206 */
+ .expected_grade = 206,
+ },
+ {
+ .desc = "6 GHz 20 MHz with fixed +4 dBm adjustment",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_6ghz_20mhz,
+ .active = false,
+ .signal = -79,
+ },
+ .expected_grade = 137,
+ },
+ /* Duplicated beacon RSSI adjustment tests */
+ {
+ .desc = "6 GHz 40 MHz dup beacon: -81 dBm + 3 dBm = -78 dBm",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_6ghz_40mhz,
+ .active = false,
+ .signal = -81,
+ .dup_beacon_adj = 3,
+ },
+ .expected_grade = 206,
+ },
+ {
+ .desc = "6 GHz 80 MHz dup beacon: -73 dBm + 6 dBm = -67 dBm",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_6ghz_80mhz,
+ .active = false,
+ .signal = -73,
+ .dup_beacon_adj = 6,
+ },
+ .expected_grade = 620,
+ },
+ {
+ .desc = "6 GHz 160 MHz dup beacon: -74 dBm + 9 dBm = -65 dBm",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_6ghz_160mhz,
+ .active = false,
+ .signal = -74,
+ .dup_beacon_adj = 9,
+ },
+ .expected_grade = 1240,
+ },
+ {
+ .desc = "6 GHz 320 MHz dup beacon: -72 dBm + 12 dBm = -60 dBm",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_6ghz_320mhz,
+ .active = false,
+ .signal = -72,
+ .dup_beacon_adj = 12,
+ },
+ .expected_grade = 3296,
+ },
+ /* PSD/EIRP RSSI adjustment tests */
+ {
+ .desc = "6 GHz 80 MHz PSD/EIRP: -77 dBm + 3 dBm = -74 dBm",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_6ghz_80mhz,
+ .active = false,
+ .signal = -77,
+ .psd_eirp_adj = 3,
+ },
+ /* -77 + 3 dBm = -74, grade 412; fallback +4: -73 -> 548 */
+ .expected_grade = 412,
+ },
+ {
+ .desc = "6 GHz 160 MHz PSD/EIRP: -70 dBm + 3 dBm = -67 dBm",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_6ghz_160mhz,
+ .active = false,
+ .signal = -70,
+ .psd_eirp_adj = 3,
+ },
+ /* -70 + 3 dBm = -67, grade 1096; fallback +4: -66 -> 1240 */
+ .expected_grade = 1096,
+ },
+ /* Puncturing penalty tests */
+ {
+ .desc = "80 MHz with 20 MHz punctured: 3 active subchannels",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_5ghz_80mhz,
+ .active = false,
+ .signal = -70,
+ .punctured = 0x2,
+ },
+ /* 548 * 0.85 (5GHz load) * 3/4 (puncturing) */
+ .expected_grade = 349,
+ },
+ {
+ .desc = "160 MHz with 40 MHz punctured: 6 active subchannels",
+ .link = {
+ .link_id = 0,
+ .chandef = &chandef_5ghz_160mhz,
+ .active = false,
+ .signal = -65,
+ .punctured = 0xC,
+ },
+ /* 1240 * 0.85 (5GHz load) * 6/8 (puncturing) */
+ .expected_grade = 791,
},
};
KUNIT_ARRAY_PARAM_DESC(link_grading, link_grading_cases, desc);
+static s8 fake_dup_beacon_rssi_adjust(struct iwl_mld *mld,
+ struct ieee80211_bss_conf *link_conf)
+{
+ const struct link_grading_test_case *params =
+ kunit_get_current_test()->param_value;
+
+ return params->link.dup_beacon_adj;
+}
+
+static s8 fake_psd_eirp_rssi_adjust(struct ieee80211_bss_conf *link_conf)
+{
+ const struct link_grading_test_case *params =
+ kunit_get_current_test()->param_value;
+
+ return params->link.psd_eirp_adj;
+}
+
static void setup_link(struct ieee80211_bss_conf *link)
{
struct kunit *test = kunit_get_current_test();
@@ -88,14 +293,14 @@ static void setup_link(struct ieee80211_bss_conf *link)
KUNIT_ALLOC_AND_ASSERT(test, link->bss);
- link->bss->signal = DBM_TO_MBM(test_param->input.link.signal);
+ link->bss->signal = DBM_TO_MBM(test_param->link.signal);
- link->chanreq.oper = *test_param->input.link.chandef;
+ link->chanreq.oper = *test_param->link.chandef;
- if (test_param->input.link.has_chan_util_elem) {
+ if (test_param->link.has_chan_util_elem) {
struct cfg80211_bss_ies *ies;
struct ieee80211_bss_load_elem bss_load = {
- .channel_util = test_param->input.link.chan_util,
+ .channel_util = test_param->link.chan_util,
};
struct element *elem =
iwlmld_kunit_gen_element(WLAN_EID_QBSS_LOAD,
@@ -110,7 +315,10 @@ static void setup_link(struct ieee80211_bss_conf *link)
rcu_assign_pointer(link->bss->ies, ies);
}
- if (test_param->input.link.active) {
+ if (test_param->link.punctured)
+ link->chanreq.oper.punctured = test_param->link.punctured;
+
+ if (test_param->link.active) {
struct ieee80211_chanctx_conf *chan_ctx =
wiphy_dereference(mld->wiphy, link->chanctx_conf);
struct iwl_mld_phy *phy;
@@ -119,7 +327,7 @@ static void setup_link(struct ieee80211_bss_conf *link)
phy = iwl_mld_phy_from_mac80211(chan_ctx);
- phy->channel_load_by_us = test_param->input.link.chan_load_by_us;
+ phy->channel_load_by_us = test_param->link.chan_load_by_us;
}
}
@@ -131,12 +339,11 @@ static void test_link_grading(struct kunit *test)
struct ieee80211_vif *vif;
struct ieee80211_bss_conf *link;
unsigned int actual_grade;
- /* Extract test case parameters */
- u8 link_id = test_param->input.link.link_id;
- bool active = test_param->input.link.active;
+ u8 link_id = test_param->link.link_id;
+ bool active = test_param->link.active;
u16 valid_links;
struct iwl_mld_kunit_link assoc_link = {
- .chandef = test_param->input.link.chandef,
+ .chandef = test_param->link.chandef,
};
/* If the link is not active, use a different link as the assoc link */
@@ -150,6 +357,11 @@ static void test_link_grading(struct kunit *test)
vif = iwlmld_kunit_setup_mlo_assoc(valid_links, &assoc_link);
+ kunit_activate_static_stub(test, iwl_mld_get_dup_beacon_rssi_adjust,
+ fake_dup_beacon_rssi_adjust);
+ kunit_activate_static_stub(test, iwl_mld_get_psd_eirp_rssi_adjust,
+ fake_psd_eirp_rssi_adjust);
+
wiphy_lock(mld->wiphy);
link = wiphy_dereference(mld->wiphy, vif->link_conf[link_id]);
KUNIT_ASSERT_NOT_NULL(test, link);
--
2.34.1
^ permalink raw reply related
* [PATCH wireless-next 08/10] wifi: iwlwifi: mld: add KUnit tests for PSD/EIRP RSSI adjustment
From: Miri Korenblit @ 2026-05-31 10:53 UTC (permalink / raw)
To: linux-wireless; +Cc: Avinash Bhatt
In-Reply-To: <20260531105309.125363-1-miriam.rachel.korenblit@intel.com>
From: Avinash Bhatt <avinash.bhatt@intel.com>
Add tests for PSD/EIRP RSSI adjustment which compensates measurements
when APs use PSD-based power scaling with bandwidth.
Tests cover all power types, bandwidths, and limiting scenarios.
Signed-off-by: Avinash Bhatt <avinash.bhatt@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mld/link.c | 4 +-
drivers/net/wireless/intel/iwlwifi/mld/link.h | 1 +
.../wireless/intel/iwlwifi/mld/tests/link.c | 372 ++++++++++++++++++
.../wireless/intel/iwlwifi/mld/tests/utils.h | 2 +
4 files changed, 378 insertions(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.c b/drivers/net/wireless/intel/iwlwifi/mld/link.c
index 98b9c4eef583..2b8b0196692e 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/link.c
@@ -1098,7 +1098,8 @@ static s8 iwl_mld_get_primary_psd(const struct ieee80211_parsed_tpe_psd *psd,
return psd->power[primary_idx] / 2;
}
-static s8 iwl_mld_get_psd_eirp_rssi_adjust(struct ieee80211_bss_conf *link_conf)
+VISIBLE_IF_IWLWIFI_KUNIT s8
+iwl_mld_get_psd_eirp_rssi_adjust(struct ieee80211_bss_conf *link_conf)
{
const struct ieee80211_parsed_tpe *tpe = &link_conf->tpe;
s8 psd_20mhz, psd_oper, psd_local, psd_reg, psd_boost;
@@ -1217,6 +1218,7 @@ static s8 iwl_mld_get_psd_eirp_rssi_adjust(struct ieee80211_bss_conf *link_conf)
return adjustment;
}
+EXPORT_SYMBOL_IF_IWLWIFI_KUNIT(iwl_mld_get_psd_eirp_rssi_adjust);
/* This function calculates the grade of a link. Returns 0 in error case */
unsigned int iwl_mld_get_link_grade(struct iwl_mld *mld,
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/link.h b/drivers/net/wireless/intel/iwlwifi/mld/link.h
index d0aa577de81d..7b56819d45fe 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/link.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/link.h
@@ -145,6 +145,7 @@ unsigned int iwl_mld_get_link_grade(struct iwl_mld *mld,
#if IS_ENABLED(CONFIG_IWLWIFI_KUNIT_TESTS)
s8 iwl_mld_get_dup_beacon_rssi_adjust(struct iwl_mld *mld,
struct ieee80211_bss_conf *link_conf);
+s8 iwl_mld_get_psd_eirp_rssi_adjust(struct ieee80211_bss_conf *link_conf);
#endif
unsigned int iwl_mld_get_chan_load(struct iwl_mld *mld,
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/link.c b/drivers/net/wireless/intel/iwlwifi/mld/tests/link.c
index 21bcc341cd7d..a4e5f2be499f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tests/link.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/link.c
@@ -158,6 +158,354 @@ static const struct dup_beacon_test_case dup_beacon_cases[] = {
KUNIT_ARRAY_PARAM_DESC(test_dup_beacon_rssi_adjust, dup_beacon_cases, desc);
+struct psd_eirp_test_case {
+ const char *desc;
+ const struct cfg80211_chan_def *chandef;
+ enum ieee80211_ap_reg_power power_type;
+ struct {
+ s8 psd_20;
+ s8 psd_oper;
+ s8 eirp_20;
+ s8 eirp_oper;
+ } local, reg;
+ s8 expected_adj;
+ struct {
+ bool no_psd_data;
+ bool no_eirp_data;
+ bool no_reg_psd_data;
+ bool has_partial_psd;
+ u8 psd_partial_count;
+ bool non_uniform_psd;
+ bool has_unusable_channels;
+ } flags;
+};
+
+static const struct psd_eirp_test_case psd_eirp_cases[] = {
+ {
+ .desc = "20 MHz VLP baseline - no boost expected",
+ .chandef = &chandef_6ghz_20mhz,
+ .power_type = IEEE80211_REG_VLP_AP,
+ .local = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 40,
+ },
+ .reg = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 40,
+ },
+ .expected_adj = 0,
+ },
+ {
+ .desc = "40 MHz VLP - power limit prevents boost",
+ .chandef = &chandef_6ghz_40mhz,
+ .power_type = IEEE80211_REG_VLP_AP,
+ .local = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 46,
+ },
+ .reg = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 46,
+ },
+ .expected_adj = 0,
+ },
+ {
+ .desc = "80 MHz LPI - power limit caps the boost",
+ .chandef = &chandef_6ghz_80mhz,
+ .power_type = IEEE80211_REG_LPI_AP,
+ .local = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 52,
+ },
+ .reg = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 52,
+ },
+ .expected_adj = 3,
+ },
+ {
+ .desc = "160 MHz LPI - power limit caps the boost",
+ .chandef = &chandef_6ghz_160mhz,
+ .power_type = IEEE80211_REG_LPI_AP,
+ .local = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 58,
+ },
+ .reg = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 58,
+ },
+ .expected_adj = 3,
+ },
+ {
+ .desc = "320 MHz SP - power limit caps the boost",
+ .chandef = &chandef_6ghz_320mhz_pri0,
+ .power_type = IEEE80211_REG_SP_AP,
+ .local = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 63,
+ },
+ .reg = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 63,
+ },
+ .expected_adj = 3,
+ },
+ {
+ .desc = "80 MHz - EIRP prevents boost",
+ .chandef = &chandef_6ghz_80mhz,
+ .power_type = IEEE80211_REG_LPI_AP,
+ .local = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 20,
+ },
+ .reg = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 20,
+ },
+ .expected_adj = 0,
+ },
+ {
+ .desc = "40 MHz - regulatory TPE sets lower limits",
+ .chandef = &chandef_6ghz_40mhz,
+ .power_type = IEEE80211_REG_LPI_AP,
+ .local = {
+ .psd_20 = 30, .psd_oper = 30,
+ .eirp_20 = 50, .eirp_oper = 56,
+ },
+ .reg = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 46,
+ },
+ .expected_adj = 3,
+ },
+ {
+ .desc = "80 MHz - PSD missing, use EIRP only",
+ .chandef = &chandef_6ghz_80mhz,
+ .power_type = IEEE80211_REG_LPI_AP,
+ .local = {
+ .psd_20 = S8_MAX, .psd_oper = S8_MAX,
+ .eirp_20 = 40, .eirp_oper = 52,
+ },
+ .reg = {
+ .psd_20 = S8_MAX, .psd_oper = S8_MAX,
+ .eirp_20 = 40, .eirp_oper = 52,
+ },
+ .expected_adj = 0,
+ .flags.no_psd_data = true,
+ },
+ {
+ .desc = "80 MHz - single PSD source available",
+ .chandef = &chandef_6ghz_80mhz,
+ .power_type = IEEE80211_REG_LPI_AP,
+ .local = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 52,
+ },
+ .reg = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 52,
+ },
+ .expected_adj = 3,
+ .flags.no_reg_psd_data = true,
+ },
+ {
+ .desc = "80 MHz - partial PSD data present",
+ .chandef = &chandef_6ghz_80mhz,
+ .power_type = IEEE80211_REG_LPI_AP,
+ .local = {
+ .psd_20 = 24, .psd_oper = 24,
+ .eirp_20 = 40, .eirp_oper = 56,
+ },
+ .reg = {
+ .psd_20 = 24, .psd_oper = 24,
+ .eirp_20 = 40, .eirp_oper = 56,
+ },
+ .expected_adj = 0,
+ .flags.has_partial_psd = true,
+ .flags.psd_partial_count = 2,
+ },
+ {
+ .desc = "160 MHz - different PSD per sub-channel",
+ .chandef = &chandef_6ghz_160mhz,
+ .power_type = IEEE80211_REG_LPI_AP,
+ .local = {
+ .psd_20 = 8, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 58,
+ },
+ .reg = {
+ .psd_20 = 8, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 58,
+ },
+ .expected_adj = 11,
+ .flags.non_uniform_psd = true,
+ },
+ {
+ .desc = "80 MHz - EIRP missing, use PSD only",
+ .chandef = &chandef_6ghz_80mhz,
+ .power_type = IEEE80211_REG_LPI_AP,
+ .local = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = S8_MAX, .eirp_oper = S8_MAX,
+ },
+ .reg = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = S8_MAX, .eirp_oper = S8_MAX,
+ },
+ .expected_adj = 3,
+ .flags.no_eirp_data = true,
+ },
+ {
+ .desc = "80 MHz - skip unusable channels in average",
+ .chandef = &chandef_6ghz_80mhz,
+ .power_type = IEEE80211_REG_LPI_AP,
+ .local = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 52,
+ },
+ .reg = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 52,
+ },
+ .expected_adj = 3,
+ .flags.has_unusable_channels = true,
+ },
+ {
+ .desc = "40 MHz - no negative adjustment",
+ .chandef = &chandef_6ghz_40mhz,
+ .power_type = IEEE80211_REG_LPI_AP,
+ .local = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 18,
+ },
+ .reg = {
+ .psd_20 = 20, .psd_oper = 20,
+ .eirp_20 = 40, .eirp_oper = 18,
+ },
+ .expected_adj = 0,
+ },
+};
+
+KUNIT_ARRAY_PARAM_DESC(test_psd_eirp_rssi_adjust, psd_eirp_cases, desc);
+
+static void setup_psd(struct ieee80211_bss_conf *link_conf,
+ const struct psd_eirp_test_case *params,
+ int num_subchannels)
+{
+ int i;
+
+ if (params->flags.no_psd_data) {
+ link_conf->tpe.psd_local[0].valid = false;
+ link_conf->tpe.psd_reg_client[0].valid = false;
+ link_conf->tpe.psd_local[0].count = 0;
+ link_conf->tpe.psd_reg_client[0].count = 0;
+ } else if (params->flags.no_reg_psd_data) {
+ link_conf->tpe.psd_local[0].valid = true;
+ link_conf->tpe.psd_local[0].count = num_subchannels;
+ link_conf->tpe.psd_reg_client[0].valid = false;
+ link_conf->tpe.psd_reg_client[0].count = 0;
+ } else if (params->flags.has_partial_psd) {
+ link_conf->tpe.psd_local[0].valid = true;
+ link_conf->tpe.psd_local[0].count =
+ params->flags.psd_partial_count;
+ link_conf->tpe.psd_reg_client[0].valid = true;
+ link_conf->tpe.psd_reg_client[0].count =
+ params->flags.psd_partial_count;
+ } else {
+ link_conf->tpe.psd_local[0].valid = true;
+ link_conf->tpe.psd_local[0].count = num_subchannels;
+ link_conf->tpe.psd_reg_client[0].valid = true;
+ link_conf->tpe.psd_reg_client[0].count = num_subchannels;
+ }
+
+ /* TPE element stores PSD limit as value * 2 */
+ if (params->flags.non_uniform_psd) {
+ /* PSD varies per sub-channel: 10/12/10/8 dBm pattern */
+ static const s8 psd_values[] = {20, 24, 20, 16, 20, 24, 20, 16,
+ 20, 24, 20, 16, 20, 24, 20};
+ /* Set primary channel (index 0) explicitly */
+ link_conf->tpe.psd_local[0].power[0] =
+ params->local.psd_20 * 2;
+ link_conf->tpe.psd_reg_client[0].power[0] =
+ params->reg.psd_20 * 2;
+ /* Set remaining subchannels with pattern */
+ for (i = 1; i < num_subchannels; i++) {
+ link_conf->tpe.psd_local[0].power[i] =
+ psd_values[i - 1];
+ link_conf->tpe.psd_reg_client[0].power[i] =
+ psd_values[i - 1];
+ }
+ } else if (params->flags.no_psd_data) {
+ for (i = 0; i < num_subchannels; i++) {
+ link_conf->tpe.psd_local[0].power[i] = S8_MAX;
+ link_conf->tpe.psd_reg_client[0].power[i] = S8_MAX;
+ }
+ } else if (params->flags.has_unusable_channels) {
+ /* Alternate usable/unusable channels for S8_MIN test */
+ /* Set primary channel (index 0) explicitly */
+ link_conf->tpe.psd_local[0].power[0] =
+ params->local.psd_20 * 2;
+ link_conf->tpe.psd_reg_client[0].power[0] =
+ params->reg.psd_20 * 2;
+ /* Alternate usable/unusable for remaining subchannels */
+ for (i = 1; i < num_subchannels; i++) {
+ if (i % 2 == 0) {
+ link_conf->tpe.psd_local[0].power[i] =
+ params->local.psd_oper * 2;
+ link_conf->tpe.psd_reg_client[0].power[i] =
+ params->reg.psd_oper * 2;
+ } else {
+ link_conf->tpe.psd_local[0].power[i] = S8_MIN;
+ link_conf->tpe.psd_reg_client[0].power[i] =
+ S8_MIN;
+ }
+ }
+ } else {
+ /* Set primary channel (index 0) separately */
+ link_conf->tpe.psd_local[0].power[0] =
+ params->local.psd_20 * 2;
+ link_conf->tpe.psd_reg_client[0].power[0] =
+ params->reg.psd_20 * 2;
+ /* Set remaining subchannels */
+ for (i = 1; i < num_subchannels; i++) {
+ link_conf->tpe.psd_local[0].power[i] =
+ params->local.psd_oper * 2;
+ link_conf->tpe.psd_reg_client[0].power[i] =
+ params->reg.psd_oper * 2;
+ }
+ }
+}
+
+static void setup_eirp(struct ieee80211_bss_conf *link_conf,
+ const struct psd_eirp_test_case *params,
+ int num_subchannels)
+{
+ int i;
+ int count = ilog2(num_subchannels) + 1;
+
+ link_conf->tpe.max_local[0].valid = !params->flags.no_eirp_data;
+ link_conf->tpe.max_reg_client[0].valid = !params->flags.no_eirp_data;
+
+ if (params->flags.no_eirp_data) {
+ link_conf->tpe.max_local[0].count = 0;
+ link_conf->tpe.max_reg_client[0].count = 0;
+ return;
+ }
+
+ link_conf->tpe.max_local[0].count = count;
+ link_conf->tpe.max_reg_client[0].count = count;
+
+ /* TPE element stores EIRP limit as value * 2 */
+ link_conf->tpe.max_local[0].power[0] = params->local.eirp_20 * 2;
+ link_conf->tpe.max_reg_client[0].power[0] = params->reg.eirp_20 * 2;
+ for (i = 1; i < count; i++) {
+ link_conf->tpe.max_local[0].power[i] =
+ params->local.eirp_oper * 2;
+ link_conf->tpe.max_reg_client[0].power[i] =
+ params->reg.eirp_oper * 2;
+ }
+}
+
static void test_dup_beacon_rssi_adjust(struct kunit *test)
{
const struct dup_beacon_test_case *params = test->param_value;
@@ -192,10 +540,34 @@ static void test_dup_beacon_rssi_adjust(struct kunit *test)
KUNIT_EXPECT_EQ(test, result, params->expected_adj);
}
+static void test_psd_eirp_rssi_adjust(struct kunit *test)
+{
+ const struct psd_eirp_test_case *params = test->param_value;
+ struct ieee80211_bss_conf *link_conf;
+ int num_subchannels;
+ s8 result;
+
+ KUNIT_ALLOC_AND_ASSERT(test, link_conf);
+
+ link_conf->power_type = params->power_type;
+ link_conf->chanreq.oper = *params->chandef;
+ num_subchannels =
+ nl80211_chan_width_to_mhz(params->chandef->width) / 20;
+
+ setup_psd(link_conf, params, num_subchannels);
+ setup_eirp(link_conf, params, num_subchannels);
+
+ result = iwl_mld_get_psd_eirp_rssi_adjust(link_conf);
+
+ KUNIT_EXPECT_EQ(test, result, params->expected_adj);
+}
+
static struct kunit_case link_cases[] = {
KUNIT_CASE_PARAM(test_missed_beacon, test_missed_beacon_gen_params),
KUNIT_CASE_PARAM(test_dup_beacon_rssi_adjust,
test_dup_beacon_rssi_adjust_gen_params),
+ KUNIT_CASE_PARAM(test_psd_eirp_rssi_adjust,
+ test_psd_eirp_rssi_adjust_gen_params),
{},
};
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.h b/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.h
index cfed5acaac3a..7cc8cb6eedd6 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.h
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tests/utils.h
@@ -77,6 +77,8 @@ CHANNEL(chan_6ghz_221, NL80211_BAND_6GHZ, 7055);
NL80211_CHAN_WIDTH_160) \
CHANDEF(chandef_6ghz_320mhz, chan_6ghz, 6105, \
NL80211_CHAN_WIDTH_320) \
+ CHANDEF(chandef_6ghz_320mhz_pri0, chan_6ghz, 6265, \
+ NL80211_CHAN_WIDTH_320) \
CHANDEF(chandef_6ghz_221_160mhz, chan_6ghz_221, 6985, \
NL80211_CHAN_WIDTH_160) \
/* Feel free to add more */
--
2.34.1
^ permalink raw reply related
* [PATCH wireless-next 07/10] wifi: iwlwifi: mld: drop TLC config cmd v4/v5 compat code
From: Miri Korenblit @ 2026-05-31 10:53 UTC (permalink / raw)
To: linux-wireless; +Cc: Shahar Tzarfati
In-Reply-To: <20260531105309.125363-1-miriam.rachel.korenblit@intel.com>
From: Shahar Tzarfati <shahar.tzarfati@intel.com>
FW core102 bumped TLC_MNG_CONFIG_CMD_API_S from version 5 to
version 6. The v4 and v5 compatibility paths in
iwl_mld_send_tlc_cmd() are no longer reachable on any supported
firmware.
Signed-off-by: Shahar Tzarfati <shahar.tzarfati@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
.../wireless/intel/iwlwifi/fw/api/datapath.h | 2 +-
.../net/wireless/intel/iwlwifi/fw/api/rs.h | 31 --------
drivers/net/wireless/intel/iwlwifi/mld/tlc.c | 74 -------------------
3 files changed, 1 insertion(+), 106 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
index e494e5b18d22..c8eb016e1a7e 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/datapath.h
@@ -57,7 +57,7 @@ enum iwl_data_path_subcmd_ids {
/**
* @TLC_MNG_CONFIG_CMD: &struct iwl_tlc_config_cmd_v4 or
- * &struct iwl_tlc_config_cmd_v5 or &struct iwl_tlc_config_cmd.
+ * &struct iwl_tlc_config_cmd.
*/
TLC_MNG_CONFIG_CMD = 0xF,
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
index f90e743caa7e..f1254546cc9d 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rs.h
@@ -206,37 +206,6 @@ struct iwl_tlc_config_cmd_v4 {
__le16 max_tx_op;
} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_4 */
-/**
- * struct iwl_tlc_config_cmd_v5 - TLC configuration
- * @sta_id: station id
- * @reserved1: reserved
- * @max_ch_width: max supported channel width from &enum iwl_tlc_mng_cfg_cw
- * @mode: &enum iwl_tlc_mng_cfg_mode
- * @chains: bitmask of &enum iwl_tlc_mng_cfg_chains
- * @sgi_ch_width_supp: bitmap of SGI support per channel width
- * use BIT(&enum iwl_tlc_mng_cfg_cw)
- * @flags: bitmask of &enum iwl_tlc_mng_cfg_flags
- * @non_ht_rates: bitmap of supported legacy rates
- * @ht_rates: bitmap of &enum iwl_tlc_mng_ht_rates, per <nss, channel-width>
- * pair (0 - 80mhz width and below, 1 - 160mhz, 2 - 320mhz).
- * @max_mpdu_len: max MPDU length, in bytes
- * @max_tx_op: max TXOP in uSecs for all AC (BK, BE, VO, VI),
- * set zero for no limit.
- */
-struct iwl_tlc_config_cmd_v5 {
- u8 sta_id;
- u8 reserved1[3];
- u8 max_ch_width;
- u8 mode;
- u8 chains;
- u8 sgi_ch_width_supp;
- __le16 flags;
- __le16 non_ht_rates;
- __le32 ht_rates[IWL_TLC_NSS_MAX][IWL_TLC_MCS_PER_BW_NUM_V4];
- __le16 max_mpdu_len;
- __le16 max_tx_op;
-} __packed; /* TLC_MNG_CONFIG_CMD_API_S_VER_5 */
-
/**
* struct iwl_tlc_config_cmd - TLC configuration
* @sta_mask: station mask (in NAN we can have multiple logical stations of
diff --git a/drivers/net/wireless/intel/iwlwifi/mld/tlc.c b/drivers/net/wireless/intel/iwlwifi/mld/tlc.c
index a03834d3ac65..d044c9ba639f 100644
--- a/drivers/net/wireless/intel/iwlwifi/mld/tlc.c
+++ b/drivers/net/wireless/intel/iwlwifi/mld/tlc.c
@@ -467,65 +467,6 @@ iwl_mld_fill_supp_rates(struct iwl_mld *mld,
}
}
-static int iwl_mld_convert_tlc_cmd_to_v5(struct iwl_tlc_config_cmd *cmd,
- struct iwl_tlc_config_cmd_v5 *cmd_v5)
-{
- if (WARN_ON_ONCE(hweight32(le32_to_cpu(cmd->sta_mask)) != 1))
- return -EINVAL;
-
- /* Convert sta_mask to sta_id */
- cmd_v5->sta_id = __ffs(le32_to_cpu(cmd->sta_mask));
-
- /* Copy all the rest */
- cmd_v5->max_ch_width = cmd->max_ch_width;
- cmd_v5->mode = cmd->mode;
- cmd_v5->chains = cmd->chains;
- cmd_v5->sgi_ch_width_supp = cmd->sgi_ch_width_supp;
- cmd_v5->flags = cmd->flags;
- cmd_v5->non_ht_rates = cmd->non_ht_rates;
-
- BUILD_BUG_ON(sizeof(cmd_v5->ht_rates) != sizeof(cmd->ht_rates));
- memcpy(cmd_v5->ht_rates, cmd->ht_rates, sizeof(cmd->ht_rates));
-
- cmd_v5->max_mpdu_len = cmd->max_mpdu_len;
- cmd_v5->max_tx_op = cmd->max_tx_op;
-
- return 0;
-}
-
-static int iwl_mld_convert_tlc_cmd_to_v4(struct iwl_tlc_config_cmd *cmd,
- struct iwl_tlc_config_cmd_v4 *cmd_v4)
-{
- if (WARN_ON_ONCE(hweight32(le32_to_cpu(cmd->sta_mask)) != 1))
- return -EINVAL;
-
- /* Convert sta_mask to sta_id */
- cmd_v4->sta_id = __ffs(le32_to_cpu(cmd->sta_mask));
-
- /* Copy everything until ht_rates */
- cmd_v4->max_ch_width = cmd->max_ch_width;
- cmd_v4->mode = cmd->mode;
- cmd_v4->chains = cmd->chains;
- cmd_v4->sgi_ch_width_supp = cmd->sgi_ch_width_supp;
- cmd_v4->flags = cmd->flags;
- cmd_v4->non_ht_rates = cmd->non_ht_rates;
-
- /* Convert ht_rates from __le32 to __le16 */
- BUILD_BUG_ON(ARRAY_SIZE(cmd_v4->ht_rates) != ARRAY_SIZE(cmd->ht_rates));
- BUILD_BUG_ON(ARRAY_SIZE(cmd_v4->ht_rates[0]) != ARRAY_SIZE(cmd->ht_rates[0]));
-
- for (int nss = 0; nss < ARRAY_SIZE(cmd->ht_rates); nss++)
- for (int bw = 0; bw < ARRAY_SIZE(cmd->ht_rates[nss]); bw++)
- cmd_v4->ht_rates[nss][bw] =
- cpu_to_le16(le32_to_cpu(cmd->ht_rates[nss][bw]));
-
- /* Copy the rest */
- cmd_v4->max_mpdu_len = cmd->max_mpdu_len;
- cmd_v4->max_tx_op = cmd->max_tx_op;
-
- return 0;
-}
-
static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
struct ieee80211_vif *vif,
struct iwl_mld_sta *mld_sta,
@@ -544,8 +485,6 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
};
u32 cmd_id = WIDE_ID(DATA_PATH_GROUP, TLC_MNG_CONFIG_CMD);
u8 cmd_ver = iwl_fw_lookup_cmd_ver(mld->fw, cmd_id, 0);
- struct iwl_tlc_config_cmd_v5 cmd_v5 = {};
- struct iwl_tlc_config_cmd_v4 cmd_v4 = {};
void *cmd_ptr;
u8 cmd_size;
int ret;
@@ -558,19 +497,6 @@ static void iwl_mld_send_tlc_cmd(struct iwl_mld *mld,
if (cmd_ver == 6) {
cmd_ptr = &cmd;
cmd_size = sizeof(cmd);
- } else if (cmd_ver == 5) {
- /* TODO: remove support once FW moves to version 6 */
- ret = iwl_mld_convert_tlc_cmd_to_v5(&cmd, &cmd_v5);
- if (ret)
- return;
- cmd_ptr = &cmd_v5;
- cmd_size = sizeof(cmd_v5);
- } else if (cmd_ver == 4) {
- ret = iwl_mld_convert_tlc_cmd_to_v4(&cmd, &cmd_v4);
- if (ret)
- return;
- cmd_ptr = &cmd_v4;
- cmd_size = sizeof(cmd_v4);
} else {
IWL_ERR(mld, "Unsupported TLC config cmd version %d\n",
cmd_ver);
--
2.34.1
^ permalink raw reply related
* [PATCH wireless-next 06/10] wifi: iwlwifi: mvm: remove __must_check annotation from command sending
From: Miri Korenblit @ 2026-05-31 10:53 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <20260531105309.125363-1-miriam.rachel.korenblit@intel.com>
We don't acually need to always check the return value. For example, if
we send a command to remove an object - we can assume success
(if it fails it is probably because the fw is dead, and then it doesn't
have the object anyway).
Remove the annotations.
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
index 6bf71092faa1..683cac56822c 100644
--- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h
@@ -1673,16 +1673,16 @@ void iwl_mvm_get_sync_time(struct iwl_mvm *mvm, int clock_type, u32 *gp2,
u32 iwl_mvm_get_systime(struct iwl_mvm *mvm);
/* Tx / Host Commands */
-int __must_check iwl_mvm_send_cmd(struct iwl_mvm *mvm,
- struct iwl_host_cmd *cmd);
-int __must_check iwl_mvm_send_cmd_pdu(struct iwl_mvm *mvm, u32 id,
- u32 flags, u16 len, const void *data);
-int __must_check iwl_mvm_send_cmd_status(struct iwl_mvm *mvm,
- struct iwl_host_cmd *cmd,
- u32 *status);
-int __must_check iwl_mvm_send_cmd_pdu_status(struct iwl_mvm *mvm, u32 id,
- u16 len, const void *data,
- u32 *status);
+int iwl_mvm_send_cmd(struct iwl_mvm *mvm,
+ struct iwl_host_cmd *cmd);
+int iwl_mvm_send_cmd_pdu(struct iwl_mvm *mvm, u32 id,
+ u32 flags, u16 len, const void *data);
+int iwl_mvm_send_cmd_status(struct iwl_mvm *mvm,
+ struct iwl_host_cmd *cmd,
+ u32 *status);
+int iwl_mvm_send_cmd_pdu_status(struct iwl_mvm *mvm, u32 id,
+ u16 len, const void *data,
+ u32 *status);
int iwl_mvm_tx_skb_sta(struct iwl_mvm *mvm, struct sk_buff *skb,
struct ieee80211_sta *sta);
int iwl_mvm_tx_skb_non_sta(struct iwl_mvm *mvm, struct sk_buff *skb);
--
2.34.1
^ permalink raw reply related
* [PATCH wireless-next 05/10] wifi: iwlwifi: trans: export the maximum supported hcmd size
From: Miri Korenblit @ 2026-05-31 10:53 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260531105309.125363-1-miriam.rachel.korenblit@intel.com>
Export the maximum allowed host command payload size to the op-modes.
Note that this information was available to the op-modes also before
this change, this just adds a clear macro.
Reviewed-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/iwl-trans.h | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
index 914864005704..c581cc8f5bcb 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h
@@ -161,6 +161,10 @@ struct iwl_device_tx_cmd {
#define TFD_MAX_PAYLOAD_SIZE (sizeof(struct iwl_device_cmd))
+/* Maximum payload size for a non-NOCOPY host command (excluding the header) */
+#define IWL_MAX_CMD_PAYLOAD_SIZE \
+ (TFD_MAX_PAYLOAD_SIZE - sizeof(struct iwl_cmd_header_wide))
+
/*
* number of transfer buffers (fragments) per transmit frame descriptor;
* this is just the driver's idea, the hardware supports 20
--
2.34.1
^ permalink raw reply related
* [PATCH wireless-next 04/10] wifi: iwlwifi: stop supporting core101
From: Miri Korenblit @ 2026-05-31 10:53 UTC (permalink / raw)
To: linux-wireless; +Cc: Shahar Tzarfati
In-Reply-To: <20260531105309.125363-1-miriam.rachel.korenblit@intel.com>
From: Shahar Tzarfati <shahar.tzarfati@intel.com>
BZ, DR and SC no longer need to accept core101 firmware.
Raise the minimum supported firmware core from 101 to 102 so
these families only match supported core102 and newer images.
Signed-off-by: Shahar Tzarfati <shahar.tzarfati@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/cfg/bz.c | 2 +-
drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 2 +-
drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
index 9cdc4f142c7f..1542cbc3bb22 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/bz.c
@@ -13,7 +13,7 @@
#define IWL_BZ_UCODE_CORE_MAX 105
/* Lowest firmware core release supported */
-#define IWL_BZ_UCODE_CORE_MIN 101
+#define IWL_BZ_UCODE_CORE_MIN 102
#define IWL_BZ_A_FM_B_FW_PRE "iwlwifi-bz-a0-fm-b0"
#define IWL_BZ_A_FM_C_FW_PRE "iwlwifi-bz-a0-fm-c0"
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
index e8968b3051d3..6a5870619411 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/dr.c
@@ -12,7 +12,7 @@
#define IWL_DR_UCODE_CORE_MAX 105
/* Lowest firmware core release supported */
-#define IWL_DR_UCODE_CORE_MIN 101
+#define IWL_DR_UCODE_CORE_MIN 102
#define IWL_DR_A_PE_A_FW_PRE "iwlwifi-dr-a0-pe-a0"
diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
index 6aaa49aeec99..f8913293ccef 100644
--- a/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
+++ b/drivers/net/wireless/intel/iwlwifi/cfg/sc.c
@@ -13,7 +13,7 @@
#define IWL_SC_UCODE_CORE_MAX 105
/* Lowest firmware core release supported */
-#define IWL_SC_UCODE_CORE_MIN 101
+#define IWL_SC_UCODE_CORE_MIN 102
#define IWL_SC_A_FM_B_FW_PRE "iwlwifi-sc-a0-fm-b0"
#define IWL_SC_A_FM_C_FW_PRE "iwlwifi-sc-a0-fm-c0"
--
2.34.1
^ permalink raw reply related
* [PATCH wireless-next 03/10] wifi: iwlwifi: remove orphaned DC2DC config enum
From: Miri Korenblit @ 2026-05-31 10:53 UTC (permalink / raw)
To: linux-wireless; +Cc: Shahar Tzarfati
In-Reply-To: <20260531105309.125363-1-miriam.rachel.korenblit@intel.com>
From: Shahar Tzarfati <shahar.tzarfati@intel.com>
FW core102 removed both DC2DC_CONFIG_CMD_API_S and
DC2DC_CONFIG_CMD_RSP_API_S. The only driver-side artifact is
enum iwl_dc2dc_config_id in fw/api/config.h, which has no
callers in any .c file across all driver paths (mld/mvm/xvt).
Remove the dead definition.
Signed-off-by: Shahar Tzarfati <shahar.tzarfati@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/fw/api/config.h | 11 +----------
1 file changed, 1 insertion(+), 10 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/config.h b/drivers/net/wireless/intel/iwlwifi/fw/api/config.h
index 1fc65469990e..84fa5ff7a57f 100644
--- a/drivers/net/wireless/intel/iwlwifi/fw/api/config.h
+++ b/drivers/net/wireless/intel/iwlwifi/fw/api/config.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause */
/*
* Copyright (C) 2012-2014, 2018-2019, 2023-2024 Intel Corporation
+ * Copyright (C) 2026 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -99,14 +100,4 @@ struct iwl_phy_cfg_cmd_v3 {
struct iwl_phy_specific_cfg phy_specific_cfg;
} __packed; /* PHY_CONFIGURATION_CMD_API_S_VER_3 */
-/*
- * enum iwl_dc2dc_config_id - flag ids
- *
- * Ids of dc2dc configuration flags
- */
-enum iwl_dc2dc_config_id {
- DCDC_LOW_POWER_MODE_MSK_SET = 0x1, /* not used */
- DCDC_FREQ_TUNE_SET = 0x2,
-}; /* MARKER_ID_API_E_VER_1 */
-
#endif /* __iwl_fw_api_config_h__ */
--
2.34.1
^ permalink raw reply related
* [PATCH wireless-next 02/10] wifi: iwlwifi: fix a typo
From: Miri Korenblit @ 2026-05-31 10:53 UTC (permalink / raw)
To: linux-wireless
In-Reply-To: <20260531105309.125363-1-miriam.rachel.korenblit@intel.com>
We use 512 A-MSDUs in an A-MPDU, not 612. Fix the typo.
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/iwl-config.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
index 933a96131d1a..6a3539ad7331 100644
--- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h
@@ -372,7 +372,7 @@ struct iwl_mac_cfg {
};
/*
- * These sizes were picked according to 8 MSDUs inside 64/256/612 A-MSDUs
+ * These sizes were picked according to 8 MSDUs inside 64/256/512 A-MSDUs
* in an A-MPDU, with additional overhead to account for processing time.
* They will be doubled for MACs starting from So/Ty that don't support
* putting multiple frames into a single buffer.
--
2.34.1
^ permalink raw reply related
* [PATCH wireless-next 01/10] wifi: iwlwifi: pcie: fix write pointer move detection
From: Miri Korenblit @ 2026-05-31 10:53 UTC (permalink / raw)
To: linux-wireless; +Cc: Johannes Berg
In-Reply-To: <20260531105309.125363-1-miriam.rachel.korenblit@intel.com>
From: Johannes Berg <johannes.berg@intel.com>
Ever since the TFD queue size is no longer limited to 256 entries,
this code has been wrong, and might erroneously not detect a move
if it was by a multiple of 256. Not a big deal, but fix it while
I see it.
Fixes: 7b3e42ea2ead ("iwlwifi: support multiple tfd queue max sizes for different devices")
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
index 976a47ef6d0e..28b276c65952 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c
@@ -2590,7 +2590,7 @@ int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx)
struct iwl_txq *txq;
unsigned long now = jiffies;
bool overflow_tx;
- u8 wr_ptr;
+ int wr_ptr;
/* Make sure the NIC is still alive in the bus */
if (test_bit(STATUS_TRANS_DEAD, &trans->status))
@@ -2613,7 +2613,7 @@ int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx)
overflow_tx) &&
!time_after(jiffies,
now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) {
- u8 write_ptr = READ_ONCE(txq->write_ptr);
+ int write_ptr = READ_ONCE(txq->write_ptr);
/*
* If write pointer moved during the wait, warn only
--
2.34.1
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox