* [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
* [PATCH wireless-next 00/10] wifi: iwlwifi: updates - 2026-05-31
From: Miri Korenblit @ 2026-05-31 10:52 UTC (permalink / raw)
To: linux-wireless
Hi,
A few cleanups, features and bugfixes from our internal tree.
Thanks,
Miri
---
Avinash Bhatt (2):
wifi: iwlwifi: mld: add KUnit tests for PSD/EIRP RSSI adjustment
wifi: iwlwifi: mld: add KUnit tests for link grading
Emmanuel Grumbach (1):
wifi: iwlwifi: bump maximum core version for BZ/SC/DR to 106
Johannes Berg (1):
wifi: iwlwifi: pcie: fix write pointer move detection
Miri Korenblit (3):
wifi: iwlwifi: fix a typo
wifi: iwlwifi: trans: export the maximum supported hcmd size
wifi: iwlwifi: mvm: remove __must_check annotation from command
sending
Shahar Tzarfati (3):
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 | 4 +-
drivers/net/wireless/intel/iwlwifi/cfg/dr.c | 4 +-
drivers/net/wireless/intel/iwlwifi/cfg/sc.c | 4 +-
.../wireless/intel/iwlwifi/fw/api/config.h | 11 +-
.../wireless/intel/iwlwifi/fw/api/datapath.h | 2 +-
.../net/wireless/intel/iwlwifi/fw/api/rs.h | 31 --
.../net/wireless/intel/iwlwifi/iwl-config.h | 2 +-
.../net/wireless/intel/iwlwifi/iwl-trans.h | 4 +
drivers/net/wireless/intel/iwlwifi/mld/link.c | 12 +-
drivers/net/wireless/intel/iwlwifi/mld/link.h | 1 +
.../intel/iwlwifi/mld/tests/link-selection.c | 280 +++++++++++--
.../wireless/intel/iwlwifi/mld/tests/link.c | 372 ++++++++++++++++++
.../wireless/intel/iwlwifi/mld/tests/utils.h | 2 +
drivers/net/wireless/intel/iwlwifi/mld/tlc.c | 74 ----
drivers/net/wireless/intel/iwlwifi/mvm/mvm.h | 20 +-
.../intel/iwlwifi/pcie/gen1_2/trans.c | 4 +-
16 files changed, 657 insertions(+), 170 deletions(-)
--
2.34.1
^ permalink raw reply
* [PATCH wireless-fixes] wifi: iwlwifi: pcie: simplify the resume flow if fast resume is not used
From: Miri Korenblit @ 2026-05-31 10:30 UTC (permalink / raw)
To: linux-wireless; +Cc: Emmanuel Grumbach, stable
From: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
In most distributions, NetworkManager shuts the device down before
entering system suspend, so fast suspend is typically not used.
On older devices, resume currently tries to grab NIC access to infer
whether the device was powered off while suspended. That probe is only
meaningful for the fast-suspend path where the device is expected to
remain alive.
Unfortunately, for unclear reasons, grabbing NIC access was harmful as
reported in the bugzilla ticket below.
Workaround this issue by simply not grabbing NIC access if fast suspend
is not used.
Fixes: 6a0f81c549a0 ("wifi: iwlwifi: fix merge damage related to iwl_pci_resume")
Cc: stable@vger.kernel.org
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221501
Assisted-by: GitHub Copilot:gpt-5.3-codex
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
---
drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 56 +++++++++++--------
1 file changed, 32 insertions(+), 24 deletions(-)
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
index dc99e7ac4726..eb3c5a6dd088 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c
@@ -1225,33 +1225,41 @@ static int _iwl_pci_resume(struct device *device, bool restore)
if (!trans->op_mode)
return 0;
- /*
- * Scratch value was altered, this means the device was powered off, we
- * need to reset it completely.
- * Note: MAC (bits 0:7) will be cleared upon suspend even with wowlan,
- * but not bits [15:8]. So if we have bits set in lower word, assume
- * the device is alive.
- * Alternatively, if the scratch value is 0xFFFFFFFF, then we no longer
- * have access to the device and consider it powered off.
- * For older devices, just try silently to grab the NIC.
- */
- if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
- u32 scratch = iwl_read32(trans, CSR_FUNC_SCRATCH);
-
- if (!(scratch & CSR_FUNC_SCRATCH_POWER_OFF_MASK) ||
- scratch == ~0U)
- device_was_powered_off = true;
- } else {
+ if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) {
/*
- * bh are re-enabled by iwl_trans_pcie_release_nic_access,
- * so re-enable them if _iwl_trans_pcie_grab_nic_access fails.
+ * Scratch value was altered, this means the device was powered
+ * off, we need to reset it completely.
+ * Note: MAC (bits 0:7) will be cleared upon suspend even with
+ * wowlan, but not bits [15:8]. So if we have bits set in lower
+ * word, assume the device is alive.
+ * Alternatively, if the scratch value is 0xFFFFFFFF, then we
+ * no longer have access to the device and consider it powered
+ * off.
+ * For older devices, just try silently to grab the NIC.
*/
- local_bh_disable();
- if (_iwl_trans_pcie_grab_nic_access(trans, true)) {
- iwl_trans_pcie_release_nic_access(trans);
+ if (trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
+ u32 scratch = iwl_read32(trans, CSR_FUNC_SCRATCH);
+
+ if (!(scratch & CSR_FUNC_SCRATCH_POWER_OFF_MASK) ||
+ scratch == ~0U) {
+ IWL_DEBUG_WOWLAN(trans,
+ "Scratch 0x%08x indicates device was powered off\n",
+ scratch);
+ device_was_powered_off = true;
+ }
} else {
- device_was_powered_off = true;
- local_bh_enable();
+ /*
+ * bh are re-enabled by iwl_trans_pcie_release_nic_access,
+ * so re-enable them if _iwl_trans_pcie_grab_nic_access
+ * fails.
+ */
+ local_bh_disable();
+ if (_iwl_trans_pcie_grab_nic_access(trans, true)) {
+ iwl_trans_pcie_release_nic_access(trans);
+ } else {
+ device_was_powered_off = true;
+ local_bh_enable();
+ }
}
}
--
2.34.1
^ permalink raw reply related
* Re: [PATCH v2] wifi: mt76: mt7996: fix reading zeroed info->control.flags after mt76_tx_status_skb_add()
From: Ryder Lee @ 2026-05-31 10:23 UTC (permalink / raw)
To: Shayne Chen (陳軒丞), lorenzo@kernel.org,
nbd@nbd.name, AngeloGioacchino Del Regno,
Chui-hao Chiu (邱垂浩), Sean Wang,
Bo Jiao (焦波), matthias.bgg@gmail.com
Cc: 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: <20260531-mt76_tx_status_skb_add-overwrite-fix-v2-1-b73c4b4a9798@kernel.org>
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.
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
^ permalink raw reply
* Re: [PATCH] wifi: mt76: mt7996: fix reading zeroed info->control.flags after mt76_tx_status_skb_add()
From: Ryder Lee @ 2026-05-31 10:07 UTC (permalink / raw)
To: lorenzo@kernel.org
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: <ahvewFh2NuB5MO8t@lore-desk>
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.
Ryder
^ permalink raw reply
* [PATCH] wifi: mt76: mt7996: Fix possible NULL pointer dereference in mt7996_mac_write_txwi_80211()
From: Lorenzo Bianconi @ 2026-05-31 9:38 UTC (permalink / raw)
To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang,
Matthias Brugger, AngeloGioacchino Del Regno, Peter Chiu, Bo Jiao
Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
Lorenzo Bianconi
For injected frames (e.g. via radiotap), mac80211 can pass
info->control.vif = NULL, as explicitly noted in struct ieee80211_tx_info.
Check vif pointer before executing ieee80211_vif_is_mld() in
mt7996_mac_write_txwi_80211 routine in order to avoid a possible NULL
pointer dereference.
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 | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index c98446057282..5ed2c73d5c75 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -757,6 +757,7 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
bool multicast = is_multicast_ether_addr(hdr->addr1);
u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK;
__le16 fc = hdr->frame_control, sc = hdr->seq_ctrl;
+ struct ieee80211_vif *vif = info->control.vif;
u16 seqno = le16_to_cpu(sc);
bool hw_bigtk = false;
u8 fc_type, fc_stype;
@@ -819,7 +820,7 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT);
}
- if (multicast && ieee80211_vif_is_mld(info->control.vif)) {
+ if (multicast && vif && ieee80211_vif_is_mld(vif)) {
val = MT_TXD3_SN_VALID |
FIELD_PREP(MT_TXD3_SEQ, IEEE80211_SEQ_TO_SN(seqno));
txwi[3] |= cpu_to_le32(val);
@@ -839,12 +840,12 @@ mt7996_mac_write_txwi_80211(struct mt7996_dev *dev, __le32 *txwi,
txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU);
}
- if (ieee80211_vif_is_mld(info->control.vif) &&
+ if (vif && ieee80211_vif_is_mld(vif) &&
(multicast || unlikely(skb->protocol == cpu_to_be16(ETH_P_PAE))))
txwi[5] |= cpu_to_le32(MT_TXD5_FL);
if (ieee80211_is_nullfunc(fc) && ieee80211_has_a4(fc) &&
- ieee80211_vif_is_mld(info->control.vif)) {
+ vif && ieee80211_vif_is_mld(vif)) {
txwi[5] |= cpu_to_le32(MT_TXD5_FL);
txwi[6] |= cpu_to_le32(MT_TXD6_DIS_MAT);
}
---
base-commit: 4913f44167cf35a9536e9eec7352e15b2de0c573
change-id: 20260531-mt7996_mac_write_txwi_80211-null-ptr-deref-8ce8d08cf53a
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related
* [PATCH] wifi: mt76: mt7996: Fix possible token leak in mt7996_tx_prepare_skb()
From: Lorenzo Bianconi @ 2026-05-31 9:10 UTC (permalink / raw)
To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang,
Matthias Brugger, AngeloGioacchino Del Regno
Cc: linux-wireless, linux-arm-kernel, linux-mediatek,
Lorenzo Bianconi
If link_conf or link_sta lookup fails in mt7996_tx_prepare_skb routine,
mt7996 driver leaks an already allocated tx token. Fix the issue
releasing the token in case of error.
Fixes: 7ef0c7ad735b0 ("wifi: mt76: mt7996: Implement MLD address translation for EAPOL")
Signed-off-by: Lorenzo Bianconi <lorenzo@kernel.org>
---
drivers/net/wireless/mediatek/mt76/mt7996/mac.c | 8 ++++++--
drivers/net/wireless/mediatek/mt76/tx.c | 2 +-
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index c98446057282..8c56344d211b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -1067,11 +1067,11 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
link_conf = rcu_dereference(vif->link_conf[wcid->link_id]);
if (!link_conf)
- return -EINVAL;
+ goto error_relase_token;
link_sta = rcu_dereference(sta->link[wcid->link_id]);
if (!link_sta)
- return -EINVAL;
+ goto error_relase_token;
dma_sync_single_for_cpu(mdev->dma_dev, tx_info->buf[1].addr,
tx_info->buf[1].len, DMA_TO_DEVICE);
@@ -1176,6 +1176,10 @@ int mt7996_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
tx_info->nbuf = MT_CT_DMA_BUF_NUM;
return 0;
+
+error_relase_token:
+ mt76_token_release(mdev, id, NULL);
+ return -EINVAL;
}
u32 mt7996_wed_init_buf(void *ptr, dma_addr_t phys, int token_id)
diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c
index 22f9690634c9..f96d9c471853 100644
--- a/drivers/net/wireless/mediatek/mt76/tx.c
+++ b/drivers/net/wireless/mediatek/mt76/tx.c
@@ -933,7 +933,7 @@ mt76_token_release(struct mt76_dev *dev, int token, bool *wake)
#endif
}
- if (dev->token_count < dev->token_size - MT76_TOKEN_FREE_THR &&
+ if (wake && dev->token_count < dev->token_size - MT76_TOKEN_FREE_THR &&
dev->phy.q_tx[0]->blocked)
*wake = true;
---
base-commit: 4913f44167cf35a9536e9eec7352e15b2de0c573
change-id: 20260531-mt7996_tx_prepare_skb-token-leack-82e240d8c66f
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related
* [PATCH v2] wifi: mt76: mt7996: fix reading zeroed info->control.flags after mt76_tx_status_skb_add()
From: Lorenzo Bianconi @ 2026-05-31 8:55 UTC (permalink / raw)
To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang,
Matthias Brugger, AngeloGioacchino Del Regno, Bo Jiao, Peter Chiu,
Lorenzo Bianconi
Cc: Roy Luo, linux-wireless, linux-arm-kernel, linux-mediatek,
linux-kernel
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,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related
* Re: Re: [PATCH net 1/1] wireless: wext: export each WEP key size only once
From: Lucas YQ21 Xu | 徐宇奇 @ 2026-05-31 7:16 UTC (permalink / raw)
To: Johannes Berg, Ren Wei, linux-wireless@vger.kernel.org
Cc: kilroyd@googlemail.com, linville@tuxdriver.com,
yuantan098@gmail.com, yifanwucs@gmail.com, tomapufckgml@gmail.com,
zcliangcn@gmail.com, bird@lzu.edu.cn
In-Reply-To: <1a8bbed215d7f6027d56ab42cf8f6e742d1e7fa1.camel@sipsolutions.net>
On Wed, 2026-05-27 at 18:18 +0800, Johannes Berg wrote:
> On Wed, 2026-05-27 at 18:18 +0800, Ren Wei wrote:
> > From: Yuqi Xu <xuyq21@lenovo.com>
> >
> > cfg80211_wext_giwrange() fills iw_range.encoding_size[] from the
> > cipher suites advertised by the wiphy. The WEXT range data describes
> > supported key sizes, but the current code appends one entry for every
> > WEP cipher occurrence.
> >
> > A wiphy may expose repeated WEP cipher entries, which can make
> > cfg80211_wext_giwrange() grow num_encoding_sizes past the available
> > encoding_size[] slots. Track whether WEP40 and WEP104 are present
> > while scanning the cipher list, then emit each corresponding key size
> > once.
> >
> > This keeps the exported WEXT data aligned with the supported key sizes
> > and makes duplicate cipher entries irrelevant.
> >
> > Fixes: 2ab658f9ce21 ("cfg80211: set WE encoding size based on available ciphers")
> > Cc: stable@kernel.org
> > Reported-by: Yuan Tan <yuantan098@gmail.com>
> > Reported-by: Yifan Wu <yifanwucs@gmail.com>
> > Reported-by: Juefei Pu <tomapufckgml@gmail.com>
> > Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
> > Reported-by: Xin Liu <bird@lzu.edu.cn>
> > Assisted-by: Codex:GPT-5.4
> >
>
> Please **always** check if the issue has been fixed already...
I re-checked the current public trees and searched the public mailing
list archives, but I could not find any fix for this issue.
The current public code in both netdev/net and torvalds/linux still has
the same logic in cfg80211_wext_giwrange():
case WLAN_CIPHER_SUITE_WEP40:
range->encoding_size[range->num_encoding_sizes++] =
WLAN_KEY_LEN_WEP40;
break;
case WLAN_CIPHER_SUITE_WEP104:
range->encoding_size[range->num_encoding_sizes++] =
WLAN_KEY_LEN_WEP104;
break;
So as far as I can tell, this issue is still present.
Thanks,
Yuqi
^ 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 7:09 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
In-Reply-To: <6be1d6e67bcb5500c9d1e92449ce7757f6166d22.camel@mediatek.com>
[-- Attachment #1: Type: text/plain, Size: 6203 bytes --]
> 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
>
> Ryder
> >
> > ---
> > base-commit: 4913f44167cf35a9536e9eec7352e15b2de0c573
> > change-id: 20260530-mt76_tx_status_skb_add-overwrite-fix-85818a9bb31f
> >
> > Best regards,
>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply
* [PATCH wifi] wifi: mac80211: fix NULL dereference of eht_oper in ieee80211_start_ap()
From: Weiming Shi @ 2026-05-31 6:39 UTC (permalink / raw)
To: Johannes Berg
Cc: Mohan Kumar G, Dhanavandhana Kannan, linux-wireless, linux-kernel,
Xiang Mei, Weiming Yang, Weiming Shi
From: Weiming Yang <weiming3@asu.edu>
ieee80211_start_ap() enters the EHT block when params->eht_cap is set,
but its last statement unconditionally dereferences params->eht_oper.
The two pointers are parsed from separate beacon-tail elements in
nl80211_calculate_ap_params(), and an EHT Operation element is not
required to be present when an EHT Capability element is. A beacon tail
carrying an HE Capability and HE Operation element (so he_support is
set) plus an EHT Capability element, but no EHT Operation element, thus
dereferences a NULL params->eht_oper:
KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
RIP: 0010:ieee80211_start_ap (net/mac80211/cfg.c:1599)
Call Trace:
nl80211_start_ap (net/wireless/nl80211.c:7177)
genl_family_rcv_msg_doit (net/netlink/genetlink.c:1114)
genl_rcv_msg (net/netlink/genetlink.c:1209)
netlink_rcv_skb (net/netlink/af_netlink.c:2550)
genl_rcv (net/netlink/genetlink.c:1218)
netlink_unicast (net/netlink/af_netlink.c:1344)
netlink_sendmsg (net/netlink/af_netlink.c:1894)
__sys_sendto (net/socket.c:2265)
NL80211_CMD_START_AP uses GENL_UNS_ADMIN_PERM, so this is reachable by
an unprivileged user in a user namespace.
Guard the dereference on params->eht_oper, as the HE block above already
does for params->he_oper.
Fixes: 22c64f37e1d4 ("wifi: mac80211: Update MCS15 support in link_conf")
Reported-by: Xiang Mei <xmei5@asu.edu>
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Weiming Shi <bestswngs@gmail.com>
---
net/mac80211/cfg.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7b77d57c9f96f..5e8d4ccaa6be4 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -1595,9 +1595,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
(IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_80MHZ |
IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_160MHZ |
IEEE80211_EHT_PHY_CAP7_NON_OFDMA_UL_MU_MIMO_320MHZ);
- link_conf->eht_disable_mcs15 =
- u8_get_bits(params->eht_oper->params,
- IEEE80211_EHT_OPER_MCS15_DISABLE);
+ if (params->eht_oper)
+ link_conf->eht_disable_mcs15 =
+ u8_get_bits(params->eht_oper->params,
+ IEEE80211_EHT_OPER_MCS15_DISABLE);
} else {
link_conf->eht_su_beamformer = false;
link_conf->eht_su_beamformee = false;
--
2.43.0
^ permalink raw reply related
* Re: [PATCH 0/3] wifi: mt76: use __relay_write to avoid race issues.
From: Jason Xing @ 2026-05-31 5:58 UTC (permalink / raw)
To: nbd, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg,
angelogioacchino.delregno, akpm, axboe
Cc: linux-wireless, Jason Xing
In-Reply-To: <20260531034010.85002-1-kerneljasonxing@gmail.com>
On Sun, May 31, 2026 at 11:40 AM Jason Xing <kerneljasonxing@gmail.com> wrote:
>
> From: Jason Xing <kernelxing@tencent.com>
>
> __relay_reserve() that is even though efficient has a disadvantage:
> it's not easy to prevent the writer and reader race conditions since
> readers can read incorrect data just after the offset is advanced at
> which point where no data or only partial data has been written into
> relayfs.
>
> ---
> The series is only complied. I came across this caller and spotted
> the issue when developing relayfs.
I think I need to rephrase a bit since it's technically not an
__issue__. I should also remove the "Fixes:" tag in patch 2/3. The
reader in mt76 tools doesn't conflict with the per flush mode in the
kernel because everytime the kernel writes a bulk of data, it will
switch to a new subbuf which is a signal that makes sure the reader
only reads one subbuf at one time.
What I'm trying to do is to avoid relay_reserve causing potential
problems in the long run from a broader perspective. It heavily relies
on how the application handles the logic. To be honest, the current
approach to reading is not efficient due to the arch of relay.
In this case, replacing reserve with write is more secure/robust
without introducing any bad side effects.
Thanks,
Jason
>
>
> Jason Xing (3):
> relayfs: introduce relay_subbuf_avail()
> wifi: mt76: mt7915: use relay_subbuf_avail() to fix stale fwlog reads
> wifi: mt76: mt7996: use relay_subbuf_avail() to fix stale fwlog reads
>
> .../wireless/mediatek/mt76/mt7915/debugfs.c | 27 +++++++++----------
> .../wireless/mediatek/mt76/mt7996/debugfs.c | 25 +++++++++--------
> include/linux/relay.h | 24 +++++++++++++++++
> 3 files changed, 49 insertions(+), 27 deletions(-)
>
> --
> 2.43.7
>
^ permalink raw reply
* [PATCH 3/3] wifi: mt76: mt7996: use relay_subbuf_avail() to fix stale fwlog reads
From: Jason Xing @ 2026-05-31 3:40 UTC (permalink / raw)
To: nbd, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg,
angelogioacchino.delregno, akpm, axboe
Cc: linux-wireless, Jason Xing
In-Reply-To: <20260531034010.85002-1-kerneljasonxing@gmail.com>
From: Jason Xing <kernelxing@tencent.com>
relay_reserve() advances buf->offset before the caller writes data.
Since relay_file_read() uses buf->offset as the readable upper bound
of the active sub-buffer, a concurrent reader can observe the
reserved-but-not-yet-written region, resulting in stale data.
WRITER READER (active sub-buf)
------ ------
relay_reserve(4+L)
buf->offset += 4+L ---+
*(u32*)dest = L | (offset already exposes the slot)
+--> read(&len, 4) => L (VALID!)
<<preempted>> read(buf, L) => STALE data X
memcpy(dest+4, ..., L)
[payload written - too late]
The userspace reader [1] uses poll() + read(&len, 4) + read(buf, len),
which is racy against the relay_reserve() window described above.
Switch to relay_subbuf_avail() + __relay_write() so the offset only
advances after each chunk is copied.
[1] https://github.com/openwrt/mt76/blob/master/tools/fwlog.c
Fixes: 98686cd21624 ("wifi: mt76: mt7996: add driver for MediaTek Wi-Fi 7 (802.11be) devices")
Signed-off-by: Jason Xing <kernelxing@tencent.com>
---
.../wireless/mediatek/mt76/mt7996/debugfs.c | 25 +++++++++----------
1 file changed, 12 insertions(+), 13 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
index 34af800964d1..82f59a7eb508 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/debugfs.c
@@ -914,22 +914,21 @@ mt7996_debugfs_write_fwlog(struct mt7996_dev *dev, const void *hdr, int hdrlen,
{
static DEFINE_SPINLOCK(lock);
unsigned long flags;
- void *dest;
+ u32 rec_len = len;
+
+ if (hdr)
+ rec_len += hdrlen;
spin_lock_irqsave(&lock, flags);
- dest = relay_reserve(dev->relay_fwlog, hdrlen + len + 4);
- if (dest) {
- *(u32 *)dest = hdrlen + len;
- dest += 4;
-
- if (hdrlen) {
- memcpy(dest, hdr, hdrlen);
- dest += hdrlen;
- }
+ if (!relay_subbuf_avail(dev->relay_fwlog, sizeof(rec_len) + rec_len))
+ goto out;
- memcpy(dest, data, len);
- relay_flush(dev->relay_fwlog);
- }
+ __relay_write(dev->relay_fwlog, &rec_len, sizeof(rec_len));
+ if (hdr)
+ __relay_write(dev->relay_fwlog, hdr, hdrlen);
+ __relay_write(dev->relay_fwlog, data, len);
+ relay_flush(dev->relay_fwlog);
+out:
spin_unlock_irqrestore(&lock, flags);
}
--
2.43.7
^ permalink raw reply related
* [PATCH 2/3] wifi: mt76: mt7915: use relay_subbuf_avail() to fix stale fwlog reads
From: Jason Xing @ 2026-05-31 3:40 UTC (permalink / raw)
To: nbd, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg,
angelogioacchino.delregno, akpm, axboe
Cc: linux-wireless, Jason Xing
In-Reply-To: <20260531034010.85002-1-kerneljasonxing@gmail.com>
From: Jason Xing <kernelxing@tencent.com>
relay_reserve() advances buf->offset before the caller writes data.
Since relay_file_read() uses buf->offset as the readable upper bound
of the active sub-buffer, a concurrent reader can observe the
reserved-but-not-yet-written region, resulting in stale data.
WRITER READER (active sub-buf)
------ ------
relay_reserve(4+L)
buf->offset += 4+L ---+
*(u32*)dest = L | (offset already exposes the slot)
+--> read(&len, 4) => L (VALID!)
<<preempted>> read(buf, L) => STALE data X
memcpy(dest+4, ..., L)
[payload written - too late]
The userspace reader [1] uses poll() + read(&len, 4) + read(buf, len),
which is racy against the relay_reserve() window described above.
Switch to relay_subbuf_avail() + __relay_write() so the offset only
advances after each chunk is copied.
[1] https://github.com/openwrt/mt76/blob/master/tools/fwlog.c
Fixes: 988845c9361a ("mt76: mt7915: add support for passing chip/firmware debug data to user space")
Signed-off-by: Jason Xing <kernelxing@tencent.com>
---
.../wireless/mediatek/mt76/mt7915/debugfs.c | 27 +++++++++----------
1 file changed, 13 insertions(+), 14 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
index 26ed3745af43..d564b265dc27 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
@@ -1346,22 +1346,21 @@ mt7915_debugfs_write_fwlog(struct mt7915_dev *dev, const void *hdr, int hdrlen,
{
static DEFINE_SPINLOCK(lock);
unsigned long flags;
- void *dest;
+ u32 rec_len = len;
+
+ if (hdr)
+ rec_len += hdrlen;
spin_lock_irqsave(&lock, flags);
- dest = relay_reserve(dev->relay_fwlog, hdrlen + len + 4);
- if (dest) {
- *(u32 *)dest = hdrlen + len;
- dest += 4;
-
- if (hdrlen) {
- memcpy(dest, hdr, hdrlen);
- dest += hdrlen;
- }
-
- memcpy(dest, data, len);
- relay_flush(dev->relay_fwlog);
- }
+ if (!relay_subbuf_avail(dev->relay_fwlog, sizeof(rec_len) + rec_len))
+ goto out;
+
+ __relay_write(dev->relay_fwlog, &rec_len, sizeof(rec_len));
+ if (hdr)
+ __relay_write(dev->relay_fwlog, hdr, hdrlen);
+ __relay_write(dev->relay_fwlog, data, len);
+ relay_flush(dev->relay_fwlog);
+out:
spin_unlock_irqrestore(&lock, flags);
}
--
2.43.7
^ permalink raw reply related
* [PATCH 1/3] relayfs: introduce relay_subbuf_avail()
From: Jason Xing @ 2026-05-31 3:40 UTC (permalink / raw)
To: nbd, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg,
angelogioacchino.delregno, akpm, axboe
Cc: linux-wireless, Jason Xing
In-Reply-To: <20260531034010.85002-1-kerneljasonxing@gmail.com>
From: Jason Xing <kernelxing@tencent.com>
Add relay_subbuf_avail() which ensures the sub-buffer has room and
returns the buffer pointer without advancing the offset.
Together with __relay_write(), it lets callers emit multi-part records
where the offset only moves after each chunk is copied, closing the
stale-read window.
Signed-off-by: Jason Xing <kernelxing@tencent.com>
---
include/linux/relay.h | 24 ++++++++++++++++++++++++
1 file changed, 24 insertions(+)
diff --git a/include/linux/relay.h b/include/linux/relay.h
index 6772a7075840..270a028586bd 100644
--- a/include/linux/relay.h
+++ b/include/linux/relay.h
@@ -268,6 +268,30 @@ static inline void *relay_reserve(struct rchan *chan, size_t length)
return reserved;
}
+/**
+ * relay_subbuf_avail - ensure @length bytes fit in current sub-buffer
+ * @chan: relay channel
+ * @length: total number of bytes to check
+ *
+ * Returns the per-cpu buffer if @length bytes fit, NULL otherwise.
+ * Switches to the next sub-buffer if necessary but does NOT advance
+ * the write offset. Use __relay_write() to write into the returned
+ * buffer.
+ *
+ * Caller must prevent preemption and serialise against other writers.
+ */
+static inline struct rchan_buf *
+relay_subbuf_avail(struct rchan *chan, size_t length)
+{
+ struct rchan_buf *buf = *this_cpu_ptr(chan->buf);
+
+ if (unlikely(buf->offset + length > buf->chan->subbuf_size)) {
+ if (!relay_switch_subbuf(buf, length))
+ return NULL;
+ }
+ return buf;
+}
+
/**
* subbuf_start_reserve - reserve bytes at the start of a sub-buffer
* @buf: relay channel buffer
--
2.43.7
^ permalink raw reply related
* [PATCH 0/3] wifi: mt76: use __relay_write to avoid race issues.
From: Jason Xing @ 2026-05-31 3:40 UTC (permalink / raw)
To: nbd, lorenzo, ryder.lee, shayne.chen, sean.wang, matthias.bgg,
angelogioacchino.delregno, akpm, axboe
Cc: linux-wireless, Jason Xing
From: Jason Xing <kernelxing@tencent.com>
__relay_reserve() that is even though efficient has a disadvantage:
it's not easy to prevent the writer and reader race conditions since
readers can read incorrect data just after the offset is advanced at
which point where no data or only partial data has been written into
relayfs.
---
The series is only complied. I came across this caller and spotted
the issue when developing relayfs.
Jason Xing (3):
relayfs: introduce relay_subbuf_avail()
wifi: mt76: mt7915: use relay_subbuf_avail() to fix stale fwlog reads
wifi: mt76: mt7996: use relay_subbuf_avail() to fix stale fwlog reads
.../wireless/mediatek/mt76/mt7915/debugfs.c | 27 +++++++++----------
.../wireless/mediatek/mt76/mt7996/debugfs.c | 25 +++++++++--------
include/linux/relay.h | 24 +++++++++++++++++
3 files changed, 49 insertions(+), 27 deletions(-)
--
2.43.7
^ permalink raw reply
* Re: [PATCH] wifi: mt76: mt7996: fix reading zeroed info->control.flags after mt76_tx_status_skb_add()
From: Ryder Lee @ 2026-05-31 2:03 UTC (permalink / raw)
To: Shayne Chen (陳軒丞), lorenzo@kernel.org,
nbd@nbd.name, AngeloGioacchino Del Regno,
Chui-hao Chiu (邱垂浩), Sean Wang,
Bo Jiao (焦波), matthias.bgg@gmail.com
Cc: linux-wireless@vger.kernel.org,
linux-arm-kernel@lists.infradead.org, Roy-CH Luo,
linux-mediatek@lists.infradead.org
In-Reply-To: <20260530-mt76_tx_status_skb_add-overwrite-fix-v1-1-e2c3151c391a@kernel.org>
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.
Ryder
>
> ---
> base-commit: 4913f44167cf35a9536e9eec7352e15b2de0c573
> change-id: 20260530-mt76_tx_status_skb_add-overwrite-fix-85818a9bb31f
>
> Best regards,
^ permalink raw reply
* [PATCH] wifi: mac80211: limit injected antenna index in ieee80211_parse_tx_radiotap
From: Deepanshu Kartikey @ 2026-05-31 1:17 UTC (permalink / raw)
To: johannes
Cc: gregory.greenman, linux-wireless, linux-kernel,
Deepanshu Kartikey, syzbot+8e0622f6d9446420271f
When parsing the radiotap header of an injected frame,
ieee80211_parse_tx_radiotap() uses the IEEE80211_RADIOTAP_ANTENNA value
directly as a shift count:
info->control.antennas |= BIT(*iterator.this_arg);
*iterator.this_arg is an 8-bit value taken straight from the frame
supplied by userspace, so BIT() can be asked to shift by up to 255. That
is undefined behaviour on the unsigned long and is reported by UBSAN:
UBSAN: shift-out-of-bounds in net/mac80211/tx.c:2174:30
shift exponent 235 is too large for 64-bit type 'unsigned long'
Call Trace:
ieee80211_parse_tx_radiotap+0xadb/0x1950 net/mac80211/tx.c:2174
ieee80211_monitor_start_xmit+0xb1f/0x1250 net/mac80211/tx.c:2451
...
packet_sendmsg+0x3eb6/0x50f0 net/packet/af_packet.c:3109
info->control.antennas is a 2-bit bitmap (u8 antennas:2), so only antenna
indices 0 and 1 can ever be represented. Ignore any larger value instead
of shifting out of bounds.
Reported-by: syzbot+8e0622f6d9446420271f@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=8e0622f6d9446420271f
Fixes: ef246a1480cc ("wifi: mac80211: support antenna control in injection")
Signed-off-by: Deepanshu Kartikey <kartikey406@gmail.com>
---
net/mac80211/tx.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index b487d2330f25..ea7f63e1fc17 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2181,7 +2181,9 @@ bool ieee80211_parse_tx_radiotap(struct sk_buff *skb,
case IEEE80211_RADIOTAP_ANTENNA:
/* this can appear multiple times, keep a bitmap */
- info->control.antennas |= BIT(*iterator.this_arg);
+ /* control.antennas is only a 2-bit bitmap */
+ if (*iterator.this_arg < 2)
+ info->control.antennas |= BIT(*iterator.this_arg);
break;
case IEEE80211_RADIOTAP_DATA_RETRIES:
--
2.43.0
^ permalink raw reply related
* [syzbot] [wireless?] UBSAN: shift-out-of-bounds in ieee80211_parse_tx_radiotap
From: syzbot @ 2026-05-30 20:57 UTC (permalink / raw)
To: johannes, linux-kernel, linux-wireless, netdev, syzkaller-bugs
Hello,
syzbot found the following issue on:
HEAD commit: 3e48a11675c5 Merge tag 'f2fs-for-7.0-rc1' of git://git.ker..
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=126256e6580000
kernel config: https://syzkaller.appspot.com/x/.config?x=bdcbd6339981e22b
dashboard link: https://syzkaller.appspot.com/bug?extid=8e0622f6d9446420271f
compiler: Debian clang version 21.1.8 (++20251221033036+2078da43e25a-1~exp1~20251221153213.50), Debian LLD 21.1.8
syz repro: https://syzkaller.appspot.com/x/repro.syz?x=15fd6c02580000
C reproducer: https://syzkaller.appspot.com/x/repro.c?x=1026fe5a580000
Downloadable assets:
disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/d900f083ada3/non_bootable_disk-3e48a116.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/0749cae3d374/vmlinux-3e48a116.xz
kernel image: https://storage.googleapis.com/syzbot-assets/425b8d5bc900/bzImage-3e48a116.xz
IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+8e0622f6d9446420271f@syzkaller.appspotmail.com
------------[ cut here ]------------
UBSAN: shift-out-of-bounds in net/mac80211/tx.c:2174:30
shift exponent 235 is too large for 64-bit type 'unsigned long'
CPU: 0 UID: 0 PID: 5454 Comm: syz.0.17 Not tainted syzkaller #0 PREEMPT(full)
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
Call Trace:
<TASK>
dump_stack_lvl+0xe8/0x150 lib/dump_stack.c:120
ubsan_epilogue+0xa/0x30 lib/ubsan.c:233
__ubsan_handle_shift_out_of_bounds+0x385/0x410 lib/ubsan.c:494
ieee80211_parse_tx_radiotap+0xadb/0x1950 net/mac80211/tx.c:2174
ieee80211_monitor_start_xmit+0xb1f/0x1250 net/mac80211/tx.c:2451
__netdev_start_xmit include/linux/netdevice.h:5275 [inline]
netdev_start_xmit include/linux/netdevice.h:5284 [inline]
xmit_one net/core/dev.c:3864 [inline]
dev_hard_start_xmit+0x2d8/0x870 net/core/dev.c:3880
__dev_queue_xmit+0x168f/0x38a0 net/core/dev.c:4829
packet_snd net/packet/af_packet.c:3077 [inline]
packet_sendmsg+0x3eb6/0x50f0 net/packet/af_packet.c:3109
sock_sendmsg_nosec net/socket.c:727 [inline]
__sock_sendmsg net/socket.c:742 [inline]
__sys_sendto+0x709/0x7a0 net/socket.c:2206
__do_sys_sendto net/socket.c:2213 [inline]
__se_sys_sendto net/socket.c:2209 [inline]
__x64_sys_sendto+0xde/0x100 net/socket.c:2209
do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
do_syscall_64+0x14d/0xf80 arch/x86/entry/syscall_64.c:94
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f251db9bf79
Code: ff c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 e8 ff ff ff f7 d8 64 89 01 48
RSP: 002b:00007fff388b1f78 EFLAGS: 00000246 ORIG_RAX: 000000000000002c
RAX: ffffffffffffffda RBX: 00007f251de15fa0 RCX: 00007f251db9bf79
RDX: 0000000000000038 RSI: 0000200000000640 RDI: 0000000000000007
RBP: 00007f251dc327e0 R08: 0000200000000380 R09: 0000000000000014
R10: 0000000004000000 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f251de15fac R14: 00007f251de15fa0 R15: 00007f251de15fa0
</TASK>
---[ end trace ]---
---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzkaller@googlegroups.com.
syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.
If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title
If you want syzbot to run the reproducer, reply with:
#syz test: git://repo/address.git branch-or-commit-hash
If you attach or paste a git patch, syzbot will apply it before testing.
If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)
If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report
If you want to undo deduplication, reply with:
#syz undup
^ permalink raw reply
* Re: [PATCH ath-next 0/2] wifi: ath12k: fix NULL deref when MLO link activation fails
From: Rameshkumar Sundaram @ 2026-05-30 17:37 UTC (permalink / raw)
To: Wei Zhang, jeff.johnson; +Cc: ath12k, linux-wireless, linux-kernel
In-Reply-To: <20260512044906.1735821-1-wei.zhang@oss.qualcomm.com>
On 5/12/2026 10:19 AM, Wei Zhang wrote:
> ath12k_mac_op_change_sta_links() adds a link to ahsta->links_map
> before verifying that the link's vdev is ready, allowing broken links
> to be processed by subsequent operations and causing NULL dereferences.
>
> Patch 1 fixes three error path inconsistencies in ath12k_mac_vdev_create()
> that leave arvif state or vdev resources inconsistent: a direct return on
> wmi_vdev_create failure bypasses err: which clears arvif->ar; and both
> failure paths in err_peer_del skip the DP peer cleanup and vdev rollback.
>
> Patch 2 uses arvif->is_created (made reliable by patch 1) to guard
> against links with no vdev before allocating a link station, preventing
> broken links from entering links_map.
>
> Wei Zhang (2):
> wifi: ath12k: fix inconsistent arvif state in vdev_create error paths
> wifi: ath12k: fix NULL deref in change_sta_links for unready link
>
> drivers/net/wireless/ath/ath12k/mac.c | 17 ++++++++---------
> 1 file changed, 8 insertions(+), 9 deletions(-)
>
> base-commit: 7b25796f571fc09a7aa6fe7efb23edccd326917d
Reviewed-by: Rameshkumar Sundaram <rameshkumar.sundaram@oss.qualcomm.com>
^ permalink raw reply
* Re: [PATCH v2] wireless-regdb: allow 320MHz channel width for Russia
From: Chen-Yu Tsai @ 2026-05-30 15:52 UTC (permalink / raw)
To: Ilya K; +Cc: linux-wireless, wireless-regdb, Louis Kotze
In-Reply-To: <d18d4ba0-9fc6-4585-8161-610ec42fdab4@0upti.me>
On Wed, May 27, 2026 at 7:48 PM Ilya K <me@0upti.me> wrote:
>
> >
> > Applied to master in wens/wireless-regdb.git, thanks!
> >
> > [1/1] wireless-regdb: allow 320MHz channel width for Russia
> > https://git.kernel.org/wens/wireless-regdb/c/62d72c287e99
> >
> Hi, can we get a signed tag with this included?
It's tagged and released today.
ChenYu
^ permalink raw reply
* [ANN] wireless-regdb: master-2026-05-30
From: Chen-Yu Tsai @ 2026-05-30 15:50 UTC (permalink / raw)
To: wireless-regdb, linux-wireless
A new release of wireless-regdb (master-2026-05-30) is available at:
https://www.kernel.org/pub/software/network/wireless-regdb/wireless-regdb-2026.05.30.tar.xz
The short log of changes since the master-2026-03-18 release is below.
--
Chen-Yu Tsai (1):
wireless-regdb: update regulatory database based on preceding changes
Hafiz Zafran (1):
wireless-regdb: Update regulatory info for Brunei Darussalam (BN) for 2022
K900 (1):
wireless-regdb: allow 320MHz channel width for Russia
Louis Kotze (5):
wireless-regdb: Update 6 GHz rules for Hong Kong (HK)
wireless-regdb: Update 5/6 GHz power rules for Russia (RU)
wireless-regdb: Fix 60 GHz power unit for Ukraine (UA)
wireless-regdb: Update 6 GHz rules for South Africa (ZA)
wireless-regdb: Update 6 GHz rules for South Korea (KR)
Mohamed Aashif (1):
wireless-regdb: Update regulatory rules for Sri Lanka (LK)
Ping-Ke Shih (1):
wireless-regdb: Add regulatory info for CEPT countries FO, GI, IM, SM and VA listed by WiFi Alliance
^ permalink raw reply
* Re: [PATCH v2] wireless-regdb: add regulatory rules for Iraq (IQ)
From: Chen-Yu Tsai @ 2026-05-30 15:33 UTC (permalink / raw)
To: Mohammed Abdullah Ali Al-Obaidi; +Cc: wireless-regdb, linux-wireless
In-Reply-To: <20260521101501.1841-1-mnew_iraq@yahoo.com>
Hi,
Just a couple notes.
On Thu, May 21, 2026 at 1:15 PM Mohammed Abdullah Ali Al-Obaidi
<mnew_iraq@yahoo.com> wrote:
>
> Add a regulatory entry for Iraq (ISO 3166-1 alpha-2: IQ).
>
> Iraq is currently absent from the regulatory database. Devices set
> to country=IQ fall back to the world domain (00), which leaves most
> of the 5 GHz spectrum marked "no IR" and severely restricts even
> 2.4 GHz operation. The Iraqi Communications and Media Commission
> (CMC) has now published an explicit, numerical national regulation
> that fills this gap.
>
> Source document
> ---------------
>
> Title : Regulation on short-range radio communication devices
> (SRD) and devices using ultra-broadband (UWB) technology
> Issuer: Republic of Iraq, Communications and Media Commission
> (CMC), Telecommunications Regulatory Department,
> International Relations Section
> Decree: Council of Commissioners decision No. 122/q-2025
> In force from: 2025-09-22
> Edition: First edition, 2025; 26 pages
> URL : https://cmc.iq/wp-content/uploads/2025/09/Regulation-on-short-range-radio-communication-devices-SRD-and-devices-using-ultra-broadband-UWB-technology.pdf
>
> The values below are taken directly from Article 4-1-13 ("Wireless
> Access Systems / WAS") of that regulation, which is the table
> governing Wi-Fi (Annex A of the regulation defines Wi-Fi as
> "802.11 Local Area Networking in 2.4 and 5 GHz ISM bands").
>
> Bands and limits, as stated in Article 4-1-13:
>
> 2400-2483.5 MHz : 100 mW EIRP, indoor and outdoor, LBT/DAA
> (EN 300 328, ERC/REC 70-03)
> 5150-5250 MHz : 200 mW EIRP, indoor
> (EN 301 893, ITU-R Res. 229 Rev. WRC-19)
> 5250-5350 MHz : 200 mW EIRP, indoor
> (EN 301 893)
> 5470-5725 MHz : 1000 mW EIRP, indoor, DFS + TPC
> (EN 301 893)
> 5725-5875 MHz : 2000 mW EIRP (10 MHz ch) / 4000 mW (20 MHz ch),
> indoor and outdoor
> (EN 302 502)
> 5945-6425 MHz : 200 mW EIRP, indoor
> (EN 303 687, ECC Report 75)
> 57-66 GHz : 10 W EIRP, indoor, LBT/DAA
> (EN 302 567)
>
> Notes on the encoding chosen below
> ----------------------------------
>
> * TPC handling for 5470-5725 MHz: The regulation explicitly requires
> both DFS and TPC. Because Linux/wireless-regdb does not natively
> enforce TPC limits, the rule is encoded with the standard DFS flag
> to remain as compliant as possible within the framework's capabilities.
> * Indoor/Outdoor for 5725-5875 MHz: The regulation explicitly permits
> both indoor and outdoor operation for this band, so no NO-OUTDOOR flag
> is applied.
> * EIRP limit for 5725-5875 MHz: The regulation provides two figures
> (2000 mW for 10 MHz channels, 4000 mW for 20 MHz channels). Because
> wireless-regdb expresses a strict per-band ceiling to ensure compliance
> across all configurations, the limit is conservatively set to 2000 mW
> to prevent narrower channel widths from exceeding their legal limit.
Please leave a short comment above the rule mentioning this. Something
like "adopting limits for 10 MHz channel width to be conservative."
> * 6 GHz channel width: Encoded at 80 MHz (the widest standard-power
> option) pending further clarification from the CMC regarding AFC
> requirements.
>
> Background on the unique 5.8 GHz figure
> ---------------------------------------
>
> The 2000 mW EIRP ceiling for 5725-5875 MHz reflects an explicit Iraqi
> national choice that follows EN 302 502 (BFWA). This choice puts Iraq
> at the high end of the regional spectrum policy for the 5.8 GHz band
> and is included verbatim from the regulation.
>
> Signed-off-by: Mohammed Abdullah Ali Al-Obaidi <mnew_iraq@yahoo.com>
> ---
> v2:
> - Changed 5725-5875 MHz EIRP ceiling from 4000 mW to 2000 mW to
> ensure absolute compliance at narrower channel widths (10 MHz).
> - Trimmed redundant encoding notes regarding standard NO-OUTDOOR,
> DFS, and AUTO-BW conventions.
> - Clarified TPC handling limitations and indoor/outdoor encoding
> choices.
>
> db.txt | 14 ++++++++++++++
> 1 file changed, 14 insertions(+)
>
> diff --git a/db.txt b/db.txt
> --- a/db.txt
> +++ b/db.txt
> @@ -insert-after-IN-block@@
> +# Iraq
> +# Source: Regulation on short-range radio communication devices (SRD)
> +# and devices using ultra-broadband (UWB) technology, First Edition
> +# 2025, issued by the Iraqi Communications and Media Commission (CMC)
> +# under Council of Commissioners decision No. 122/q-2025, in force
> +# from 2025-09-22. Limits below are taken from Article 4-1-13
> +# (Wireless Access Systems) of that regulation.
> +# https://cmc.iq/wp-content/uploads/2025/09/Regulation-on-short-range-radio-communication-devices-SRD-and-devices-using-ultra-broadband-UWB-technology.pdf
> +country IQ: DFS-ETSI
> + (2400 - 2483.5 @ 40), (100 mW), wmmrule=ETSI
> + (5150 - 5250 @ 80), (200 mW), NO-OUTDOOR, AUTO-BW, wmmrule=ETSI
> + (5250 - 5350 @ 80), (200 mW), NO-OUTDOOR, DFS, AUTO-BW, wmmrule=ETSI
> + (5470 - 5725 @ 160), (1000 mW), NO-OUTDOOR, DFS, wmmrule=ETSI
Since Linux doesn't support TPC, it would be better if this rule follows
EN 301 893 and reduces the EIRP. EN 301 893 reduces the limit from 30 dBm
to 27 dBm. Please just use 27 dBm here, and also mention it in the commit
message.
> + (5725 - 5875 @ 80), (2000 mW)
The boundary of WiFi channel 144 actually goes up to 5730. Since this
5 MHz is split between two bands, the current way actually prevents
you from using this channel. Normally we add AUTO-BW to both channels
that are straddled. But since the restrictions for 5725-5875 are looser,
we just let the previous band go up to 5730 MHz instead of 5725 MHz,
and leave a comment explaining it.
Please do so as well. You can use the US region as an example.
> + (5945 - 6425 @ 80), (200 mW), NO-OUTDOOR, wmmrule=ETSI
> + (57000 - 66000 @ 2160), (40)
Please copy the the numbers and units from the regulation verbatim,
unless modifications like the TPC-less reduction was done. So this
should not be "40" dBm, but "10000 mW".
Thanks
ChenYu
^ permalink raw reply
* [PATCH] wifi: mt76: mt7996: fix reading zeroed info->control.flags after mt76_tx_status_skb_add()
From: Lorenzo Bianconi @ 2026-05-30 15:25 UTC (permalink / raw)
To: Felix Fietkau, Ryder Lee, Shayne Chen, Sean Wang,
Matthias Brugger, AngeloGioacchino Del Regno, Bo Jiao, Peter Chiu,
Lorenzo Bianconi
Cc: Roy Luo, linux-wireless, linux-arm-kernel, linux-mediatek
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);
---
base-commit: 4913f44167cf35a9536e9eec7352e15b2de0c573
change-id: 20260530-mt76_tx_status_skb_add-overwrite-fix-85818a9bb31f
Best regards,
--
Lorenzo Bianconi <lorenzo@kernel.org>
^ permalink raw reply related
* Re: [PATCH 3/4] dt-bindings: bus: add brcm,bcm6362-wlan
From: Krzysztof Kozlowski @ 2026-05-30 11:50 UTC (permalink / raw)
To: Alessio Ferri
Cc: Rafał Miłecki, Rob Herring, Krzysztof Kozlowski,
Conor Dooley, Philipp Zabel, Florian Fainelli, linux-kernel,
linux-wireless, devicetree
In-Reply-To: <20260529-add-bcm6362-wlan-v1-3-722242777f58@gmail.com>
On Fri, May 29, 2026 at 02:06:01AM +0200, Alessio Ferri wrote:
> Document the binding for the SHIM bridge that gates the on-chip
> 2.4 GHz WLAN block of the Broadcom BCM6362 SoC. The bridge owns the
> SHIM peephole, a single clock for the macro, and two resets (the
> SHIM macro itself and its ubus side). It is also a bus: it carries
> one brcm,bus-axi child describing the bcma backplane behind the
> SHIM, with a standard interrupt-map routing the d11 core's IRQ to
> the SoC interrupt controller.
>
> Assisted-by: Claude:claude-4.8-opus
> Signed-off-by: Alessio Ferri <alessio.ferri@mythread.it>
> ---
> .../devicetree/bindings/bus/brcm,bcm6362-wlan.yaml | 106 +++++++++++++++++++++
> 1 file changed, 106 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/bus/brcm,bcm6362-wlan.yaml b/Documentation/devicetree/bindings/bus/brcm,bcm6362-wlan.yaml
> new file mode 100644
> index 000000000000..c8d49ccdd2c1
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/bus/brcm,bcm6362-wlan.yaml
> @@ -0,0 +1,106 @@
> +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> +%YAML 1.2
> +---
> +$id: http://devicetree.org/schemas/bus/brcm,bcm6362-wlan.yaml#
> +$schema: http://devicetree.org/meta-schemas/core.yaml#
> +
> +title: Broadcom BCM6362 on-chip WLAN SHIM bridge
> +
> +maintainers:
> + - Alessio Ferri <alessio.ferri@mythread.it>
> +
> +description: |
> + The BCM6362 SoC integrates a 2.4 GHz Broadcom WLAN block whose
> + register backplane uses the Broadcom AMBA (bcma) architecture. The
> + backplane is gated by a small SHIM bridge that holds the WLAN macro
> + in reset and disables its clocks until released by software. CFE
> + does not release this block, so software bring-up is required
> + before bcma can enumerate the backplane.
> +
> + This binding describes the SHIM bridge node. The SHIM driver brings
Do not describe binding. Do not describe driver.
Describe hardware.
> + the macro up and then populates the brcm,bus-axi child node, which
> + describes the bcma backplane behind the SHIM and is bound by the
> + bcma-host-soc driver. The SoC-specific configuration (big-endian
> + accessors, SHIM-attached topology, SHIM Control register peephole
> + pointer) is delivered to bcma via platform_data injected at
> + populate time, so the brcm,bus-axi child stays SoC-agnostic.
How is it relevant?
> +
> +properties:
> + compatible:
> + const: brcm,bcm6362-wlan
> +
> + reg:
> + maxItems: 1
> + description: SHIM peephole registers.
What is SHIM?
> +
> + reg-names:
> + items:
> + - const: shim
> +
> + clocks:
> + maxItems: 1
> +
> + resets:
> + items:
> + - description: SHIM macro reset
> + - description: SHIM ubus reset
> +
> + reset-names:
> + items:
> + - const: shim
> + - const: shim-ubus
> +
> + '#address-cells':
> + const: 1
> +
> + '#size-cells':
> + const: 1
> +
> + ranges: true
> +
> +patternProperties:
> + "^axi@[0-9a-f]+$":
Use consistent quotes.
> + type: object
> + description: The bcma AXI backplane behind the SHIM.
> + $ref: /schemas/types.yaml#
Need proper ref. You could easily check instead of sending Claude slop -
is there any binding with above syntax?
You don't get subnodes for buses for devices not being the actual
buses.
Best regards,
Krzysztof
^ permalink raw reply
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