Linux wireless drivers development
 help / color / mirror / Atom feed
* [PATCH v2 2/3] remoteproc: qcom_wcnss_iris: add support for WCN3610
From: Kerigan Creighton @ 2026-03-05  0:32 UTC (permalink / raw)
  To: linux-wireless
  Cc: loic.poulain, wcn36xx, andersson, mathieu.poirier,
	linux-remoteproc, linux-arm-msm, robh, krzk+dt, conor+dt,
	devicetree, linux-kernel, Kerigan Creighton, Dmitry Baryshkov
In-Reply-To: <20260305003253.1022386-1-kerigancreighton@gmail.com>

Add a qcom,wcn3610 compatible string.
The WCN3610 shares the same register configuration as the
WCN3620, so its configuration is being reused.

Signed-off-by: Kerigan Creighton <kerigancreighton@gmail.com>
Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>
---
Changes in v2:
 - Move remoteproc compatible string addition to the middle of 
   the patch set.
 - Add Reviewed-by Dmitry (thanks!)
---
 drivers/remoteproc/qcom_wcnss_iris.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/remoteproc/qcom_wcnss_iris.c b/drivers/remoteproc/qcom_wcnss_iris.c
index 2b89b4db6c..e58b59355f 100644
--- a/drivers/remoteproc/qcom_wcnss_iris.c
+++ b/drivers/remoteproc/qcom_wcnss_iris.c
@@ -95,6 +95,7 @@ void qcom_iris_disable(struct qcom_iris *iris)
 }
 
 static const struct of_device_id iris_of_match[] = {
+	{ .compatible = "qcom,wcn3610", .data = &wcn3620_data },
 	{ .compatible = "qcom,wcn3620", .data = &wcn3620_data },
 	{ .compatible = "qcom,wcn3660", .data = &wcn3660_data },
 	{ .compatible = "qcom,wcn3660b", .data = &wcn3680_data },
-- 
2.53.0


^ permalink raw reply related

* [PATCH v2 1/3] dt-bindings: remoteproc: qcom,wcnss-pil: add WCN3610 compatible
From: Kerigan Creighton @ 2026-03-05  0:32 UTC (permalink / raw)
  To: linux-wireless
  Cc: loic.poulain, wcn36xx, andersson, mathieu.poirier,
	linux-remoteproc, linux-arm-msm, robh, krzk+dt, conor+dt,
	devicetree, linux-kernel, Kerigan Creighton
In-Reply-To: <20260305003253.1022386-1-kerigancreighton@gmail.com>

Document the qcom,wcn3610 compatible string for use with
the qcom_wcnss_iris remoteproc driver.

Signed-off-by: Kerigan Creighton <kerigancreighton@gmail.com>
---
Changes in v2:
 - Move the Documentation patch to the beginning of the patch set.
---
 Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.yaml
index 117fb4d0c4..018cdf5177 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.yaml
@@ -109,6 +109,7 @@ properties:
     properties:
       compatible:
         enum:
+          - qcom,wcn3610
           - qcom,wcn3620
           - qcom,wcn3660
           - qcom,wcn3660b
-- 
2.53.0


^ permalink raw reply related

* [PATCH v2 0/3] Add support for Qualcomm WCN3610
From: Kerigan Creighton @ 2026-03-05  0:32 UTC (permalink / raw)
  To: linux-wireless
  Cc: loic.poulain, wcn36xx, andersson, mathieu.poirier,
	linux-remoteproc, linux-arm-msm, robh, krzk+dt, conor+dt,
	devicetree, linux-kernel, Kerigan Creighton

The WCN3610 is a 2.4GHz-only WLAN/BT combo chip used in some
cheaper Android and Windows phones such as the Lumia 550, and
IoT devices like the Anki Vector robot. It shares a lot in
common with the WCN3620.

This series adds support for the WCN3610 across the necessary
subsystems:

   * Document the new compatible string (patch 1).
   * Add compatible string in qcom_wcnss_iris (patch 2).
   * Add rf_id and CFGs for the WCN3610 in wcn36xx, disable
     powersave for this specific chip, ensure it is 2.4GHz-only
     (patch 3).

Tested on an Anki Vector 1.0 and 2.0 robot. Support for other
WCN36xx chips has not been affected.

Changes in v2:
 - Move the Documentation patch to the beginning of the patch set.
 - Move remoteproc compatible string addition to the middle of 
   the patch set.
 - Add Reviewed-by Dmitry (thanks!) to remoteproc compatible patch.
 - Move wcn36xx driver changes to the end of the patch set.

Kerigan Creighton (3):
  dt-bindings: remoteproc: qcom,wcnss-pil: add WCN3610 compatible
  remoteproc: qcom_wcnss_iris: add support for WCN3610
  wifi: wcn36xx: add support for WCN3610

 .../bindings/remoteproc/qcom,wcnss-pil.yaml   |  1 +
 drivers/net/wireless/ath/wcn36xx/main.c       |  4 +-
 drivers/net/wireless/ath/wcn36xx/smd.c        | 70 ++++++++++++++++++-
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h    |  1 +
 drivers/remoteproc/qcom_wcnss_iris.c          |  1 +
 5 files changed, 75 insertions(+), 2 deletions(-)

-- 
2.53.0


^ permalink raw reply

* [PATCH 7/7] wifi: mt76: mt792x: build iface combinations dynamically for optional NAN
From: Sean Wang @ 2026-03-04 23:50 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: linux-wireless, linux-mediatek, yu-ching.liu, yuchi.wang,
	jenhao.yang, posh.sun, Sean Wang
In-Reply-To: <20260304235020.40451-1-sean.wang@kernel.org>

From: Sean Wang <sean.wang@mediatek.com>

Expose NAN capability only when supported by firmware. Split chanctx
interface combinations into base and NAN sets and dynamically append NAN
combinations when available.

Co-developed-by: Stella Liu <yu-ching.liu@mediatek.com>
Signed-off-by: Stella Liu <yu-ching.liu@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 drivers/net/wireless/mediatek/mt76/mt792x.h   |   4 +
 .../net/wireless/mediatek/mt76/mt792x_core.c  | 113 ++++++++++++++++--
 2 files changed, 109 insertions(+), 8 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h
index d3988e5b38c0..57c9a0437c5e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
@@ -23,6 +23,7 @@
 #define MT792x_CFEND_RATE_11B		0x03	/* 11B LP, 11M */
 
 #define MT792x_FW_TAG_FEATURE	4
+#define MT792x_FW_CAP_NAN	BIT(5)
 #define MT792x_FW_CAP_CNM	BIT(7)
 
 #define MT792x_CHIP_CAP_CLC_EVT_EN BIT(0)
@@ -263,6 +264,9 @@ struct mt792x_dev {
 	struct ieee80211_chanctx_conf *new_ctx;
 
 	struct ieee80211_vif *nan_vif;
+
+	const struct ieee80211_iface_combination *iface_combinations;
+	int n_iface_combinations;
 };
 
 static inline struct mt792x_bss_conf *
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
index f12cbfb35f9b..e0850998cb4e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
@@ -3,6 +3,7 @@
 
 #include <linux/module.h>
 #include <linux/firmware.h>
+#include <linux/slab.h>
 
 #include "mt792x.h"
 #include "dma.h"
@@ -60,7 +61,33 @@ static const struct ieee80211_iface_limit if_limits_chanctx_scc[] = {
 	}
 };
 
-static const struct ieee80211_iface_combination if_comb_chanctx[] = {
+static const struct ieee80211_iface_limit if_limits_nan_mcc[] = {
+	{
+		.max = 2,
+		.types = BIT(NL80211_IFTYPE_STATION),
+	},
+	{
+		.max = 1,
+		.types = BIT(NL80211_IFTYPE_NAN),
+	},
+};
+
+static const struct ieee80211_iface_limit if_limits_nan_scc[] = {
+	{
+		.max = 2,
+		.types = BIT(NL80211_IFTYPE_STATION),
+	},
+	{
+		.max = 1,
+		.types = BIT(NL80211_IFTYPE_NAN),
+	},
+	{
+		.max = 1,
+		.types = BIT(NL80211_IFTYPE_AP),
+	},
+};
+
+static const struct ieee80211_iface_combination if_comb_chanctx_base[] = {
 	{
 		.limits = if_limits_chanctx_mcc,
 		.n_limits = ARRAY_SIZE(if_limits_chanctx_mcc),
@@ -77,6 +104,60 @@ static const struct ieee80211_iface_combination if_comb_chanctx[] = {
 	}
 };
 
+static const struct ieee80211_iface_combination if_comb_chanctx_nan[] = {
+	{
+		.limits = if_limits_nan_mcc,
+		.n_limits = ARRAY_SIZE(if_limits_nan_mcc),
+		.max_interfaces = 3,
+		.num_different_channels = 2,
+		.beacon_int_infra_match = false,
+	},
+	{
+		.limits = if_limits_nan_scc,
+		.n_limits = ARRAY_SIZE(if_limits_nan_scc),
+		.max_interfaces = 4,
+		.num_different_channels = 1,
+		.beacon_int_infra_match = false,
+	},
+};
+
+static int mt792x_setup_iface_combinations(struct mt792x_dev *dev,
+					   struct wiphy *wiphy)
+{
+	const bool cnm = !!(dev->fw_features & MT792x_FW_CAP_CNM);
+	const bool nan = !!(dev->fw_features & MT792x_FW_CAP_NAN);
+	const int n_base = ARRAY_SIZE(if_comb_chanctx_base);
+	const int n_nan = ARRAY_SIZE(if_comb_chanctx_nan);
+	struct ieee80211_iface_combination *comb;
+
+	if (!cnm) {
+		dev->iface_combinations = if_comb;
+		dev->n_iface_combinations = ARRAY_SIZE(if_comb);
+		return 0;
+	}
+
+	/* CNM enabled, NAN optional */
+	if (!nan) {
+		dev->iface_combinations = if_comb_chanctx_base;
+		dev->n_iface_combinations = ARRAY_SIZE(if_comb_chanctx_base);
+		return 0;
+	}
+
+	/* CNM + NAN: dynamically build base + nan list */
+	comb = devm_kcalloc(&wiphy->dev, n_base + n_nan, sizeof(*comb),
+			    GFP_KERNEL);
+	if (!comb)
+		return -ENOMEM;
+
+	memcpy(comb, if_comb_chanctx_base, sizeof(if_comb_chanctx_base));
+	memcpy(comb + n_base, if_comb_chanctx_nan, sizeof(if_comb_chanctx_nan));
+
+	dev->iface_combinations = comb;
+	dev->n_iface_combinations = n_base + n_nan;
+
+	return 0;
+}
+
 void mt792x_tx(struct ieee80211_hw *hw, struct ieee80211_tx_control *control,
 	       struct sk_buff *skb)
 {
@@ -621,6 +702,7 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw)
 	struct mt792x_phy *phy = mt792x_hw_phy(hw);
 	struct mt792x_dev *dev = phy->dev;
 	struct wiphy *wiphy = hw->wiphy;
+	int err;
 
 	hw->queues = 4;
 	if (dev->has_eht) {
@@ -641,15 +723,17 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw)
 	hw->vif_data_size = sizeof(struct mt792x_vif);
 	hw->chanctx_data_size = sizeof(struct mt792x_chanctx);
 
-	if (dev->fw_features & MT792x_FW_CAP_CNM) {
+	if (dev->fw_features & MT792x_FW_CAP_CNM)
 		wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
-		wiphy->iface_combinations = if_comb_chanctx;
-		wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_chanctx);
-	} else {
+	else
 		wiphy->flags &= ~WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL;
-		wiphy->iface_combinations = if_comb;
-		wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
-	}
+
+	err = mt792x_setup_iface_combinations(dev, wiphy);
+	if (err)
+		return err;
+
+	wiphy->iface_combinations = dev->iface_combinations;
+	wiphy->n_iface_combinations = dev->n_iface_combinations;
 	wiphy->flags &= ~(WIPHY_FLAG_IBSS_RSN | WIPHY_FLAG_4ADDR_AP |
 			  WIPHY_FLAG_4ADDR_STATION);
 	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
@@ -657,6 +741,19 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw)
 				 BIT(NL80211_IFTYPE_P2P_CLIENT) |
 				 BIT(NL80211_IFTYPE_P2P_GO) |
 				 BIT(NL80211_IFTYPE_P2P_DEVICE);
+	if ((dev->fw_features & MT792x_FW_CAP_CNM) &&
+	    (dev->fw_features & MT792x_FW_CAP_NAN)) {
+		wiphy->interface_modes |= BIT(NL80211_IFTYPE_NAN);
+		wiphy->nan_supported_bands = BIT(NL80211_BAND_2GHZ);
+		wiphy->nan_capa.flags = WIPHY_NAN_FLAGS_CONFIGURABLE_SYNC |
+					WIPHY_NAN_FLAGS_USERSPACE_DE;
+		wiphy->nan_capa.op_mode = NAN_OP_MODE_PHY_MODE_MASK;
+		wiphy->nan_capa.n_antennas = 0x22;
+		wiphy->nan_capa.max_channel_switch_time = 12;
+		wiphy->nan_capa.dev_capabilities = NAN_DEV_CAPA_EXT_KEY_ID_SUPPORTED |
+						   NAN_DEV_CAPA_NDPE_SUPPORTED;
+	}
+
 	wiphy->max_remain_on_channel_duration = 5000;
 	wiphy->max_scan_ie_len = MT76_CONNAC_SCAN_IE_LEN;
 	wiphy->max_scan_ssids = 4;
-- 
2.43.0


^ permalink raw reply related

* [PATCH 6/7] wifi: mt76: mt7925: add mac80211 NAN start/stop/change_conf ops
From: Sean Wang @ 2026-03-04 23:50 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: linux-wireless, linux-mediatek, yu-ching.liu, yuchi.wang,
	jenhao.yang, posh.sun, Sean Wang
In-Reply-To: <20260304235020.40451-1-sean.wang@kernel.org>

From: Sean Wang <sean.wang@mediatek.com>

Wire mac80211 NAN start/stop/change_conf callbacks to mt7925 NAN MCU
enable/disable/config. Track the active NAN vif and notify mac80211 on
cluster join events.

Co-developed-by: Stella Liu <yu-ching.liu@mediatek.com>
Signed-off-by: Stella Liu <yu-ching.liu@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 .../net/wireless/mediatek/mt76/mt7925/main.c  | 69 +++++++++++++++++++
 .../net/wireless/mediatek/mt76/mt7925/nan.c   |  7 ++
 drivers/net/wireless/mediatek/mt76/mt792x.h   |  2 +
 3 files changed, 78 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/main.c b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
index afcc0fa4aa35..f215984495c7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/main.c
@@ -11,6 +11,7 @@
 #include "regd.h"
 #include "mcu.h"
 #include "mac.h"
+#include "nan.h"
 
 static void
 mt7925_init_he_caps(struct mt792x_phy *phy, enum nl80211_band band,
@@ -442,6 +443,8 @@ mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
 	INIT_WORK(&mvif->csa_work, mt7925_csa_work);
 	timer_setup(&mvif->csa_timer, mt792x_csa_timer, 0);
 
+	if (vif->type == NL80211_IFTYPE_NAN)
+		dev->nan_vif = vif;
 out:
 	mt792x_mutex_release(dev);
 
@@ -2297,6 +2300,69 @@ static void mt7925_channel_switch_rx_beacon(struct ieee80211_hw *hw,
 	}
 }
 
+static int mt7925_start_nan(struct ieee80211_hw *hw,
+			    struct ieee80211_vif *vif,
+			    struct cfg80211_nan_conf *conf)
+{
+	struct mt792x_dev *dev = mt792x_hw_dev(hw);
+	struct ieee80211_bss_conf *link_conf = &vif->bss_conf;
+	int err = 0;
+
+	mt792x_mutex_acquire(dev);
+
+	link_conf->chanreq.oper.chan = conf->band_cfgs[NL80211_BAND_2GHZ].chan;
+
+	err = mt7925_mcu_add_bss_info(&dev->phy, NULL, link_conf,
+				      NULL, true);
+	if (err < 0)
+		goto out;
+
+	err = mt7925_nan_enable(vif, dev, conf);
+
+out:
+	mt792x_mutex_release(dev);
+
+	return err;
+}
+
+static int mt7925_stop_nan(struct ieee80211_hw *hw,
+			   struct ieee80211_vif *vif)
+{
+	struct ieee80211_bss_conf *link_conf = &vif->bss_conf;
+	struct mt792x_dev *dev = mt792x_hw_dev(hw);
+	int err = 0;
+
+	mt792x_mutex_acquire(dev);
+
+	err = mt7925_nan_disable(vif, dev);
+	if (err < 0)
+		goto out;
+
+	err = mt7925_mcu_add_bss_info(&dev->phy, NULL, link_conf,
+				      NULL, false);
+out:
+	mt792x_mutex_release(dev);
+
+	return err;
+}
+
+static int mt7925_nan_change_conf(struct ieee80211_hw *hw,
+				  struct ieee80211_vif *vif,
+				  struct cfg80211_nan_conf *conf,
+				  u32 changes)
+{
+	struct mt792x_dev *dev = mt792x_hw_dev(hw);
+	int err = 0;
+
+	mt792x_mutex_acquire(dev);
+
+	err = mt7925_nan_change_configure(vif, dev, conf);
+
+	mt792x_mutex_release(dev);
+
+	return err;
+}
+
 const struct ieee80211_ops mt7925_ops = {
 	.tx = mt792x_tx,
 	.start = mt7925_start,
@@ -2366,6 +2432,9 @@ const struct ieee80211_ops mt7925_ops = {
 	.channel_switch = mt7925_channel_switch,
 	.abort_channel_switch = mt7925_abort_channel_switch,
 	.channel_switch_rx_beacon = mt7925_channel_switch_rx_beacon,
+	.start_nan = mt7925_start_nan,
+	.stop_nan = mt7925_stop_nan,
+	.nan_change_conf = mt7925_nan_change_conf,
 };
 EXPORT_SYMBOL_GPL(mt7925_ops);
 
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/nan.c b/drivers/net/wireless/mediatek/mt76/mt7925/nan.c
index 9483ee94c05e..bb67374c9764 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/nan.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/nan.c
@@ -344,11 +344,18 @@ mt7925_nan_mcu_handle_de_event(struct mt792x_dev *dev, struct tlv *tlv)
 	if (de_evt->event_type != NAN_EVENT_ID_JOINED_CLUSTER)
 		return;
 
+	if (!ieee80211_vif_nan_started(dev->nan_vif)) {
+		dev_warn(dev->mt76.dev, "nan: joined-cluster event but NAN not started\n");
+		return;
+	}
+
 	dev_dbg(dev->mt76.dev, "nan: anchor_master_rank=%*phN\n",
 		NAN_ANCHOR_MASTER_RANK_NUM, de_evt->anchor_master_rank);
 
 	dev_dbg(dev->mt76.dev, "nan: own_nmi=%pM master_nmi=%pM\n",
 		de_evt->own_nmi, de_evt->master_nmi);
+
+	ieee80211_nan_cluster_joined(dev->nan_vif, cluster_id, true, GFP_KERNEL);
 }
 
 void mt7925_nan_mcu_event(struct mt792x_dev *dev, struct sk_buff *skb)
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h
index 1f381ab356bc..d3988e5b38c0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
@@ -261,6 +261,8 @@ struct mt792x_dev {
 	u32 backup_l2;
 
 	struct ieee80211_chanctx_conf *new_ctx;
+
+	struct ieee80211_vif *nan_vif;
 };
 
 static inline struct mt792x_bss_conf *
-- 
2.43.0


^ permalink raw reply related

* [PATCH 5/7] wifi: mt76: mt7925: add NAN MCU ABI and basic cmd/event support
From: Sean Wang @ 2026-03-04 23:50 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: linux-wireless, linux-mediatek, yu-ching.liu, yuchi.wang,
	jenhao.yang, posh.sun, Sean Wang
In-Reply-To: <20260304235020.40451-1-sean.wang@kernel.org>

From: Sean Wang <sean.wang@mediatek.com>

Add initial Neighbor Awareness Networking (NAN) MCU ABI definitions for
mt7925 and implement basic NAN control commands.

This introduces NAN command TLVs for enable/disable/configure, plus
event parsing for NAN discovery engine indications. The new code also
adds helper logic for configuring DW interval, cluster ID, RSSI
thresholds and social channel scan parameters.

This change only adds the firmware-facing ABI and command/event
plumbing; it does not yet adapt or expose NAN functionality to upper
layers (cfg80211/mac80211) in mt76. Upper-layer integration will follow
in subsequent patches.

Co-developed-by: Stella Liu <yu-ching.liu@mediatek.com>
Signed-off-by: Stella Liu <yu-ching.liu@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 .../wireless/mediatek/mt76/mt76_connac_mcu.h  |   2 +
 .../wireless/mediatek/mt76/mt7925/Makefile    |   2 +-
 .../net/wireless/mediatek/mt76/mt7925/mcu.c   |   6 +-
 .../net/wireless/mediatek/mt76/mt7925/nan.c   | 386 ++++++++++++++++++
 .../net/wireless/mediatek/mt76/mt7925/nan.h   | 200 +++++++++
 .../net/wireless/mediatek/mt76/mt7925/regd.c  |  30 ++
 .../net/wireless/mediatek/mt76/mt7925/regd.h  |   3 +
 7 files changed, 627 insertions(+), 2 deletions(-)
 create mode 100644 drivers/net/wireless/mediatek/mt76/mt7925/nan.c
 create mode 100644 drivers/net/wireless/mediatek/mt76/mt7925/nan.h

diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
index 11986e164a38..ca29e015d1ab 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
@@ -1075,6 +1075,7 @@ enum {
 	MCU_UNI_EVENT_THERMAL = 0x35,
 	MCU_UNI_EVENT_RSSI_MONITOR = 0x41,
 	MCU_UNI_EVENT_NIC_CAPAB = 0x43,
+	MCU_UNI_EVENT_NAN = 0x56,
 	MCU_UNI_EVENT_WED_RRO = 0x57,
 	MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
 	MCU_UNI_EVENT_ALL_STA_INFO = 0x6e,
@@ -1314,6 +1315,7 @@ enum {
 	MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
 	MCU_UNI_CMD_RSSI_MONITOR = 0x41,
 	MCU_UNI_CMD_TESTMODE_CTRL = 0x46,
+	MCU_UNI_CMD_NAN	= 0x56,
 	MCU_UNI_CMD_RRO = 0x57,
 	MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,
 	MCU_UNI_CMD_PER_STA_INFO = 0x6d,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/Makefile b/drivers/net/wireless/mediatek/mt76/mt7925/Makefile
index 8f1078ce3231..f9dcc0bba393 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/Makefile
@@ -4,7 +4,7 @@ obj-$(CONFIG_MT7925_COMMON) += mt7925-common.o
 obj-$(CONFIG_MT7925E) += mt7925e.o
 obj-$(CONFIG_MT7925U) += mt7925u.o
 
-mt7925-common-y := mac.o mcu.o regd.o main.o init.o debugfs.o
+mt7925-common-y := mac.o mcu.o regd.o main.o init.o debugfs.o nan.o
 mt7925-common-$(CONFIG_NL80211_TESTMODE) += testmode.o
 mt7925e-y := pci.o pci_mac.o pci_mcu.o
 mt7925u-y := usb.o
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index a41e0d2fb3f9..ecf086aee930 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -7,6 +7,7 @@
 #include "regd.h"
 #include "mcu.h"
 #include "mac.h"
+#include "nan.h"
 
 #define MT_STA_BFER			BIT(0)
 #define MT_STA_BFEE			BIT(1)
@@ -37,7 +38,8 @@ int mt7925_mcu_parse_response(struct mt76_dev *mdev, int cmd,
 		   cmd == MCU_UNI_CMD(BSS_INFO_UPDATE) ||
 		   cmd == MCU_UNI_CMD(STA_REC_UPDATE) ||
 		   cmd == MCU_UNI_CMD(OFFLOAD) ||
-		   cmd == MCU_UNI_CMD(SUSPEND)) {
+		   cmd == MCU_UNI_CMD(SUSPEND) ||
+		   cmd == MCU_UNI_CMD(NAN)) {
 		struct mt7925_mcu_uni_event *event;
 
 		skb_pull(skb, sizeof(*rxd));
@@ -600,6 +602,8 @@ mt7925_mcu_uni_rx_unsolicited_event(struct mt792x_dev *dev,
 		dev->fw_assert = true;
 		mt76_connac_mcu_coredump_event(&dev->mt76, skb, &dev->coredump);
 		return;
+	case MCU_UNI_EVENT_NAN:
+		mt7925_nan_mcu_event(dev, skb);
 	default:
 		break;
 	}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/nan.c b/drivers/net/wireless/mediatek/mt76/mt7925/nan.c
new file mode 100644
index 000000000000..9483ee94c05e
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/nan.c
@@ -0,0 +1,386 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/* Copyright (C) 2025-2026 MediaTek Inc. */
+
+#include <asm/byteorder.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/string.h>
+#include <linux/types.h>
+#include <linux/ieee80211.h>
+#include <net/cfg80211.h>
+#include <net/mac80211.h>
+
+#include "mt7925.h"
+#include "mcu.h"
+#include "nan.h"
+#include "regd.h"
+
+static void mt7925_nan_set_5g_channel(struct mt792x_dev *dev,
+				      struct mt7925_nan_enable_req_tlv *req,
+				      struct cfg80211_nan_conf *conf)
+{
+	struct ieee80211_channel *chan;
+	u32 ch5g = 0;
+
+	chan = conf->band_cfgs[NL80211_BAND_5GHZ].chan;
+
+	if (chan)
+		dev_info(dev->mt76.dev, "MP = %u, 5g ch: %u\n",
+			 conf->master_pref, chan->hw_value);
+	else
+		dev_info(dev->mt76.dev, "MP = %u, 5g ch is null\n",
+			 conf->master_pref);
+
+	if (!chan)
+		return;
+
+	if (!mt7925_regd_is_valid_channel(dev, NL80211_BAND_5GHZ, chan))
+		return;
+
+	req->config_5g_channel = 1;
+
+	if (chan->hw_value == NAN_5G_LOW_DISC_CHANNEL)
+		ch5g |= BIT(0);
+	else if (chan->hw_value == NAN_5G_HIGH_DISC_CHANNEL)
+		ch5g |= BIT(1);
+
+	req->channel_5g_val = cpu_to_le32(ch5g);
+}
+
+static void mt7925_nan_set_cluster_id(struct mt7925_nan_enable_req_tlv *req,
+				      const u8 *cluster_id)
+{
+	if (!cluster_id)
+		return;
+
+	req->cluster_high = cpu_to_le16(*(const u16 *)(cluster_id + 4));
+	req->cluster_low = cpu_to_le16((u16)cluster_id[3]);
+}
+
+static void mt7925_nan_set_dw_interval(struct mt7925_nan_enable_req_tlv *req,
+				       struct cfg80211_nan_conf *conf)
+{
+	if (conf->band_cfgs[NL80211_BAND_2GHZ].awake_dw_interval > 0) {
+		req->config_dw.config_2dot4g_dw_band = 1;
+		req->config_dw.dw_2dot4g_interval_val =
+			cpu_to_le32(conf->band_cfgs[NL80211_BAND_2GHZ].awake_dw_interval);
+	}
+
+	if (conf->band_cfgs[NL80211_BAND_5GHZ].awake_dw_interval > 0) {
+		req->config_dw.config_5g_dw_band = 1;
+		req->config_dw.dw_5g_interval_val =
+			cpu_to_le32(conf->band_cfgs[NL80211_BAND_5GHZ].awake_dw_interval);
+	}
+}
+
+static void mt7925_nan_set_disc_beacon(struct mt7925_nan_enable_req_tlv *req,
+				       struct cfg80211_nan_conf *conf)
+{
+	if (conf->discovery_beacon_interval > 0) {
+		req->config_2dot4g_beacons = true;
+		req->beacon_2dot4g_val = conf->discovery_beacon_interval;
+	}
+}
+
+static void mt7925_nan_set_rssi_thresholds(struct mt7925_nan_enable_req_tlv *req,
+					   struct cfg80211_nan_conf *conf)
+{
+	if (conf->band_cfgs[NL80211_BAND_2GHZ].chan) {
+		req->config_2dot4g_rssi_close = 1;
+		req->rssi_close_2dot4g_val =
+			abs(conf->band_cfgs[NL80211_BAND_2GHZ].rssi_close);
+		req->config_2dot4g_rssi_middle = 1;
+		req->rssi_middle_2dot4g_val =
+			abs(conf->band_cfgs[NL80211_BAND_2GHZ].rssi_middle);
+	}
+
+	if (conf->band_cfgs[NL80211_BAND_5GHZ].chan) {
+		req->config_5g_rssi_close = 1;
+		req->rssi_close_5g_val =
+			abs(conf->band_cfgs[NL80211_BAND_5GHZ].rssi_close);
+		req->config_5g_rssi_middle = 1;
+		req->rssi_middle_5g_val =
+			abs(conf->band_cfgs[NL80211_BAND_5GHZ].rssi_middle);
+	}
+}
+
+static void mt7925_nan_set_scan_params(struct mt7925_nan_enable_req_tlv *req,
+				       struct cfg80211_nan_conf *conf)
+{
+	req->scan_params_val.scan_period[0] =
+		conf->scan_period < 255 ? conf->scan_period : 255;
+	req->scan_params_val.dwell_time[0] =
+		conf->scan_dwell_time < 255 ? conf->scan_dwell_time : 255;
+}
+
+int mt7925_nan_enable(struct ieee80211_vif *vif,
+		      struct mt792x_dev *dev,
+		      struct cfg80211_nan_conf *conf)
+{
+	struct mt76_dev *mdev = &dev->mt76;
+	struct {
+		u8 rsv[4];
+		struct mt7925_nan_enable_req_tlv nan_req_tlv;
+	} nan_cmd = {
+		.rsv = { 0 },
+		.nan_req_tlv = {
+			.tag = cpu_to_le16(NAN_UNI_CMD_ENABLE_REQUEST),
+			.len = cpu_to_le16(sizeof(struct mt7925_nan_enable_req_tlv)),
+			.config_random_factor_force = 0,
+			.random_factor_force_val = 0,
+			.config_hop_count_force = 0,
+			.hop_count_force_val = 0,
+		},
+	};
+	struct mt7925_nan_enable_req_tlv *p_nan_req_tlv = &nan_cmd.nan_req_tlv;
+
+	if (!dev || !conf)
+		return -EINVAL;
+
+	p_nan_req_tlv->master_pref = conf->master_pref;
+
+	mt7925_nan_set_5g_channel(dev, p_nan_req_tlv, conf);
+	mt7925_nan_set_cluster_id(p_nan_req_tlv, conf->cluster_id);
+	mt7925_nan_set_dw_interval(p_nan_req_tlv, conf);
+	mt7925_nan_set_disc_beacon(p_nan_req_tlv, conf);
+	mt7925_nan_set_rssi_thresholds(p_nan_req_tlv, conf);
+	mt7925_nan_set_scan_params(p_nan_req_tlv, conf);
+
+	return mt76_mcu_send_msg(mdev, MCU_UNI_CMD(NAN), &nan_cmd, sizeof(nan_cmd), true);
+}
+
+int mt7925_nan_disable(struct ieee80211_vif *vif, struct mt792x_dev *dev)
+{
+	struct mt76_dev *mdev = &dev->mt76;
+	struct {
+		u8 rsv[4];
+		struct tlv nan_dis_tlv;
+	} nan_cmd = {
+		.rsv = { 0 },
+		.nan_dis_tlv = {
+			.tag = cpu_to_le16(NAN_UNI_CMD_DISABLE_REQUEST),
+			.len = cpu_to_le16(sizeof(struct tlv)),
+		},
+	};
+
+	if (!dev)
+		return -EINVAL;
+
+	return mt76_mcu_send_msg(mdev, MCU_UNI_CMD(NAN), &nan_cmd, sizeof(nan_cmd), true);
+}
+
+static void
+mt7925_nan_mp_tlv(struct sk_buff *skb, u8 master_pref)
+{
+	struct mt7925_nan_master_preference_tlv *mp_tlv = NULL;
+	struct tlv *tlv = NULL;
+
+	if (!skb)
+		return;
+
+	tlv = mt76_connac_mcu_add_tlv(skb, NAN_UNI_CMD_SET_MASTER_PREFERENCE,
+				      sizeof(struct mt7925_nan_master_preference_tlv));
+	if (!tlv)
+		return;
+
+	mp_tlv = (struct mt7925_nan_master_preference_tlv *)tlv;
+
+	if (master_pref > NAN_MAX_MASTER_PREFERENCE)
+		return;
+
+	mp_tlv->master_preference = master_pref;
+}
+
+static void
+mt7925_nan_dw_tlv(struct sk_buff *skb, struct cfg80211_nan_conf *conf)
+{
+	struct mt7925_nan_dw_interval_tlv *dw_tlv = NULL;
+	struct tlv *tlv = NULL;
+	u16 interval;
+
+	if (!skb || !conf)
+		return;
+
+	tlv = mt76_connac_mcu_add_tlv(skb, NAN_UNI_CMD_SET_DW_INTERVAL,
+				      sizeof(struct mt7925_nan_dw_interval_tlv));
+
+	if (!tlv)
+		return;
+
+	dw_tlv = (struct mt7925_nan_dw_interval_tlv *)tlv;
+
+	/* Set DW interval for 2.4GHz and 5GHz bands if available */
+	if (conf->band_cfgs[NL80211_BAND_2GHZ].awake_dw_interval > 0) {
+		dw_tlv->dw_interval = conf->band_cfgs[NL80211_BAND_2GHZ].awake_dw_interval;
+	} else if (conf->band_cfgs[NL80211_BAND_5GHZ].awake_dw_interval > 0) {
+		dw_tlv->dw_interval = conf->band_cfgs[NL80211_BAND_5GHZ].awake_dw_interval;
+	} else {
+		/* Fallback to a default value or log a warning */
+		dw_tlv->dw_interval = NAN_DEFAULT_DW_INTERVAL;
+	}
+
+	/* Validate and set NAN Discovery Beacon Interval */
+	interval = conf->discovery_beacon_interval > 0 ?
+		   conf->discovery_beacon_interval :
+		   NAN_DEFAULT_DISC_BCN_INTERVAL;
+
+	dw_tlv->disc_bcn_interval = cpu_to_le16(interval);
+}
+
+static void
+mt7925_nan_cluster_id_tlv(struct sk_buff *skb, const u8 *cluster_id)
+{
+	struct mt7925_nan_cluster_id_tlv *cluster_tlv = NULL;
+	struct tlv *tlv = NULL;
+
+	if (!skb || !cluster_id)
+		return;
+
+	tlv = mt76_connac_mcu_add_tlv(skb, NAN_UNI_CMD_SET_CLUSTER_ID,
+				      sizeof(struct mt7925_nan_cluster_id_tlv));
+
+	if (!tlv)
+		return;
+
+	cluster_tlv = (struct mt7925_nan_cluster_id_tlv *)tlv;
+
+	memcpy(cluster_tlv->cluster_id, cluster_id, ETH_ALEN);
+}
+
+static void
+mt7925_nan_sync_rssi_tlv(struct sk_buff *skb, struct cfg80211_nan_conf *conf)
+{
+	struct mt7925_nan_sync_rssi_tlv *rssi_tlv = NULL;
+	struct tlv *tlv = NULL;
+
+	if (!skb || !conf)
+		return;
+
+	tlv = mt76_connac_mcu_add_tlv(skb, NAN_UNI_CMD_SET_SYNC_RSSI,
+				      sizeof(struct mt7925_nan_sync_rssi_tlv));
+
+	if (!tlv)
+		return;
+
+	rssi_tlv = (struct mt7925_nan_sync_rssi_tlv *)tlv;
+
+	if (conf->band_cfgs[NL80211_BAND_2GHZ].chan) {
+		rssi_tlv->rssi_close_2g =
+			conf->band_cfgs[NL80211_BAND_2GHZ].rssi_close;
+		rssi_tlv->rssi_middle_2g =
+			conf->band_cfgs[NL80211_BAND_2GHZ].rssi_middle;
+	}
+
+	if (conf->band_cfgs[NL80211_BAND_5GHZ].chan) {
+		rssi_tlv->rssi_close_5g =
+			conf->band_cfgs[NL80211_BAND_5GHZ].rssi_close;
+		rssi_tlv->rssi_middle_5g =
+			conf->band_cfgs[NL80211_BAND_5GHZ].rssi_middle;
+	}
+}
+
+int mt7925_nan_change_configure(struct ieee80211_vif *vif,
+				struct mt792x_dev *dev,
+				struct cfg80211_nan_conf *conf)
+{
+	struct mt76_dev *mdev = &dev->mt76;
+	struct mt7925_nan_common_hdr *hdr = NULL;
+	struct sk_buff *skb = NULL;
+
+	if (!dev || !conf)
+		return -EINVAL;
+
+	skb = mt76_mcu_msg_alloc(mdev, NULL, MT7925_NAN_CONF_MAX_SIZE);
+	if (!skb)
+		return -ENOMEM;
+
+	hdr = (struct mt7925_nan_common_hdr *)skb_put(skb, sizeof(*hdr));
+	memset(hdr, 0, sizeof(*hdr));
+
+	mt7925_nan_mp_tlv(skb, conf->master_pref);
+	mt7925_nan_dw_tlv(skb, conf);
+	mt7925_nan_cluster_id_tlv(skb, conf->cluster_id);
+	mt7925_nan_sync_rssi_tlv(skb, conf);
+
+	return mt76_mcu_skb_send_msg(mdev, skb,
+				     MCU_UNI_CMD(NAN), true);
+}
+
+static void
+mt7925_nan_mcu_handle_de_event(struct mt792x_dev *dev, struct tlv *tlv)
+{
+	struct mt7925_nan_de_event *de_evt = NULL;
+	u8 cluster_id[ETH_ALEN] __aligned(2) = {0x50, 0x6f, 0x9a, 0x01, 0x00, 0x00};
+	u16 len;
+
+	if (!dev || !tlv) {
+		if (dev)
+			dev_warn(dev->mt76.dev, "nan: failed to parse TLV\n");
+		return;
+	}
+
+	len = le16_to_cpu(tlv->len);
+	if (len < sizeof(*tlv) + sizeof(*de_evt)) {
+		dev_warn(dev->mt76.dev,
+			 "nan: short de_event tlv len=%u\n", len);
+		return;
+	}
+
+	de_evt = (struct mt7925_nan_de_event *)tlv->data;
+	if (!de_evt) {
+		dev_warn(dev->mt76.dev, "nan: missing DE event payload\n");
+		return;
+	}
+
+	if (de_evt->event_type == NAN_EVENT_ID_DISC_MAC_ADDR)
+		return;
+
+	memcpy(cluster_id, de_evt->cluster_id, ETH_ALEN);
+
+	dev_dbg(dev->mt76.dev, "nan: evt=%u cluster=%pM\n",
+		de_evt->event_type, de_evt->cluster_id);
+
+	if (de_evt->event_type != NAN_EVENT_ID_JOINED_CLUSTER)
+		return;
+
+	dev_dbg(dev->mt76.dev, "nan: anchor_master_rank=%*phN\n",
+		NAN_ANCHOR_MASTER_RANK_NUM, de_evt->anchor_master_rank);
+
+	dev_dbg(dev->mt76.dev, "nan: own_nmi=%pM master_nmi=%pM\n",
+		de_evt->own_nmi, de_evt->master_nmi);
+}
+
+void mt7925_nan_mcu_event(struct mt792x_dev *dev, struct sk_buff *skb)
+{
+	struct tlv *tlv;
+	u32 tlv_len;
+
+	if (!dev || !skb)
+		return;
+
+	if (skb->len < sizeof(struct mt7925_mcu_rxd) + 4)
+		return;
+
+	skb_pull(skb, sizeof(struct mt7925_mcu_rxd) + 4);
+	tlv = (struct tlv *)skb->data;
+	tlv_len = skb->len;
+
+	while (tlv_len >= sizeof(*tlv)) {
+		u16 len = le16_to_cpu(tlv->len);
+
+		if (len < sizeof(*tlv) || len > tlv_len)
+			break;
+
+		switch (le16_to_cpu(tlv->tag)) {
+		case NAN_UNI_EVENT_ID_DE_EVENT_IND:
+			mt7925_nan_mcu_handle_de_event(dev, tlv);
+			break;
+		default:
+			break;
+		}
+
+		tlv_len -= len;
+		tlv = (struct tlv *)((u8 *)tlv + len);
+	}
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/nan.h b/drivers/net/wireless/mediatek/mt76/mt7925/nan.h
new file mode 100644
index 000000000000..8c145e4b0b6f
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/nan.h
@@ -0,0 +1,200 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/* Copyright (C) 2025-2026 MediaTek Inc. */
+
+#ifndef __MT7925_NAN_H
+#define __MT7925_NAN_H
+
+#include <linux/if_ether.h>
+#include <linux/types.h>
+
+#include "../mt76_connac_mcu.h"
+
+#define NAN_MAX_SOCIAL_CHANNELS		3
+#define NAN_ANCHOR_MASTER_RANK_NUM	8
+#define NAN_5G_LOW_DISC_CHANNEL		44
+#define NAN_5G_HIGH_DISC_CHANNEL	149
+#define NAN_MAX_MASTER_PREFERENCE	255
+#define NAN_DEFAULT_DW_INTERVAL		1
+#define NAN_DEFAULT_DISC_BCN_INTERVAL	100
+
+#define MT7925_NAN_CONF_MAX_SIZE					\
+	(sizeof(struct mt7925_nan_common_hdr) +				\
+	 sizeof(struct mt7925_nan_master_preference_tlv) +		\
+	 sizeof(struct mt7925_nan_dw_interval_tlv) +			\
+	 sizeof(struct mt7925_nan_cluster_id_tlv) +			\
+	 sizeof(struct mt7925_nan_sync_rssi_tlv))
+
+enum nan_uni_cmd_tag {
+	NAN_UNI_CMD_SET_MASTER_PREFERENCE	= 0,
+	NAN_UNI_CMD_ENABLE_REQUEST		= 7,
+	NAN_UNI_CMD_DISABLE_REQUEST		= 8,
+	NAN_UNI_CMD_SET_DW_INTERVAL		= 26,
+	NAN_UNI_CMD_SET_SYNC_RSSI		= 39,
+	NAN_UNI_CMD_SET_CLUSTER_ID		= 40,
+};
+
+enum nan_uni_event_tag {
+	NAN_UNI_EVENT_ID_DE_EVENT_IND		= 19,
+};
+
+enum nan_disc_event_type {
+	NAN_EVENT_ID_DISC_MAC_ADDR		= 0,
+	NAN_EVENT_ID_JOINED_CLUSTER		= 2,
+};
+
+struct mt7925_nan_social_ch_scan_params {
+	u8 dwell_time[NAN_MAX_SOCIAL_CHANNELS];
+	__le16 scan_period[NAN_MAX_SOCIAL_CHANNELS];
+} __packed;
+
+struct mt7925_nan_conf_dw {
+	u8 config_2dot4g_dw_band;
+	__le32 dw_2dot4g_interval_val;
+
+	u8 config_5g_dw_band;
+	__le32 dw_5g_interval_val;
+} __packed;
+
+struct mt7925_nan_enable_req_tlv {
+	__le16 tag;
+	__le16 len;
+
+	u8 master_pref;
+	__le16 cluster_low;
+	__le16 cluster_high;
+
+	u8 config_support_5g;
+	u8 support_5g_val;
+
+	u8 config_sid_beacon;
+	u8 sid_beacon_val;
+
+	u8 config_2dot4g_rssi_close;
+	u8 rssi_close_2dot4g_val;
+	u8 config_2dot4g_rssi_middle;
+	u8 rssi_middle_2dot4g_val;
+
+	u8 config_2dot4g_rssi_proximity;
+	u8 rssi_proximity_2dot4g_val;
+	u8 config_hop_count_limit;
+	u8 hop_count_limit_val;
+
+	u8 config_2dot4g_support;
+	u8 support_2dot4g_val;
+
+	u8 config_2dot4g_beacons;
+	u8 beacon_2dot4g_val;
+
+	u8 config_2dot4g_sdf;
+	u8 sdf_2dot4g_val;
+
+	u8 config_5g_beacons;
+	u8 beacon_5g_val;
+
+	u8 config_5g_sdf;
+	u8 sdf_5g_val;
+
+	u8 config_5g_rssi_close;
+	u8 rssi_close_5g_val;
+
+	u8 config_5g_rssi_middle;
+	u8 rssi_middle_5g_val;
+
+	u8 config_5g_rssi_close_proximity;
+	u8 rssi_close_proximity_5g_val;
+
+	u8 config_rssi_window_size;
+	u8 rssi_window_size_val;
+
+	u8 config_oui;
+	__le32 oui_val;
+
+	u8 config_intf_addr;
+	u8 intf_addr_val[ETH_ALEN];
+
+	u8 config_cluster_attribute_val;
+
+	u8 config_scan_params;
+	struct mt7925_nan_social_ch_scan_params scan_params_val;
+
+	u8 config_random_factor_force;
+	u8 random_factor_force_val;
+
+	u8 config_hop_count_force;
+	u8 hop_count_force_val;
+
+	u8 config_24g_channel;
+	__le32 channel_24g_val;
+
+	u8 config_5g_channel;
+	__le32 channel_5g_val;
+
+	struct mt7925_nan_conf_dw config_dw;
+
+	u8 config_disc_mac_addr_randomization;
+	__le32 disc_mac_addr_rand_interval_sec;
+
+	u8 discovery_indication_cfg;
+
+	u8 config_subscribe_sid_beacon;
+	__le32 subscribe_sid_beacon_val;
+
+	u8 enable_log_slot_statistics;
+} __packed __aligned(4);
+
+struct mt7925_nan_common_hdr {
+	u8 reserved[4];
+};
+
+struct mt7925_nan_master_preference_tlv {
+	__le16 tag;
+	__le16 len;
+	u8 master_preference;
+	u8 reserved[3];
+} __packed __aligned(4);
+
+struct mt7925_nan_dw_interval_tlv {
+	__le16 tag;
+	__le16 len;
+	u8 dw_interval;
+	u8 vendor_ioctl;
+	__le16 disc_bcn_interval;
+} __packed __aligned(4);
+
+struct mt7925_nan_cluster_id_tlv {
+	__le16 tag;
+	__le16 len;
+	u8 cluster_id[ETH_ALEN];
+	u8 reserved[2];
+} __packed __aligned(4);
+
+struct mt7925_nan_sync_rssi_tlv {
+	__le16 tag;
+	__le16 len;
+	s8 rssi_close_2g;
+	s8 rssi_middle_2g;
+	s8 rssi_close_5g;
+	s8 rssi_middle_5g;
+} __packed __aligned(4);
+
+struct mt7925_nan_de_event {
+	u8 event_type;
+	u8 cluster_id[ETH_ALEN];
+	u8 anchor_master_rank[NAN_ANCHOR_MASTER_RANK_NUM];
+	u8 own_nmi[ETH_ALEN];
+	u8 master_nmi[ETH_ALEN];
+};
+
+int mt7925_nan_enable(struct ieee80211_vif *vif,
+		      struct mt792x_dev *dev,
+		      struct cfg80211_nan_conf *conf);
+
+int mt7925_nan_disable(struct ieee80211_vif *vif,
+		       struct mt792x_dev *dev);
+
+int mt7925_nan_change_configure(struct ieee80211_vif *vif,
+				struct mt792x_dev *dev,
+				struct cfg80211_nan_conf *conf);
+
+void mt7925_nan_mcu_event(struct mt792x_dev *dev, struct sk_buff *skb);
+#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regd.c b/drivers/net/wireless/mediatek/mt76/mt7925/regd.c
index 16f56ee879d4..0235437d11d5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/regd.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/regd.c
@@ -217,6 +217,36 @@ mt7925_regd_is_valid_alpha2(const char *alpha2)
 	return false;
 }
 
+bool
+mt7925_regd_is_valid_channel(struct mt792x_dev *dev,
+			     enum nl80211_band band,
+			     struct ieee80211_channel *chan)
+{
+	struct ieee80211_hw *hw = mt76_hw(dev);
+	struct wiphy *wiphy = hw->wiphy;
+	struct ieee80211_supported_band *sband;
+	struct ieee80211_channel *ch;
+	int i;
+
+	if (!chan)
+		return false;
+
+	sband = wiphy->bands[band];
+	if (!sband)
+		return false;
+
+	for (i = 0; i < sband->n_channels; i++) {
+		ch = &sband->channels[i];
+
+		if (ch->hw_value == chan->hw_value &&
+		    ((ch->flags & IEEE80211_CHAN_DISABLED) == 0))
+			return true;
+	}
+
+	return false;
+}
+EXPORT_SYMBOL_GPL(mt7925_regd_is_valid_channel);
+
 int mt7925_regd_change(struct mt792x_phy *phy, char *alpha2)
 {
 	struct wiphy *wiphy = phy->mt76->hw->wiphy;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/regd.h b/drivers/net/wireless/mediatek/mt76/mt7925/regd.h
index 0767f078862e..0b0754cf8ae7 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/regd.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/regd.h
@@ -13,6 +13,9 @@ void mt7925_regd_be_ctrl(struct mt792x_dev *dev, u8 *alpha2);
 void mt7925_regd_notifier(struct wiphy *wiphy, struct regulatory_request *req);
 bool mt7925_regd_clc_supported(struct mt792x_dev *dev);
 int mt7925_regd_change(struct mt792x_phy *phy, char *alpha2);
+bool mt7925_regd_is_valid_channel(struct mt792x_dev *dev,
+				  enum nl80211_band band,
+				  struct ieee80211_channel *chan);
 int mt7925_regd_init(struct mt792x_phy *phy);
 
 #endif
-- 
2.43.0


^ permalink raw reply related

* [PATCH 4/7] wifi: mt76: connac: add NAN connection type
From: Sean Wang @ 2026-03-04 23:50 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: linux-wireless, linux-mediatek, yu-ching.liu, yuchi.wang,
	jenhao.yang, posh.sun, Sean Wang
In-Reply-To: <20260304235020.40451-1-sean.wang@kernel.org>

From: Sean Wang <sean.wang@mediatek.com>

Introduce a dedicated NAN connection type for connac-based firmware.

This prepares driver support for NAN interfaces by allowing MCU
device/BSS configuration to represent NAN roles using a distinct
connection type.

No functional behaviour change yet as NAN is not exposed to userspace.

Co-developed-by: Stella Liu <yu-ching.liu@mediatek.com>
Signed-off-by: Stella Liu <yu-ching.liu@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c | 11 +++++++++++
 drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h |  2 ++
 drivers/net/wireless/mediatek/mt76/mt7925/mcu.c      |  4 ++++
 3 files changed, 17 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index 89bd52ea8bf7..09efcab7d783 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -422,6 +422,9 @@ void mt76_connac_mcu_sta_basic_tlv(struct mt76_dev *dev, struct sk_buff *skb,
 		basic->conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC);
 		basic->aid = cpu_to_le16(link_sta->sta->aid);
 		break;
+	case NL80211_IFTYPE_NAN:
+		basic->conn_type = cpu_to_le32(CONNECTION_NAN);
+		break;
 	default:
 		WARN_ON(1);
 		break;
@@ -1212,6 +1215,10 @@ int mt76_connac_mcu_uni_add_dev(struct mt76_phy *phy,
 	case NL80211_IFTYPE_ADHOC:
 		basic_req.basic.conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC);
 		break;
+	case NL80211_IFTYPE_NAN:
+		basic_req.basic.conn_type = cpu_to_le32(CONNECTION_NAN);
+		basic_req.basic.conn_state = !enable;
+		break;
 	default:
 		WARN_ON(1);
 		break;
@@ -1613,6 +1620,10 @@ int mt76_connac_mcu_uni_add_bss(struct mt76_phy *phy,
 	case NL80211_IFTYPE_ADHOC:
 		basic_req.basic.conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC);
 		break;
+	case NL80211_IFTYPE_NAN:
+		basic_req.basic.conn_type = cpu_to_le32(CONNECTION_NAN);
+		basic_req.basic.active = enable;
+		break;
 	default:
 		WARN_ON(1);
 		break;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
index fd9cf9c0c32f..11986e164a38 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
@@ -876,6 +876,7 @@ enum {
 #define NETWORK_P2P			BIT(17)
 #define NETWORK_IBSS			BIT(18)
 #define NETWORK_WDS			BIT(21)
+#define NETWORK_NAN			BIT(22)
 
 #define SCAN_FUNC_RANDOM_MAC		BIT(0)
 #define SCAN_FUNC_RNR_SCAN		BIT(3)
@@ -888,6 +889,7 @@ enum {
 #define CONNECTION_IBSS_ADHOC		(STA_TYPE_ADHOC | NETWORK_IBSS)
 #define CONNECTION_WDS			(STA_TYPE_WDS | NETWORK_WDS)
 #define CONNECTION_INFRA_BC		(STA_TYPE_BC | NETWORK_INFRA)
+#define CONNECTION_NAN			(NETWORK_NAN)
 
 #define CONN_STATE_DISCONNECT		0
 #define CONN_STATE_CONNECT		1
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index 261ed6528808..a41e0d2fb3f9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -2563,6 +2563,10 @@ mt7925_mcu_bss_basic_tlv(struct sk_buff *skb,
 		basic_req->conn_type = cpu_to_le32(CONNECTION_IBSS_ADHOC);
 		basic_req->active = true;
 		break;
+	case NL80211_IFTYPE_NAN:
+		basic_req->conn_type = cpu_to_le32(CONNECTION_NAN);
+		basic_req->active = enable;
+		break;
 	default:
 		WARN_ON(1);
 		break;
-- 
2.43.0


^ permalink raw reply related

* [PATCH 3/7] wifi: mt76: mt7925: guard HE 6 GHz capa lookup by HE iftype caps
From: Sean Wang @ 2026-03-04 23:50 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: linux-wireless, linux-mediatek, yu-ching.liu, yuchi.wang,
	jenhao.yang, posh.sun, Sean Wang
In-Reply-To: <20260304235020.40451-1-sean.wang@kernel.org>

From: Sean Wang <sean.wang@mediatek.com>

ieee80211_get_he_6ghz_capa() WARNs if the iftype has no sband iftype_data
or lacks HE. Probe HE support first with ieee80211_get_he_iftype_cap()
and only then query the 6 GHz capa. And initialize he_6ghz_capa/eht_cap
to avoid uninitialized use.

Co-developed-by: Stella Liu <yu-ching.liu@mediatek.com>
Signed-off-by: Stella Liu <yu-ching.liu@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 15 +++++++++++----
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index e050c2795cb4..261ed6528808 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -2436,8 +2436,8 @@ mt7925_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_vif *vif,
 			enum nl80211_band band,
 			struct ieee80211_link_sta *link_sta)
 {
-	struct ieee80211_he_6ghz_capa *he_6ghz_capa;
-	const struct ieee80211_sta_eht_cap *eht_cap;
+	struct ieee80211_he_6ghz_capa *he_6ghz_capa = NULL;
+	const struct ieee80211_sta_eht_cap *eht_cap = NULL;
 	__le16 capa = 0;
 	u8 mode = 0;
 
@@ -2445,11 +2445,18 @@ mt7925_get_phy_mode_ext(struct mt76_phy *phy, struct ieee80211_vif *vif,
 		he_6ghz_capa = &link_sta->he_6ghz_capa;
 		eht_cap = &link_sta->eht_cap;
 	} else {
+		const struct ieee80211_sta_he_cap *he_cap;
 		struct ieee80211_supported_band *sband;
 
 		sband = phy->hw->wiphy->bands[band];
-		capa = ieee80211_get_he_6ghz_capa(sband, vif->type);
-		he_6ghz_capa = (struct ieee80211_he_6ghz_capa *)&capa;
+
+		he_cap = (band == NL80211_BAND_6GHZ) ?
+			 ieee80211_get_he_iftype_cap(sband, vif->type) : NULL;
+
+		if (he_cap) {
+			capa = ieee80211_get_he_6ghz_capa(sband, vif->type);
+			he_6ghz_capa = (struct ieee80211_he_6ghz_capa *)&capa;
+		}
 
 		eht_cap = ieee80211_get_eht_iftype_cap(sband, vif->type);
 	}
-- 
2.43.0


^ permalink raw reply related

* [PATCH 2/7] wifi: mt76: mt7925: guard against NULL chandef in BSS RLM TLV
From: Sean Wang @ 2026-03-04 23:50 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: linux-wireless, linux-mediatek, yu-ching.liu, yuchi.wang,
	jenhao.yang, posh.sun, Sean Wang
In-Reply-To: <20260304235020.40451-1-sean.wang@kernel.org>

From: Sean Wang <sean.wang@mediatek.com>

mt7925_mcu_bss_rlm_tlv() dereferences chandef->chan without verifying
that chandef and chandef->chan are present.

While current callers normally provide a valid chandef, future call
paths or partially configured interfaces may result in missing channel
information and lead to a NULL pointer dereference.

Add a defensive check and bail out early when channel information is
not available. This does not change behaviour for normal operation.

Co-developed-by: Stella Liu <yu-ching.liu@mediatek.com>
Signed-off-by: Stella Liu <yu-ching.liu@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 drivers/net/wireless/mediatek/mt76/mt7925/mcu.c | 11 +++++++++--
 1 file changed, 9 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
index 1379bf6a26b5..e050c2795cb4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mcu.c
@@ -2291,11 +2291,18 @@ void mt7925_mcu_bss_rlm_tlv(struct sk_buff *skb, struct mt76_phy *phy,
 {
 	struct cfg80211_chan_def *chandef = ctx ? &ctx->def :
 						  &link_conf->chanreq.oper;
-	int freq1 = chandef->center_freq1, freq2 = chandef->center_freq2;
-	enum nl80211_band band = chandef->chan->band;
 	struct bss_rlm_tlv *req;
+	enum nl80211_band band;
+	int freq1, freq2;
 	struct tlv *tlv;
 
+	if (WARN_ON_ONCE(!chandef || !chandef->chan))
+		return;
+
+	freq1 = chandef->center_freq1;
+	freq2 = chandef->center_freq2;
+	band = chandef->chan->band;
+
 	tlv = mt76_connac_mcu_add_tlv(skb, UNI_BSS_INFO_RLM, sizeof(*req));
 	req = (struct bss_rlm_tlv *)tlv;
 	req->control_channel = chandef->chan->hw_value;
-- 
2.43.0


^ permalink raw reply related

* [PATCH 1/7] wifi: mt76: mt792x: advertise multicast management frame registration support
From: Sean Wang @ 2026-03-04 23:50 UTC (permalink / raw)
  To: nbd, lorenzo.bianconi
  Cc: linux-wireless, linux-mediatek, yu-ching.liu, yuchi.wang,
	jenhao.yang, posh.sun, Sean Wang

From: Sean Wang <sean.wang@mediatek.com>

Advertise NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS so userspace can
register to receive multicast management/action frames.

This capability is required for NAN discovery and related operations.

Co-developed-by: Stella Liu <yu-ching.liu@mediatek.com>
Signed-off-by: Stella Liu <yu-ching.liu@mediatek.com>
Signed-off-by: Sean Wang <sean.wang@mediatek.com>
---
 drivers/net/wireless/mediatek/mt76/mt792x_core.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt792x_core.c b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
index 152cfcca2f90..f12cbfb35f9b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x_core.c
+++ b/drivers/net/wireless/mediatek/mt76/mt792x_core.c
@@ -678,6 +678,7 @@ int mt792x_init_wiphy(struct ieee80211_hw *hw)
 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_BEACON_RATE_HE);
 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_ACK_SIGNAL_SUPPORT);
 	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_CAN_REPLACE_PTK0);
+	wiphy_ext_feature_set(wiphy, NL80211_EXT_FEATURE_MULTICAST_REGISTRATIONS);
 
 	ieee80211_hw_set(hw, SINGLE_SCAN_ON_ALL_BANDS);
 	ieee80211_hw_set(hw, HAS_RATE_CONTROL);
-- 
2.43.0


^ permalink raw reply related

* Re: [PATCH 2/3] remoteproc: qcom_wcnss_iris: add support for WCN3610
From: Dmitry Baryshkov @ 2026-03-04 23:45 UTC (permalink / raw)
  To: Kerigan Creighton
  Cc: linux-wireless, loic.poulain, wcn36xx, andersson, mathieu.poirier,
	linux-remoteproc, linux-arm-msm, robh, krzk+dt, conor+dt,
	devicetree, linux-kernel
In-Reply-To: <20260304192409.927562-2-kerigancreighton@gmail.com>

On Wed, Mar 04, 2026 at 01:24:08PM -0600, Kerigan Creighton wrote:
> Add a qcom,wcn3610 compatible string.
> The WCN3610 shares the same register configuration as the
> WCN3620, so its configuration is being reused.
> 
> Signed-off-by: Kerigan Creighton <kerigancreighton@gmail.com>
> ---
>  drivers/remoteproc/qcom_wcnss_iris.c | 1 +
>  1 file changed, 1 insertion(+)
> 

Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@oss.qualcomm.com>


-- 
With best wishes
Dmitry

^ permalink raw reply

* Re: [PATCH 3/3] dt-bindings: remoteproc: qcom,wcnss-pil: add WCN3610 compatible
From: Jeff Johnson @ 2026-03-04 23:11 UTC (permalink / raw)
  To: Kerigan Creighton, linux-wireless
  Cc: loic.poulain, wcn36xx, andersson, mathieu.poirier,
	linux-remoteproc, linux-arm-msm, robh, krzk+dt, conor+dt,
	devicetree, linux-kernel
In-Reply-To: <20260304192409.927562-3-kerigancreighton@gmail.com>

On 3/4/2026 11:24 AM, Kerigan Creighton wrote:
> Document the qcom,wcn3610 compatible string for use with
> the qcom_wcnss_iris remoteproc driver.
> 
> Signed-off-by: Kerigan Creighton <kerigancreighton@gmail.com>

https://www.kernel.org/doc/html/latest/devicetree/bindings/submitting-patches.html

"The Documentation/ portion of the patch should come in the series before the
code implementing the binding."

Also ideally for any multi-patch series there should be a cover letter.


^ permalink raw reply

* [PATCH] wifi: mac80211: Fix static_branch_dec() underflow for aql_disable.
From: Kuniyuki Iwashima @ 2026-03-04 20:43 UTC (permalink / raw)
  To: Johannes Berg
  Cc: Lorenzo Bianconi, Kuniyuki Iwashima, Kuniyuki Iwashima,
	linux-wireless, syzbot+feb9ce36a95341bb47a4

syzbot reported static_branch_dec() underflow in aql_enable_write().

The problem is that aql_enable_write() does not serialise concurrent
write()s to the debugfs.

aql_enable_write() checks static_key_false(&aql_disable.key) and
later calls static_branch_inc() or static_branch_dec(), but the
state may change between the two calls.

Let's add a static mutex and move static_key_false() there.

[0]:
val == 0
WARNING: kernel/jump_label.c:311 at __static_key_slow_dec_cpuslocked.part.0+0x107/0x120 kernel/jump_label.c:311, CPU#0: syz.1.3155/20288
Modules linked in:
CPU: 0 UID: 0 PID: 20288 Comm: syz.1.3155 Tainted: G     U       L      syzkaller #0 PREEMPT(full)
Tainted: [U]=USER, [L]=SOFTLOCKUP
Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/24/2026
RIP: 0010:__static_key_slow_dec_cpuslocked.part.0+0x107/0x120 kernel/jump_label.c:311
Code: f2 c9 ff 5b 5d c3 cc cc cc cc e8 54 f2 c9 ff 48 89 df e8 ac f9 ff ff eb ad e8 45 f2 c9 ff 90 0f 0b 90 eb a2 e8 3a f2 c9 ff 90 <0f> 0b 90 eb 97 48 89 df e8 5c 4b 33 00 e9 36 ff ff ff 0f 1f 80 00
RSP: 0018:ffffc9000b9f7c10 EFLAGS: 00010293
RAX: 0000000000000000 RBX: ffffffff9b3e5d40 RCX: ffffffff823c57b4
RDX: ffff8880285a0000 RSI: ffffffff823c5846 RDI: ffff8880285a0000
RBP: 0000000000000000 R08: 0000000000000005 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: 000000000000000a
R13: 1ffff9200173ef88 R14: 0000000000000001 R15: ffffc9000b9f7e98
FS:  00007f530dd726c0(0000) GS:ffff8881245e3000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000200000001140 CR3: 000000007cc4a000 CR4: 00000000003526f0
Call Trace:
 <TASK>
 __static_key_slow_dec_cpuslocked kernel/jump_label.c:297 [inline]
 __static_key_slow_dec kernel/jump_label.c:321 [inline]
 static_key_slow_dec+0x7c/0xc0 kernel/jump_label.c:336
 aql_enable_write+0x2b2/0x310 net/mac80211/debugfs.c:343
 short_proxy_write+0x133/0x1a0 fs/debugfs/file.c:383
 vfs_write+0x2aa/0x1070 fs/read_write.c:684
 ksys_pwrite64 fs/read_write.c:793 [inline]
 __do_sys_pwrite64 fs/read_write.c:801 [inline]
 __se_sys_pwrite64 fs/read_write.c:798 [inline]
 __x64_sys_pwrite64+0x1eb/0x250 fs/read_write.c:798
 do_syscall_x64 arch/x86/entry/syscall_64.c:63 [inline]
 do_syscall_64+0xc9/0xf80 arch/x86/entry/syscall_64.c:94
 entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f530cf9aeb9
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:00007f530dd72028 EFLAGS: 00000246 ORIG_RAX: 0000000000000012
RAX: ffffffffffffffda RBX: 00007f530d215fa0 RCX: 00007f530cf9aeb9
RDX: 0000000000000003 RSI: 0000000000000000 RDI: 0000000000000010
RBP: 00007f530d008c1f R08: 0000000000000000 R09: 0000000000000000
R10: 4200000000000005 R11: 0000000000000246 R12: 0000000000000000
R13: 00007f530d216038 R14: 00007f530d215fa0 R15: 00007ffde89fb978
 </TASK>

Fixes: e908435e402a ("mac80211: introduce aql_enable node in debugfs")
Reported-by: syzbot+feb9ce36a95341bb47a4@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/all/69a8979e.a70a0220.b118c.0025.GAE@google.com/
Signed-off-by: Kuniyuki Iwashima <kuniyu@google.com>
---
 net/mac80211/debugfs.c | 23 ++++++++++++++---------
 1 file changed, 14 insertions(+), 9 deletions(-)

diff --git a/net/mac80211/debugfs.c b/net/mac80211/debugfs.c
index d02f07368c51..bf379e7f81dd 100644
--- a/net/mac80211/debugfs.c
+++ b/net/mac80211/debugfs.c
@@ -320,7 +320,8 @@ static ssize_t aql_enable_read(struct file *file, char __user *user_buf,
 static ssize_t aql_enable_write(struct file *file, const char __user *user_buf,
 				size_t count, loff_t *ppos)
 {
-	bool aql_disabled = static_key_false(&aql_disable.key);
+	static DEFINE_MUTEX(aql_disable_mutex);
+	bool aql_disabled;
 	char buf[3];
 	size_t len;
 
@@ -335,15 +336,19 @@ static ssize_t aql_enable_write(struct file *file, const char __user *user_buf,
 	if (len > 0 && buf[len - 1] == '\n')
 		buf[len - 1] = 0;
 
-	if (buf[0] == '0' && buf[1] == '\0') {
-		if (!aql_disabled)
-			static_branch_inc(&aql_disable);
-	} else if (buf[0] == '1' && buf[1] == '\0') {
-		if (aql_disabled)
-			static_branch_dec(&aql_disable);
-	} else {
+	if ((buf[0] != '0' && buf[0] != '1') || buf[1] != '\0')
 		return -EINVAL;
-	}
+
+	mutex_lock(&aql_disable_mutex);
+
+	aql_disabled = static_key_false(&aql_disable.key);
+
+	if (buf[0] == '0' && !aql_disabled)
+		static_branch_inc(&aql_disable);
+	else if (buf[0] == '1' && aql_disabled)
+		static_branch_dec(&aql_disable);
+
+	mutex_unlock(&aql_disable_mutex);
 
 	return count;
 }
-- 
2.53.0.473.g4a7958ca14-goog


^ permalink raw reply related

* Re: Use-after-free in iwl-mld after hardware fails to restart.
From: Ben Greear @ 2026-03-04 19:57 UTC (permalink / raw)
  To: Korenblit, Miriam Rachel, linux-wireless
In-Reply-To: <57f29f81-9a05-ffef-342f-818a25842c6e@candelatech.com>

On 3/4/26 11:26, Ben Greear wrote:
> On 3/3/26 06:27, Ben Greear wrote:
>> On 3/2/26 23:19, Korenblit, Miriam Rachel wrote:
>>>
>>>
>>>> -----Original Message-----
>>>> From: Ben Greear <greearb@candelatech.com>
>>>> Sent: Monday, March 2, 2026 9:00 PM
>>>> To: linux-wireless <linux-wireless@vger.kernel.org>; Korenblit, Miriam Rachel
>>>> <miriam.rachel.korenblit@intel.com>
>>>> Subject: Use-after-free in iwl-mld after hardware fails to restart.
>>>>
>>>> Hello,
>>>>
>>>> Here's another failure case from my torture test system.
>>>>
>>>> This is from a patched 6.18.14+ kernel, but from a look at upstream Linux
>>>> kernel, the problems are there as well.
>>>>
>>>> I believe the problem is something like this:
>>>>
>>>> firmware crashes several times and cannot recover.  Maybe
>>>> Intel folks can tell why it is crashing?  I'd love to know if that
>>>> is something that can be fixed in the driver.
>>>>
>>>>   From mac80211/util.c:
>>>>
>>>> int ieee80211_reconfig(struct ieee80211_local *local)
>>>> is called, and gets to the failure case in this code (I see that second WARN in the
>>>> crash logs)
>>>> .....
>>>>     /*
>>>>      * Upon resume hardware can sometimes be goofy due to
>>>>      * various platform / driver / bus issues, so restarting
>>>>      * the device may at times not work immediately. Propagate
>>>>      * the error.
>>>>      */
>>>>     res = drv_start(local);
>>>>     if (res) {
>>>>         if (suspended)
>>>>             WARN(1, "Hardware became unavailable upon resume.
>>>> This could be a software issue prior to suspend or a hardware issue.\n");
>>>>         else
>>>>             WARN(1, "Hardware became unavailable during
>>>> restart.\n");
>>>>         ieee80211_wake_queues_by_reason(hw,
>>>> IEEE80211_MAX_QUEUE_MAP,
>>>>
>>>>     IEEE80211_QUEUE_STOP_REASON_SUSPEND,
>>>>                         false);
>>>>         ieee80211_handle_reconfig_failure(local);
>>>>         return res;
>>>>
>>>>
>>>> This method has comments about cleaning things up, but I don't see where it
>>>> actually
>>>> cleans up the driver.  And it sets SDATA_IN_DRIVER to false, so a lot of the calls
>>>> in driver-ops.h that would otherwise tell the driver to clean up skip calls to
>>>> the driver.
>>>>
>>>> static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)
>>>> {
>>>>     struct ieee80211_sub_if_data *sdata;
>>>>     struct ieee80211_chanctx *ctx;
>>>>
>>>>     lockdep_assert_wiphy(local->hw.wiphy);
>>>>
>>>>     /*
>>>>      * We get here if during resume the device can't be restarted properly.
>>>>      * We might also get here if this happens during HW reset, which is a
>>>>      * slightly different situation and we need to drop all connections in
>>>>      * the latter case.
>>>>      *
>>>>      * Ask cfg80211 to turn off all interfaces, this will result in more
>>>>      * warnings but at least we'll then get into a clean stopped state.
>>>>      */
>>>>
>>>>     local->resuming = false;
>>>>     local->suspended = false;
>>>>     local->in_reconfig = false;
>>>>     local->reconfig_failure = true;
>>>>
>>>>     ieee80211_flush_completed_scan(local, true);
>>>>
>>>>     /* scheduled scan clearly can't be running any more, but tell
>>>>      * cfg80211 and clear local state
>>>>      */
>>>>     ieee80211_sched_scan_end(local);
>>>>
>>>>     list_for_each_entry(sdata, &local->interfaces, list)
>>>>         sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER;
>>>>
>>>>     /* Mark channel contexts as not being in the driver any more to avoid
>>>>      * removing them from the driver during the shutdown process...
>>>>      */
>>>>     list_for_each_entry(ctx, &local->chanctx_list, list)
>>>>         ctx->driver_present = false;
>>>> }
>>>>
>>>>
>>>> So, how is the driver supposed to be cleaned up in this scenario?
>>> Driver was cleaned up in drv_start. See iwl_mld_restart_cleanup.
>>> Could you please share the iwlmld.ko and iwlwifi.ko files?

Hello Miriam,

Should we call 'iwl_mld_restart_cleanup()' in the failure path before the goto error?

I do not see the log "mld-mac80211-start, already in-hw-restart, stopping fw cleanup"
in my dump, so it seems it did not actually do cleanup in this particular crash.

	if (mld->fw_status.in_hw_restart) {
		IWL_ERR(mld, "mld-mac80211-start, already in-hw-restart, stopping fw cleanup\n");
		iwl_mld_stop_fw(mld);
		iwl_mld_restart_cleanup(mld);
	}

	if (!in_d3 || ret) {
		ret = iwl_mld_start_fw(mld);
		if (ret) {
			IWL_ERR(mld, "Failed start-fw. ret=%d\n", ret);
			goto error;
		}
	}

...

And note this in the error path in same method:

error:
	/* If we failed to restart the hw, there is nothing useful
	 * we can do but indicate we are no longer in restart.
	 */
	mld->fw_status.in_hw_restart = false;

Maybe that keeps that cleanup code above from hitting in double failure
states?

[snipped rest of the logs to keep the email from being huge]

Thanks,
Ben


^ permalink raw reply

* Re: Use-after-free in iwl-mld after hardware fails to restart.
From: Ben Greear @ 2026-03-04 19:26 UTC (permalink / raw)
  To: Korenblit, Miriam Rachel, linux-wireless
In-Reply-To: <b5803b14-c421-4a05-96c7-56ba7d1b8edb@candelatech.com>

On 3/3/26 06:27, Ben Greear wrote:
> On 3/2/26 23:19, Korenblit, Miriam Rachel wrote:
>>
>>
>>> -----Original Message-----
>>> From: Ben Greear <greearb@candelatech.com>
>>> Sent: Monday, March 2, 2026 9:00 PM
>>> To: linux-wireless <linux-wireless@vger.kernel.org>; Korenblit, Miriam Rachel
>>> <miriam.rachel.korenblit@intel.com>
>>> Subject: Use-after-free in iwl-mld after hardware fails to restart.
>>>
>>> Hello,
>>>
>>> Here's another failure case from my torture test system.
>>>
>>> This is from a patched 6.18.14+ kernel, but from a look at upstream Linux
>>> kernel, the problems are there as well.
>>>
>>> I believe the problem is something like this:
>>>
>>> firmware crashes several times and cannot recover.  Maybe
>>> Intel folks can tell why it is crashing?  I'd love to know if that
>>> is something that can be fixed in the driver.
>>>
>>>   From mac80211/util.c:
>>>
>>> int ieee80211_reconfig(struct ieee80211_local *local)
>>> is called, and gets to the failure case in this code (I see that second WARN in the
>>> crash logs)
>>> .....
>>>     /*
>>>      * Upon resume hardware can sometimes be goofy due to
>>>      * various platform / driver / bus issues, so restarting
>>>      * the device may at times not work immediately. Propagate
>>>      * the error.
>>>      */
>>>     res = drv_start(local);
>>>     if (res) {
>>>         if (suspended)
>>>             WARN(1, "Hardware became unavailable upon resume.
>>> This could be a software issue prior to suspend or a hardware issue.\n");
>>>         else
>>>             WARN(1, "Hardware became unavailable during
>>> restart.\n");
>>>         ieee80211_wake_queues_by_reason(hw,
>>> IEEE80211_MAX_QUEUE_MAP,
>>>
>>>     IEEE80211_QUEUE_STOP_REASON_SUSPEND,
>>>                         false);
>>>         ieee80211_handle_reconfig_failure(local);
>>>         return res;
>>>
>>>
>>> This method has comments about cleaning things up, but I don't see where it
>>> actually
>>> cleans up the driver.  And it sets SDATA_IN_DRIVER to false, so a lot of the calls
>>> in driver-ops.h that would otherwise tell the driver to clean up skip calls to
>>> the driver.
>>>
>>> static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)
>>> {
>>>     struct ieee80211_sub_if_data *sdata;
>>>     struct ieee80211_chanctx *ctx;
>>>
>>>     lockdep_assert_wiphy(local->hw.wiphy);
>>>
>>>     /*
>>>      * We get here if during resume the device can't be restarted properly.
>>>      * We might also get here if this happens during HW reset, which is a
>>>      * slightly different situation and we need to drop all connections in
>>>      * the latter case.
>>>      *
>>>      * Ask cfg80211 to turn off all interfaces, this will result in more
>>>      * warnings but at least we'll then get into a clean stopped state.
>>>      */
>>>
>>>     local->resuming = false;
>>>     local->suspended = false;
>>>     local->in_reconfig = false;
>>>     local->reconfig_failure = true;
>>>
>>>     ieee80211_flush_completed_scan(local, true);
>>>
>>>     /* scheduled scan clearly can't be running any more, but tell
>>>      * cfg80211 and clear local state
>>>      */
>>>     ieee80211_sched_scan_end(local);
>>>
>>>     list_for_each_entry(sdata, &local->interfaces, list)
>>>         sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER;
>>>
>>>     /* Mark channel contexts as not being in the driver any more to avoid
>>>      * removing them from the driver during the shutdown process...
>>>      */
>>>     list_for_each_entry(ctx, &local->chanctx_list, list)
>>>         ctx->driver_present = false;
>>> }
>>>
>>>
>>> So, how is the driver supposed to be cleaned up in this scenario?
>> Driver was cleaned up in drv_start. See iwl_mld_restart_cleanup.
>> Could you please share the iwlmld.ko and iwlwifi.ko files?
> 
> I have already made code changes and re-compiled to try to track it down.
> 
> If you can let me know what sort of information you'd like to see (like
> gdb code listings?) I can gather it next time I can reproduce the problem.
> 
> Any idea why the firmware is crashing?
> 
> Thanks,
> Ben
> 

I hit something like this again just now, here is the logs from the kdump vmcore-dmesg
file.   wlan11 is on the bus 0000:36:00.0 radio.  My previously posted work-arounds help in
other cases, but seems it does not fully solve use-after-free down in iwlmld.  I'll work on
on a way to fix this, but suggestions are welcome.


[start of file, but obviously more logs above this]

[ 3494.878836] iwlwifi 0000:36:00.0: Transport status: 0x0000014A, valid: 7
[ 3494.884282] iwlwifi 0000:36:00.0: 0x20000070 | NMI_INTERRUPT_LMAC_FATAL
[ 3494.889638] iwlwifi 0000:36:00.0: 0x00000000 | umac branchlink1
[ 3494.894369] iwlwifi 0000:36:00.0: 0xC00808AA | umac branchlink2
[ 3494.899033] iwlwifi 0000:36:00.0: 0x80287BFE | umac interruptlink1
[ 3494.903939] iwlwifi 0000:36:00.0: 0xC008462C | umac interruptlink2
[ 3494.908882] iwlwifi 0000:36:00.0: 0x00000002 | umac data1
[ 3494.913001] iwlwifi 0000:36:00.0: 0xC008462C | umac data2
[ 3494.917134] iwlwifi 0000:36:00.0: 0x00000000 | umac data3
[ 3494.921275] iwlwifi 0000:36:00.0: 0x00000065 | umac major
[ 3494.925428] iwlwifi 0000:36:00.0: 0x6EF20B19 | umac minor
[ 3494.929553] iwlwifi 0000:36:00.0: 0x0007295B | frame pointer
[ 3494.933953] iwlwifi 0000:36:00.0: 0xD00D6258 | stack pointer
[ 3494.938360] iwlwifi 0000:36:00.0: 0x0001016A | last host cmd
[ 3494.942921] iwlwifi 0000:36:00.0: 0x00000000 | isr status reg
[ 3494.947502] iwlwifi 0000:36:00.0: TCM1 status:
[ 3494.950682] iwlwifi 0000:36:00.0: 0x00000070 | error ID
[ 3494.954654] iwlwifi 0000:36:00.0: 0x00001D2E | tcm branchlink2
[ 3494.959297] iwlwifi 0000:36:00.0: 0x0000211C | tcm interruptlink1
[ 3494.964135] iwlwifi 0000:36:00.0: 0x0000211C | tcm interruptlink2
[ 3494.968954] iwlwifi 0000:36:00.0: 0x40000000 | tcm data1
[ 3494.973032] iwlwifi 0000:36:00.0: 0xDEADBEEF | tcm data2
[ 3494.977066] iwlwifi 0000:36:00.0: 0xDEADBEEF | tcm data3
[ 3494.981105] iwlwifi 0000:36:00.0: 0x00001DAC | tcm log PC
[ 3494.985235] iwlwifi 0000:36:00.0: 0x00803FF0 | tcm frame pointer
[ 3494.990031] iwlwifi 0000:36:00.0: 0x00803F5C | tcm stack pointer
[ 3494.994792] iwlwifi 0000:36:00.0: 0x00000000 | tcm msg ID
[ 3494.998921] iwlwifi 0000:36:00.0: 0x40080000 | tcm ISR status
[ 3495.003417] iwlwifi 0000:36:00.0: 0x000002F0 | tcm HW status[0]
[ 3495.008143] iwlwifi 0000:36:00.0: 0x00000000 | tcm HW status[1]
[ 3495.012785] iwlwifi 0000:36:00.0: 0x00000000 | tcm HW status[2]
[ 3495.017447] iwlwifi 0000:36:00.0: 0x00008100 | tcm HW status[3]
[ 3495.022154] iwlwifi 0000:36:00.0: 0x00000000 | tcm HW status[4]
[ 3495.026812] iwlwifi 0000:36:00.0: 0x00000000 | tcm SW status[0]
[ 3495.031608] iwlwifi 0000:36:00.0: RCM1 status:
[ 3495.034792] iwlwifi 0000:36:00.0: 0x00000070 | error ID
[ 3495.038840] iwlwifi 0000:36:00.0: 0x00001E2E | rcm branchlink2
[ 3495.043414] iwlwifi 0000:36:00.0: 0x000027A0 | rcm interruptlink1
[ 3495.048248] iwlwifi 0000:36:00.0: 0x000027A0 | rcm interruptlink2
[ 3495.053182] iwlwifi 0000:36:00.0: 0x20000000 | rcm data1
[ 3495.057450] iwlwifi 0000:36:00.0: 0xDEADBEEF | rcm data2
[ 3495.061499] iwlwifi 0000:36:00.0: 0xDEADBEEF | rcm data3
[ 3495.065536] iwlwifi 0000:36:00.0: 0x00001E98 | rcm log PC
[ 3495.069770] iwlwifi 0000:36:00.0: 0x00803FF0 | rcm frame pointer
[ 3495.074511] iwlwifi 0000:36:00.0: 0x00803F5C | rcm stack pointer
[ 3495.079238] iwlwifi 0000:36:00.0: 0x00000000 | rcm msg ID
[ 3495.083362] iwlwifi 0000:36:00.0: 0x20000000 | rcm ISR status
[ 3495.087864] iwlwifi 0000:36:00.0: 0x00420500 | frame HW status
[ 3495.092420] iwlwifi 0000:36:00.0: 0x00000000 | LMAC-to-RCM request mbox
[ 3495.097785] iwlwifi 0000:36:00.0: 0x00000000 | RCM-to-LMAC request mbox
[ 3495.103207] iwlwifi 0000:36:00.0: 0x00000000 | MAC header control
[ 3495.108022] iwlwifi 0000:36:00.0: 0x00000000 | MAC header addr1 low
[ 3495.113015] iwlwifi 0000:36:00.0: 0x003C0000 | MAC header info
[ 3495.117652] iwlwifi 0000:36:00.0: 0x00000000 | MAC header error
[ 3495.122379] iwlwifi 0000:36:00.0: TCM2 status:
[ 3495.125549] iwlwifi 0000:36:00.0: 0x00000070 | error ID
[ 3495.129511] iwlwifi 0000:36:00.0: 0x00001D2E | tcm branchlink2
[ 3495.134131] iwlwifi 0000:36:00.0: 0x0000211C | tcm interruptlink1
[ 3495.138958] iwlwifi 0000:36:00.0: 0x0000211C | tcm interruptlink2
[ 3495.143789] iwlwifi 0000:36:00.0: 0x40000000 | tcm data1
[ 3495.148002] iwlwifi 0000:36:00.0: 0xDEADBEEF | tcm data2
[ 3495.152057] iwlwifi 0000:36:00.0: 0xDEADBEEF | tcm data3
[ 3495.156113] iwlwifi 0000:36:00.0: 0x00001DAC | tcm log PC
[ 3495.160241] iwlwifi 0000:36:00.0: 0x00803FF0 | tcm frame pointer
[ 3495.165010] iwlwifi 0000:36:00.0: 0x00803F5C | tcm stack pointer
[ 3495.169754] iwlwifi 0000:36:00.0: 0x00000000 | tcm msg ID
[ 3495.173894] iwlwifi 0000:36:00.0: 0x40080000 | tcm ISR status
[ 3495.178380] iwlwifi 0000:36:00.0: 0x000002F0 | tcm HW status[0]
[ 3495.183093] iwlwifi 0000:36:00.0: 0x00000000 | tcm HW status[1]
[ 3495.187778] iwlwifi 0000:36:00.0: 0x00000000 | tcm HW status[2]
[ 3495.192457] iwlwifi 0000:36:00.0: 0x00008000 | tcm HW status[3]
[ 3495.197171] iwlwifi 0000:36:00.0: 0x00000000 | tcm HW status[4]
[ 3495.201818] iwlwifi 0000:36:00.0: 0x00000000 | tcm SW status[0]
[ 3495.206557] iwlwifi 0000:36:00.0: RCM2 status:
[ 3495.209741] iwlwifi 0000:36:00.0: 0x00000070 | error ID
[ 3495.213759] iwlwifi 0000:36:00.0: 0x00001E2E | rcm branchlink2
[ 3495.218334] iwlwifi 0000:36:00.0: 0x000027A0 | rcm interruptlink1
[ 3495.223171] iwlwifi 0000:36:00.0: 0x000027A0 | rcm interruptlink2
[ 3495.228036] iwlwifi 0000:36:00.0: 0x20000000 | rcm data1
[ 3495.232073] iwlwifi 0000:36:00.0: 0xDEADBEEF | rcm data2
[ 3495.236110] iwlwifi 0000:36:00.0: 0xDEADBEEF | rcm data3
[ 3495.240163] iwlwifi 0000:36:00.0: 0x00001E98 | rcm log PC
[ 3495.244352] iwlwifi 0000:36:00.0: 0x00803FF0 | rcm frame pointer
[ 3495.249099] iwlwifi 0000:36:00.0: 0x00803F5C | rcm stack pointer
[ 3495.253841] iwlwifi 0000:36:00.0: 0x00000000 | rcm msg ID
[ 3495.257984] iwlwifi 0000:36:00.0: 0x20000000 | rcm ISR status
[ 3495.262512] iwlwifi 0000:36:00.0: 0x00420500 | frame HW status
[ 3495.267085] iwlwifi 0000:36:00.0: 0x00000000 | LMAC-to-RCM request mbox
[ 3495.272467] iwlwifi 0000:36:00.0: 0x00000000 | RCM-to-LMAC request mbox
[ 3495.277912] iwlwifi 0000:36:00.0: 0x00000000 | MAC header control
[ 3495.282758] iwlwifi 0000:36:00.0: 0x00000000 | MAC header addr1 low
[ 3495.287772] iwlwifi 0000:36:00.0: 0x003C0000 | MAC header info
[ 3495.292384] iwlwifi 0000:36:00.0: 0x00000000 | MAC header error
[ 3495.297079] iwlwifi 0000:36:00.0: IML/ROM dump:
[ 3495.300348] iwlwifi 0000:36:00.0: 0x00000B03 | IML/ROM error/state
[ 3495.305291] iwlwifi 0000:36:00.0: 0x0000EF94 | IML/ROM data1
[ 3495.309772] iwlwifi 0000:36:00.0: 0x00000080 | IML/ROM WFPM_AUTH_KEY_0
[ 3495.315054] iwlwifi 0000:36:00.0: Fseq Registers:
[ 3495.318508] iwlwifi 0000:36:00.0: 0x67A00000 | FSEQ_ERROR_CODE
[ 3495.323084] iwlwifi 0000:36:00.0: 0x80B10006 | FSEQ_TOP_INIT_VERSION
[ 3495.328205] iwlwifi 0000:36:00.0: 0x00570000 | FSEQ_CNVIO_INIT_VERSION
[ 3495.333479] iwlwifi 0000:36:00.0: 0x0000AA14 | FSEQ_OTP_VERSION
[ 3495.338133] iwlwifi 0000:36:00.0: 0x0000000F | FSEQ_TOP_CONTENT_VERSION
[ 3495.343515] iwlwifi 0000:36:00.0: 0x4552414E | FSEQ_ALIVE_TOKEN
[ 3495.348165] iwlwifi 0000:36:00.0: 0x02001910 | FSEQ_CNVI_ID
[ 3495.352470] iwlwifi 0000:36:00.0: 0x02001910 | FSEQ_CNVR_ID
[ 3495.356777] iwlwifi 0000:36:00.0: 0x02001910 | CNVI_AUX_MISC_CHIP
[ 3495.361619] iwlwifi 0000:36:00.0: 0x02001910 | CNVR_AUX_MISC_CHIP
[ 3495.366456] iwlwifi 0000:36:00.0: 0x8F0F1BED | CNVR_SCU_SD_REGS_SD_REG_DIG_DCDC_VTRIM
[ 3495.373018] iwlwifi 0000:36:00.0: 0x00000000 | CNVR_SCU_SD_REGS_SD_REG_ACTIVE_VDIG_MIRROR
[ 3495.379941] iwlwifi 0000:36:00.0: 0x00570000 | FSEQ_PREV_CNVIO_INIT_VERSION
[ 3495.385643] iwlwifi 0000:36:00.0: 0x00B10006 | FSEQ_WIFI_FSEQ_VERSION
[ 3495.390826] iwlwifi 0000:36:00.0: 0x00B10005 | FSEQ_BT_FSEQ_VERSION
[ 3495.395833] iwlwifi 0000:36:00.0: 0x000000E6 | FSEQ_CLASS_TP_VERSION
[ 3495.401013] iwlwifi 0000:36:00.0: UMAC CURRENT PC: 0x8028b720
[ 3495.405529] iwlwifi 0000:36:00.0: LMAC1 CURRENT PC: 0xd0
[ 3495.409573] iwlwifi 0000:36:00.0: LMAC2 CURRENT PC: 0xd0
[ 3495.413616] iwlwifi 0000:36:00.0: UMAC CURRENT PC 1: 0x8028b71e
[ 3495.418273] iwlwifi 0000:36:00.0: TCM1 CURRENT PC: 0xd0
[ 3495.422241] iwlwifi 0000:36:00.0: RCM1 CURRENT PC: 0xd0
[ 3495.426197] iwlwifi 0000:36:00.0: RCM2 CURRENT PC: 0xd0
[ 3495.430238] iwlwifi 0000:36:00.0: Function Scratch status:
[ 3495.434468] iwlwifi 0000:36:00.0: 0x01010101 | Func Scratch
[ 3496.372015] iwlwifi 0000:36:00.0: Failed to get INIT_COMPLETE -110
[ 3496.376948] iwlwifi 0000:36:00.0: WRT: Collecting data: ini trigger 4 fired (delay=0ms).
[ 3498.129835] iwlwifi 0000:36:00.0: Failed start-fw. ret=-110
[ 3498.134138] ------------[ cut here ]------------
[ 3498.134142] Hardware became unavailable during restart.
[ 3498.134249] WARNING: CPU: 3 PID: 52511 at net/mac80211/util.c:1927 ieee80211_reconfig+0x1df/0x4790 [mac80211]
[ 3498.134445] Modules linked in: vrf nf_conntrack_netlink nf_conntrack nfnetlink nf_defrag_ipv6 nf_defrag_ipv4 8021q garp mrp stp llc macvlan pktgen rfcomm 
rpcrdma rdma_cm iw_cm nfsv3 ib_cm ib_core nfs netfs qrtr bnep snd_hda_codec_intelhdmi snd_hda_codec_hdmi snd_hda_codec_alc662 snd_hda_codec_realtek_lib 
snd_hda_codec_generic ee1004 iTCO_wdt snd_hda_intel intel_rapl_msr intel_pmc_bxt snd_intel_dspcfg iTCO_vendor_support snd_hda_codec coretemp snd_hda_core 
snd_hwdep intel_rapl_common intel_uncore_frequency snd_seq intel_uncore_frequency_common snd_seq_device snd_pcm iwlmld snd_timer intel_tcc_cooling snd i2c_i801 
x86_pkg_temp_thermal i2c_smbus intel_powerclamp pcspkr intel_wmi_thunderbolt soundcore mac80211 i2c_mux btusb btbcm iwlwifi btmtk btrtl btintel bluetooth 
cfg80211 ftdi_sio mei_pxp mei_hdcp intel_pmc_core intel_pch_thermal pmt_telemetry pmt_discovery pmt_class intel_pmc_ssram_telemetry intel_vsec acpi_pad bfq nfsd 
sch_fq_codel auth_rpcgss nfs_acl lockd grace nfs_localio sunrpc zram raid1 dm_raid raid456
[ 3498.134640]  async_raid6_recov async_memcpy async_pq async_xor xor async_tx raid6_pq i915 drm_buddy intel_gtt drm_client_lib drm_display_helper 
drm_kms_helper cec rc_core ttm igb agpgart dca i2c_algo_bit hwmon mei_wdt drm video intel_oc_wdt wmi i2c_core scsi_dh_rdac scsi_dh_emc scsi_dh_alua dm_multipath 
fuse [last unloaded: nfnetlink]
[ 3498.134776] CPU: 3 UID: 0 PID: 52511 Comm: kworker/3:2 Kdump: loaded Tainted: G        W           6.18.14+ #28 PREEMPT(full)
[ 3498.134784] Tainted: [W]=WARN
[ 3498.134787] Hardware name: Default string Default string/SKYBAY, BIOS 5.12 02/21/2023
[ 3498.134792] Workqueue: events_freezable ieee80211_restart_work [mac80211]
[ 3498.134914] RIP: 0010:ieee80211_reconfig+0x1df/0x4790 [mac80211]
[ 3498.135012] Code: 89 5c 24 08 e8 42 e6 ec ff 4c 8b 5c 24 08 85 c0 89 04 24 0f 84 a7 08 00 00 48 c7 c7 00 8f 41 a2 4c 89 5c 24 08 e8 b1 1e d1 de <0f> 0b 48 b8 
00 00 00 00 00 fc ff df 4c 8b 5c 24 08 49 8d bb 44 44
[ 3498.135018] RSP: 0018:ffff888163ddfa60 EFLAGS: 00010282
[ 3498.135024] RAX: 0000000000000000 RBX: ffff8881635d2080 RCX: 0000000000000001
[ 3498.135028] RDX: 0000000000000027 RSI: 0000000000000004 RDI: ffff88841dba4e48
[ 3498.135032] RBP: dffffc0000000000 R08: 0000000000000001 R09: ffffed1083b749c9
[ 3498.135036] R10: ffff88841dba4e4b R11: 00000000000b05e0 R12: ffffed102c6ba1e5
[ 3498.135040] R13: ffff8881635d4d00 R14: ffff8881635d0f28 R15: ffff8881635d52c8
[ 3498.135044] FS:  0000000000000000(0000) GS:ffff8884974c6000(0000) knlGS:0000000000000000
[ 3498.135049] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 3498.135052] CR2: 00007f38f1bc2ff8 CR3: 000000000509a003 CR4: 00000000003706f0
[ 3498.135057] Call Trace:
[ 3498.135061]  <TASK>
[ 3498.135066]  ? find_held_lock+0x2b/0x80
[ 3498.135077]  ? schedule+0x2cc/0x3a0
[ 3498.135093]  ? ieee80211_stop_device+0x110/0x110 [mac80211]
[ 3498.135219]  ? synchronize_rcu_expedited+0x379/0x3e0
[ 3498.135227]  ? rcu_exp_wait_wake+0x13c0/0x13c0
[ 3498.135231]  ? do_raw_spin_lock+0x12c/0x270
[ 3498.135240]  ? swake_up_locked+0x1b0/0x1b0
[ 3498.135252]  ? cond_synchronize_rcu_expedited_full+0x90/0x90
[ 3498.135264]  ieee80211_restart_work+0x261/0x3c0 [mac80211]
[ 3498.135376]  process_one_work+0x83f/0x17b0
[ 3498.135392]  ? pwq_dec_nr_in_flight+0xe00/0xe00
[ 3498.135416]  ? ieee80211_ifcomb_check+0x180/0x180 [mac80211]
[ 3498.135513]  worker_thread+0x58c/0xfb0
[ 3498.135524]  ? __kthread_parkme+0xc6/0x1f0
[ 3498.135534]  ? rescuer_thread+0x1340/0x1340
[ 3498.135539]  kthread+0x3b7/0x770
[ 3498.135546]  ? kthread_is_per_cpu+0xb0/0xb0
[ 3498.135550]  ? ret_from_fork+0x17/0x3a0
[ 3498.135557]  ? lock_release+0xce/0x290
[ 3498.135565]  ? kthread_is_per_cpu+0xb0/0xb0
[ 3498.135571]  ret_from_fork+0x28b/0x3a0
[ 3498.135575]  ? kthread_is_per_cpu+0xb0/0xb0
[ 3498.135580]  ret_from_fork_asm+0x11/0x20
[ 3498.135599]  </TASK>
[ 3498.135602] irq event stamp: 163557
[ 3498.135605] hardirqs last  enabled at (163563): [<ffffffff8161233e>] __up_console_sem+0x5e/0x70
[ 3498.135612] hardirqs last disabled at (163568): [<ffffffff81612323>] __up_console_sem+0x43/0x70
[ 3498.135616] softirqs last  enabled at (162518): [<ffffffff81470b5c>] __irq_exit_rcu+0xcc/0x100
[ 3498.135625] softirqs last disabled at (162513): [<ffffffff81470b5c>] __irq_exit_rcu+0xcc/0x100
[ 3498.135630] ---[ end trace 0000000000000000 ]---
[ 3498.135791] wlan11: deauthenticating from 02:58:a4:ff:75:59 by local choice (Reason: 3=DEAUTH_LEAVING)
[ 3498.144135] wlan11: sta-info-move-state to NONE: current state: 4 (NOT AUTH) is invalid
[ 3498.144154] wlan11: HW problem - can not stop rx aggregation for 02:58:a4:ff:75:59 tid 0
[ 3498.144160] wlan11: HW problem - can not stop rx aggregation for 02:58:a4:ff:75:59 tid 4
[ 3498.144165] wlan11: HW problem - can not stop rx aggregation for 02:58:a4:ff:75:59 tid 6
[ 3498.144191] iwlwifi 0000:36:00.0: Failed to trigger RX queues sync (-5)
[ 3498.174792] wlan11: drv-sta-state, sdata-not-in-driver, old_state: 4  new_state: 3
[ 3498.184599] wlan11: failed to remove key (0, 02:58:a4:ff:75:59) from hardware (-5)
[ 3498.192202] wlan11: drv-sta-state, sdata-not-in-driver, old_state: 3  new_state: 2
[ 3498.198503] wlan11: drv-sta-state, sdata-not-in-driver, old_state: 2  new_state: 1
[ 3498.205662] wlan11: drv-sta-state, sdata-not-in-driver, old_state: 1  new_state: 0
[ 3498.214838] ------------[ cut here ]------------
[ 3498.214847] WARNING: CPU: 3 PID: 52511 at net/mac80211/driver-ops.h:1055 ieee80211_del_chanctx+0x336/0x3d0 [mac80211]
[ 3498.215059] Modules linked in: vrf nf_conntrack_netlink nf_conntrack nfnetlink nf_defrag_ipv6 nf_defrag_ipv4 8021q garp mrp stp llc macvlan pktgen rfcomm 
rpcrdma rdma_cm iw_cm nfsv3 ib_cm ib_core nfs netfs qrtr bnep snd_hda_codec_intelhdmi snd_hda_codec_hdmi snd_hda_codec_alc662 snd_hda_codec_realtek_lib 
snd_hda_codec_generic ee1004 iTCO_wdt snd_hda_intel intel_rapl_msr intel_pmc_bxt snd_intel_dspcfg iTCO_vendor_support snd_hda_codec coretemp snd_hda_core 
snd_hwdep intel_rapl_common intel_uncore_frequency snd_seq intel_uncore_frequency_common snd_seq_device snd_pcm iwlmld snd_timer intel_tcc_cooling snd i2c_i801 
x86_pkg_temp_thermal i2c_smbus intel_powerclamp pcspkr intel_wmi_thunderbolt soundcore mac80211 i2c_mux btusb btbcm iwlwifi btmtk btrtl btintel bluetooth 
cfg80211 ftdi_sio mei_pxp mei_hdcp intel_pmc_core intel_pch_thermal pmt_telemetry pmt_discovery pmt_class intel_pmc_ssram_telemetry intel_vsec acpi_pad bfq nfsd 
sch_fq_codel auth_rpcgss nfs_acl lockd grace nfs_localio sunrpc zram raid1 dm_raid raid456
[ 3498.215403]  async_raid6_recov async_memcpy async_pq async_xor xor async_tx raid6_pq i915 drm_buddy intel_gtt drm_client_lib drm_display_helper 
drm_kms_helper cec rc_core ttm igb agpgart dca i2c_algo_bit hwmon mei_wdt drm video intel_oc_wdt wmi i2c_core scsi_dh_rdac scsi_dh_emc scsi_dh_alua dm_multipath 
fuse [last unloaded: nfnetlink]
[ 3498.215521] CPU: 3 UID: 0 PID: 52511 Comm: kworker/3:2 Kdump: loaded Tainted: G        W           6.18.14+ #28 PREEMPT(full)
[ 3498.215529] Tainted: [W]=WARN
[ 3498.215532] Hardware name: Default string Default string/SKYBAY, BIOS 5.12 02/21/2023
[ 3498.215537] Workqueue: events_freezable ieee80211_restart_work [mac80211]
[ 3498.215644] RIP: 0010:ieee80211_del_chanctx+0x336/0x3d0 [mac80211]
[ 3498.215856] Code: fe ff ff 80 3d 68 6a a3 ff 00 0f 85 fe fd ff ff 48 c7 c7 60 aa 41 a2 c6 05 54 6a a3 ff 01 e8 a1 41 cf de 0f 0b e9 e4 fd ff ff <0f> 0b 48 c7 
c7 80 ab 41 a2 e8 0c ec ea de e9 65 fe ff ff 48 89 ef
[ 3498.215865] RSP: 0018:ffff888163ddf108 EFLAGS: 00010246
[ 3498.215877] RAX: 0000000000000000 RBX: ffff8881635d0ee0 RCX: 0000000000000000
[ 3498.215884] RDX: 0000000000000004 RSI: ffff8881635d0788 RDI: ffff8881f5f4b718
[ 3498.215891] RBP: ffff88815e94d454 R08: 0000000000000001 R09: 000000005102af7d
[ 3498.215898] R10: ffff8881f5f4ac00 R11: ffff8881f5f4b6a0 R12: ffff88815e94d400
[ 3498.215903] R13: 0000000000000000 R14: ffff8881635d4f00 R15: ffff88815e94d4b0
[ 3498.215907] FS:  0000000000000000(0000) GS:ffff8884974c6000(0000) knlGS:0000000000000000
[ 3498.215912] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 3498.215916] CR2: 00007f38f1bc2ff8 CR3: 00000001ca0eb002 CR4: 00000000003706f0
[ 3498.215920] Call Trace:
[ 3498.215925]  <TASK>
[ 3498.215932]  ieee80211_free_chanctx+0x144/0x210 [mac80211]
[ 3498.216047]  __ieee80211_link_release_channel+0x394/0x4a0 [mac80211]
[ 3498.216146]  ieee80211_set_disassoc+0x9dc/0x1c10 [mac80211]
[ 3498.216244]  ? ieee80211_add_link_elems+0x35b0/0x35b0 [mac80211]
[ 3498.216347]  ieee80211_mgd_deauth+0x526/0x1780 [mac80211]
[ 3498.216517]  ? check_irq_usage+0xb5/0xa20
[ 3498.216536]  ? ieee80211_mgd_assoc+0x5be0/0x5be0 [mac80211]
[ 3498.216724]  ? check_path.constprop.0+0x24/0x50
[ 3498.216735]  ? check_noncircular+0x7e/0x140
[ 3498.216755]  ? lock_is_held_type+0xa5/0x110
[ 3498.216773]  cfg80211_mlme_deauth+0x333/0x7a0 [cfg80211]
[ 3498.216975]  ? prb_final_commit+0x40/0x40
[ 3498.216990]  ? cfg80211_mlme_assoc+0x960/0x960 [cfg80211]
[ 3498.217170]  cfg80211_mlme_down+0x16f/0x230 [cfg80211]
[ 3498.217333]  ? cfg80211_mlme_disassoc+0x450/0x450 [cfg80211]
[ 3498.217492]  ? kfree+0x2ae/0x580
[ 3498.217515]  cfg80211_disconnect+0x4d2/0x700 [cfg80211]
[ 3498.217694]  cfg80211_netdev_notifier_call+0x661/0x10a0 [cfg80211]
[ 3498.217855]  ? prb_next_reserve_seq+0x2a0/0x2a0
[ 3498.217869]  ? cfg80211_register_netdevice+0x2a0/0x2a0 [cfg80211]
[ 3498.218022]  ? up+0x102/0x180
[ 3498.218030]  ? __bfs+0x12e/0x220
[ 3498.218035]  ? do_raw_spin_unlock+0x54/0x220
[ 3498.218043]  ? check_irq_usage+0xb5/0xa20
[ 3498.218049]  ? __bfs+0x12e/0x220
[ 3498.218056]  ? check_irq_usage+0xb5/0xa20
[ 3498.218064]  ? check_path.constprop.0+0x24/0x50
[ 3498.218070]  ? __bfs+0x12e/0x220
[ 3498.218094]  ? __lock_acquire+0x432/0x23b0
[ 3498.218107]  ? lock_acquire+0x155/0x2e0
[ 3498.218113]  ? packet_notifier+0xd3/0xa70
[ 3498.218120]  ? find_held_lock+0x2b/0x80
[ 3498.218126]  ? packet_notifier+0x1f0/0xa70
[ 3498.218132]  ? lock_release+0xce/0x290
[ 3498.218140]  ? packet_notifier+0x1fa/0xa70
[ 3498.218149]  ? packet_getname_spkt+0x290/0x290
[ 3498.218154]  ? lock_is_held_type+0xa5/0x110
[ 3498.218166]  notifier_call_chain+0x97/0x280
[ 3498.218178]  __dev_close_many+0xe8/0x670
[ 3498.218187]  ? netdev_notify_peers+0x20/0x20
[ 3498.218194]  ? try_to_wake_up+0xa09/0x1450
[ 3498.218206]  netif_close_many+0x1e6/0x5c0
[ 3498.218215]  ? __dev_close_many+0x670/0x670
[ 3498.218222]  ? wake_up_q+0xaf/0x130
[ 3498.218231]  netif_close+0x141/0x1d0
[ 3498.218237]  ? netif_close_many+0x5c0/0x5c0
[ 3498.218249]  dev_close+0x89/0x1f0
[ 3498.218255]  cfg80211_shutdown_all_interfaces+0x76/0x190 [cfg80211]
[ 3498.218344]  ieee80211_restart_work+0x2c8/0x3c0 [mac80211]
[ 3498.218440]  process_one_work+0x83f/0x17b0
[ 3498.218455]  ? pwq_dec_nr_in_flight+0xe00/0xe00
[ 3498.218466]  ? ieee80211_ifcomb_check+0x180/0x180 [mac80211]
[ 3498.218562]  worker_thread+0x58c/0xfb0
[ 3498.218573]  ? __kthread_parkme+0xc6/0x1f0
[ 3498.218582]  ? rescuer_thread+0x1340/0x1340
[ 3498.218588]  kthread+0x3b7/0x770
[ 3498.218594]  ? kthread_is_per_cpu+0xb0/0xb0
[ 3498.218599]  ? ret_from_fork+0x17/0x3a0
[ 3498.218605]  ? lock_release+0xce/0x290
[ 3498.218612]  ? kthread_is_per_cpu+0xb0/0xb0
[ 3498.218619]  ret_from_fork+0x28b/0x3a0
[ 3498.218624]  ? kthread_is_per_cpu+0xb0/0xb0
[ 3498.218629]  ret_from_fork_asm+0x11/0x20
[ 3498.218646]  </TASK>
[ 3498.218649] irq event stamp: 168549
[ 3498.218652] hardirqs last  enabled at (168555): [<ffffffff8161233e>] __up_console_sem+0x5e/0x70
[ 3498.218658] hardirqs last disabled at (168560): [<ffffffff81612323>] __up_console_sem+0x43/0x70
[ 3498.218663] softirqs last  enabled at (167244): [<ffffffffa261e604>] __cleanup_single_sta+0x224/0x530 [mac80211]
[ 3498.218797] softirqs last disabled at (167242): [<ffffffffa271ee1d>] ieee80211_txq_purge+0x1bd/0x3c0 [mac80211]
[ 3498.218893] ---[ end trace 0000000000000000 ]---
[ 3498.219198] drv-remove-chanctx, NOT driver_present, not sending request to driver.
[ 3498.219208] ==================================================================
[ 3498.231427] BUG: KASAN: slab-use-after-free in iwl_mld_mac80211_flush+0x2c6/0x330 [iwlmld]
[ 3498.238423] Read of size 8 at addr ffff88813ef850a8 by task kworker/3:2/52511
[ 3498.244271]
[ 3498.244477] CPU: 3 UID: 0 PID: 52511 Comm: kworker/3:2 Kdump: loaded Tainted: G        W           6.18.14+ #28 PREEMPT(full)
[ 3498.244483] Tainted: [W]=WARN
[ 3498.244484] Hardware name: Default string Default string/SKYBAY, BIOS 5.12 02/21/2023
[ 3498.244486] Workqueue: events_freezable ieee80211_restart_work [mac80211]
[ 3498.244599] Call Trace:
[ 3498.244601]  <TASK>
[ 3498.244603]  dump_stack_lvl+0x73/0xa0
[ 3498.244609]  print_report+0xce/0x620
[ 3498.244615]  ? __virt_addr_valid+0x205/0x3f0
[ 3498.244620]  ? iwl_mld_mac80211_flush+0x2c6/0x330 [iwlmld]
[ 3498.244643]  kasan_report+0xc6/0xf0
[ 3498.244648]  ? iwl_mld_mac80211_flush+0x2c6/0x330 [iwlmld]
[ 3498.244666]  iwl_mld_mac80211_flush+0x2c6/0x330 [iwlmld]
[ 3498.244690]  __ieee80211_flush_queues+0x4e4/0x950 [mac80211]
[ 3498.244787]  ? ieee80211_get_vif_queues+0x270/0x270 [mac80211]
[ 3498.244880]  ? printk_get_console_flush_type+0x2d0/0x2d0
[ 3498.244884]  ? lock_is_held_type+0xa5/0x110
[ 3498.244890]  __ieee80211_recalc_idle+0x375/0x4a0 [mac80211]
[ 3498.244982]  ieee80211_recalc_idle+0x10/0x30 [mac80211]
[ 3498.245074]  ieee80211_del_chanctx+0x27d/0x3d0 [mac80211]
[ 3498.245167]  ieee80211_free_chanctx+0x144/0x210 [mac80211]
[ 3498.245260]  __ieee80211_link_release_channel+0x394/0x4a0 [mac80211]
[ 3498.245353]  ieee80211_set_disassoc+0x9dc/0x1c10 [mac80211]
[ 3498.245444]  ? ieee80211_add_link_elems+0x35b0/0x35b0 [mac80211]
[ 3498.245534]  ieee80211_mgd_deauth+0x526/0x1780 [mac80211]
[ 3498.245622]  ? check_irq_usage+0xb5/0xa20
[ 3498.245627]  ? ieee80211_mgd_assoc+0x5be0/0x5be0 [mac80211]
[ 3498.245728]  ? check_path.constprop.0+0x24/0x50
[ 3498.245732]  ? check_noncircular+0x7e/0x140
[ 3498.245737]  ? lock_is_held_type+0xa5/0x110
[ 3498.245742]  cfg80211_mlme_deauth+0x333/0x7a0 [cfg80211]
[ 3498.245858]  ? prb_final_commit+0x40/0x40
[ 3498.245863]  ? cfg80211_mlme_assoc+0x960/0x960 [cfg80211]
[ 3498.245949]  cfg80211_mlme_down+0x16f/0x230 [cfg80211]
[ 3498.246034]  ? cfg80211_mlme_disassoc+0x450/0x450 [cfg80211]
[ 3498.246116]  ? kfree+0x2ae/0x580
[ 3498.246123]  cfg80211_disconnect+0x4d2/0x700 [cfg80211]
[ 3498.246208]  cfg80211_netdev_notifier_call+0x661/0x10a0 [cfg80211]
[ 3498.246291]  ? prb_next_reserve_seq+0x2a0/0x2a0
[ 3498.246295]  ? cfg80211_register_netdevice+0x2a0/0x2a0 [cfg80211]
[ 3498.246378]  ? up+0x102/0x180
[ 3498.246382]  ? __bfs+0x12e/0x220
[ 3498.246385]  ? do_raw_spin_unlock+0x54/0x220
[ 3498.246390]  ? check_irq_usage+0xb5/0xa20
[ 3498.246394]  ? __bfs+0x12e/0x220
[ 3498.246398]  ? check_irq_usage+0xb5/0xa20
[ 3498.246402]  ? check_path.constprop.0+0x24/0x50
[ 3498.246405]  ? __bfs+0x12e/0x220
[ 3498.246410]  ? __lock_acquire+0x432/0x23b0
[ 3498.246417]  ? lock_acquire+0x155/0x2e0
[ 3498.246420]  ? packet_notifier+0xd3/0xa70
[ 3498.246425]  ? find_held_lock+0x2b/0x80
[ 3498.246428]  ? packet_notifier+0x1f0/0xa70
[ 3498.246432]  ? lock_release+0xce/0x290
[ 3498.246436]  ? packet_notifier+0x1fa/0xa70
[ 3498.246440]  ? packet_getname_spkt+0x290/0x290
[ 3498.246443]  ? lock_is_held_type+0xa5/0x110
[ 3498.246449]  notifier_call_chain+0x97/0x280
[ 3498.246456]  __dev_close_many+0xe8/0x670
[ 3498.246461]  ? netdev_notify_peers+0x20/0x20
[ 3498.246466]  ? try_to_wake_up+0xa09/0x1450
[ 3498.246472]  netif_close_many+0x1e6/0x5c0
[ 3498.246477]  ? __dev_close_many+0x670/0x670
[ 3498.246481]  ? wake_up_q+0xaf/0x130
[ 3498.246486]  netif_close+0x141/0x1d0
[ 3498.246489]  ? netif_close_many+0x5c0/0x5c0
[ 3498.246495]  dev_close+0x89/0x1f0
[ 3498.246498]  cfg80211_shutdown_all_interfaces+0x76/0x190 [cfg80211]
[ 3498.246639]  ieee80211_restart_work+0x2c8/0x3c0 [mac80211]
[ 3498.246751]  process_one_work+0x83f/0x17b0
[ 3498.246758]  ? pwq_dec_nr_in_flight+0xe00/0xe00
[ 3498.246763]  ? ieee80211_ifcomb_check+0x180/0x180 [mac80211]
[ 3498.246887]  worker_thread+0x58c/0xfb0
[ 3498.246893]  ? __kthread_parkme+0xc6/0x1f0
[ 3498.246898]  ? rescuer_thread+0x1340/0x1340
[ 3498.246901]  kthread+0x3b7/0x770
[ 3498.246904]  ? kthread_is_per_cpu+0xb0/0xb0
[ 3498.246907]  ? ret_from_fork+0x17/0x3a0
[ 3498.246911]  ? lock_release+0xce/0x290
[ 3498.246915]  ? kthread_is_per_cpu+0xb0/0xb0
[ 3498.246918]  ret_from_fork+0x28b/0x3a0
[ 3498.246921]  ? kthread_is_per_cpu+0xb0/0xb0
[ 3498.246924]  ret_from_fork_asm+0x11/0x20
[ 3498.246932]  </TASK>
[ 3498.246933]
[ 3498.519343] Allocated by task 57169:
[ 3498.521634]  kasan_save_stack+0x1c/0x40
[ 3498.521644]  kasan_save_track+0x10/0x30
[ 3498.521648]  __kasan_kmalloc+0x83/0x90
[ 3498.521652]  __kmalloc_noprof+0x24e/0x7d0
[ 3498.521657]  __sta_info_alloc+0x9c/0x1980 [mac80211]
[ 3498.521817]  ieee80211_prep_connection+0x1e3/0x1550 [mac80211]
[ 3498.521919]  ieee80211_mgd_auth+0xec6/0x1960 [mac80211]
[ 3498.522034]  cfg80211_mlme_auth+0x458/0x7f0 [cfg80211]
[ 3498.522154]  nl80211_authenticate+0xa90/0x1180 [cfg80211]
[ 3498.522249]  genl_family_rcv_msg_doit+0x1cb/0x2a0
[ 3498.522255]  genl_rcv_msg+0x3f7/0x6b0
[ 3498.522258]  netlink_rcv_skb+0x125/0x380
[ 3498.522261]  genl_rcv+0x24/0x40
[ 3498.522265]  netlink_unicast+0x5dd/0x9d0
[ 3498.522268]  netlink_sendmsg+0x749/0xc00
[ 3498.522271]  __sock_sendmsg+0xc1/0x150
[ 3498.522277]  ____sys_sendmsg+0x5f4/0x8f0
[ 3498.522281]  ___sys_sendmsg+0xed/0x170
[ 3498.522285]  __sys_sendmsg+0x107/0x1a0
[ 3498.522288]  do_syscall_64+0x69/0x1210
[ 3498.522294]  entry_SYSCALL_64_after_hwframe+0x4b/0x53
[ 3498.522299]
[ 3498.522508] Freed by task 52511:
[ 3498.524450]  kasan_save_stack+0x1c/0x40
[ 3498.524456]  kasan_save_track+0x10/0x30
[ 3498.524460]  __kasan_save_free_info+0x37/0x50
[ 3498.524464]  __kasan_slab_free+0x3b/0x60
[ 3498.524468]  kfree+0x164/0x580
[ 3498.524473]  __sta_info_flush+0x409/0x610 [mac80211]
[ 3498.524568]  ieee80211_set_disassoc+0x14fb/0x1c10 [mac80211]
[ 3498.524658]  ieee80211_mgd_deauth+0x526/0x1780 [mac80211]
[ 3498.524762]  cfg80211_mlme_deauth+0x333/0x7a0 [cfg80211]
[ 3498.524888]  cfg80211_mlme_down+0x16f/0x230 [cfg80211]
[ 3498.524983]  cfg80211_disconnect+0x4d2/0x700 [cfg80211]
[ 3498.525065]  cfg80211_netdev_notifier_call+0x661/0x10a0 [cfg80211]
[ 3498.525173]  notifier_call_chain+0x97/0x280
[ 3498.525179]  __dev_close_many+0xe8/0x670
[ 3498.525184]  netif_close_many+0x1e6/0x5c0
[ 3498.525188]  netif_close+0x141/0x1d0
[ 3498.525192]  dev_close+0x89/0x1f0
[ 3498.525196]  cfg80211_shutdown_all_interfaces+0x76/0x190 [cfg80211]
[ 3498.525277]  ieee80211_restart_work+0x2c8/0x3c0 [mac80211]
[ 3498.525365]  process_one_work+0x83f/0x17b0
[ 3498.525370]  worker_thread+0x58c/0xfb0
[ 3498.525373]  kthread+0x3b7/0x770
[ 3498.525377]  ret_from_fork+0x28b/0x3a0
[ 3498.525394]  ret_from_fork_asm+0x11/0x20
[ 3498.525400]
[ 3498.525610] The buggy address belongs to the object at ffff88813ef84000
  which belongs to the cache kmalloc-8k of size 8192
[ 3498.535533] The buggy address is located 4264 bytes inside of
  freed 8192-byte region [ffff88813ef84000, ffff88813ef86000)
[ 3498.545368]
[ 3498.545577] The buggy address belongs to the physical page:
[ 3498.549863] page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x13ef80
[ 3498.549868] head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
[ 3498.549871] anon flags: 0x5fff8000000040(head|node=0|zone=2|lastcpupid=0x3fff)
[ 3498.549877] page_type: f5(slab)
[ 3498.549882] raw: 005fff8000000040 ffff888120043180 ffffea0005cb8600 0000000000000005
[ 3498.549885] raw: 0000000000000000 0000000000020002 00000000f5000000 0000000000000000
[ 3498.549889] head: 005fff8000000040 ffff888120043180 ffffea0005cb8600 0000000000000005
[ 3498.549893] head: 0000000000000000 0000000000020002 00000000f5000000 0000000000000000
[ 3498.549896] head: 005fff8000000003 ffffea0004fbe001 00000000ffffffff 00000000ffffffff
[ 3498.549899] head: ffffffffffffffff 0000000000000000 00000000ffffffff 0000000000000000
[ 3498.549902] page dumped because: kasan: bad access detected
[ 3498.549905]
[ 3498.550110] Memory state around the buggy address:
[ 3498.553615]  ffff88813ef84f80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 3498.559547]  ffff88813ef85000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 3498.565482] >ffff88813ef85080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 3498.571409]                                   ^
[ 3498.574652]  ffff88813ef85100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 3498.580588]  ffff88813ef85180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
[ 3498.586522] ==================================================================
[ 3498.629921] Disabling lock debugging due to kernel taint: 0x5 (lockdep)

Thanks,
Ben


^ permalink raw reply

* [PATCH 3/3] dt-bindings: remoteproc: qcom,wcnss-pil: add WCN3610 compatible
From: Kerigan Creighton @ 2026-03-04 19:24 UTC (permalink / raw)
  To: linux-wireless
  Cc: loic.poulain, wcn36xx, andersson, mathieu.poirier,
	linux-remoteproc, linux-arm-msm, robh, krzk+dt, conor+dt,
	devicetree, linux-kernel, Kerigan Creighton
In-Reply-To: <20260304192409.927562-1-kerigancreighton@gmail.com>

Document the qcom,wcn3610 compatible string for use with
the qcom_wcnss_iris remoteproc driver.

Signed-off-by: Kerigan Creighton <kerigancreighton@gmail.com>
---
 Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.yaml | 1 +
 1 file changed, 1 insertion(+)

diff --git a/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.yaml b/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.yaml
index 117fb4d0c4..018cdf5177 100644
--- a/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.yaml
+++ b/Documentation/devicetree/bindings/remoteproc/qcom,wcnss-pil.yaml
@@ -109,6 +109,7 @@ properties:
     properties:
       compatible:
         enum:
+          - qcom,wcn3610
           - qcom,wcn3620
           - qcom,wcn3660
           - qcom,wcn3660b
-- 
2.53.0


^ permalink raw reply related

* [PATCH 2/3] remoteproc: qcom_wcnss_iris: add support for WCN3610
From: Kerigan Creighton @ 2026-03-04 19:24 UTC (permalink / raw)
  To: linux-wireless
  Cc: loic.poulain, wcn36xx, andersson, mathieu.poirier,
	linux-remoteproc, linux-arm-msm, robh, krzk+dt, conor+dt,
	devicetree, linux-kernel, Kerigan Creighton
In-Reply-To: <20260304192409.927562-1-kerigancreighton@gmail.com>

Add a qcom,wcn3610 compatible string.
The WCN3610 shares the same register configuration as the
WCN3620, so its configuration is being reused.

Signed-off-by: Kerigan Creighton <kerigancreighton@gmail.com>
---
 drivers/remoteproc/qcom_wcnss_iris.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/remoteproc/qcom_wcnss_iris.c b/drivers/remoteproc/qcom_wcnss_iris.c
index 2b89b4db6c..e58b59355f 100644
--- a/drivers/remoteproc/qcom_wcnss_iris.c
+++ b/drivers/remoteproc/qcom_wcnss_iris.c
@@ -95,6 +95,7 @@ void qcom_iris_disable(struct qcom_iris *iris)
 }
 
 static const struct of_device_id iris_of_match[] = {
+	{ .compatible = "qcom,wcn3610", .data = &wcn3620_data },
 	{ .compatible = "qcom,wcn3620", .data = &wcn3620_data },
 	{ .compatible = "qcom,wcn3660", .data = &wcn3660_data },
 	{ .compatible = "qcom,wcn3660b", .data = &wcn3680_data },
-- 
2.53.0


^ permalink raw reply related

* [PATCH 1/3] wifi: wcn36xx: add support for WCN3610
From: Kerigan Creighton @ 2026-03-04 19:24 UTC (permalink / raw)
  To: linux-wireless
  Cc: loic.poulain, wcn36xx, andersson, mathieu.poirier,
	linux-remoteproc, linux-arm-msm, robh, krzk+dt, conor+dt,
	devicetree, linux-kernel, Kerigan Creighton

The WCN3610 is a 2.4GHz-only WLAN/BLE combo chip used in some
cheaper Android and Windows phones such as the Lumia 550, and
IoT devices like the Anki Vector robot. It shares a lot in
common with the WCN3620.

Tested on an Anki Vector 1.0 and 2.0 robot. Support for other
WCN36xx chips has not been affected.

The WCN3610 requires specific BTC configuration values for
stable Wi-Fi. Without these values, there's some packet loss.
An extra CFG table was made so other chips are not affected.

STA_POWERSAVE causes firmware bugs (long hangs) with the
WCN3610, thus it has been disabled just for this chip.

Signed-off-by: Kerigan Creighton <kerigancreighton@gmail.com>
---
 drivers/net/wireless/ath/wcn36xx/main.c    |  4 +-
 drivers/net/wireless/ath/wcn36xx/smd.c     | 70 +++++++++++++++++++++-
 drivers/net/wireless/ath/wcn36xx/wcn36xx.h |  1 +
 3 files changed, 73 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c
index c3f0860873..6c90c13251 100644
--- a/drivers/net/wireless/ath/wcn36xx/main.c
+++ b/drivers/net/wireless/ath/wcn36xx/main.c
@@ -1438,7 +1438,7 @@ static int wcn36xx_init_ieee80211(struct wcn36xx *wcn)
 		BIT(NL80211_IFTYPE_MESH_POINT);
 
 	wcn->hw->wiphy->bands[NL80211_BAND_2GHZ] = &wcn_band_2ghz;
-	if (wcn->rf_id != RF_IRIS_WCN3620)
+	if (wcn->rf_id != RF_IRIS_WCN3620 && wcn->rf_id != RF_IRIS_WCN3610)
 		wcn->hw->wiphy->bands[NL80211_BAND_5GHZ] = &wcn_band_5ghz;
 
 	if (wcn->rf_id == RF_IRIS_WCN3680)
@@ -1535,6 +1535,8 @@ static int wcn36xx_platform_get_resources(struct wcn36xx *wcn,
 	/* External RF module */
 	iris_node = of_get_child_by_name(mmio_node, "iris");
 	if (iris_node) {
+		if (of_device_is_compatible(iris_node, "qcom,wcn3610"))
+			wcn->rf_id = RF_IRIS_WCN3610;
 		if (of_device_is_compatible(iris_node, "qcom,wcn3620"))
 			wcn->rf_id = RF_IRIS_WCN3620;
 		if (of_device_is_compatible(iris_node, "qcom,wcn3660") ||
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index 813553edcb..7352c73f32 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -83,6 +83,70 @@ static struct wcn36xx_cfg_val wcn36xx_cfg_vals[] = {
 	WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 1000),
 };
 
+static struct wcn36xx_cfg_val wcn3610_cfg_vals[] = {
+	WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
+	WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
+	WCN36XX_CFG_VAL(LOW_GAIN_OVERRIDE, 0),
+	WCN36XX_CFG_VAL(POWER_STATE_PER_CHAIN, 785),
+	WCN36XX_CFG_VAL(CAL_PERIOD, 5),
+	WCN36XX_CFG_VAL(CAL_CONTROL, 1),
+	WCN36XX_CFG_VAL(PROXIMITY, 0),
+	WCN36XX_CFG_VAL(NETWORK_DENSITY, 3),
+	WCN36XX_CFG_VAL(MAX_MEDIUM_TIME, 6000),
+	WCN36XX_CFG_VAL(MAX_MPDUS_IN_AMPDU, 64),
+	WCN36XX_CFG_VAL(RTS_THRESHOLD, 2347),
+	WCN36XX_CFG_VAL(SHORT_RETRY_LIMIT, 15),
+	WCN36XX_CFG_VAL(LONG_RETRY_LIMIT, 15),
+	WCN36XX_CFG_VAL(FRAGMENTATION_THRESHOLD, 8000),
+	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ZERO, 5),
+	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_ONE, 10),
+	WCN36XX_CFG_VAL(DYNAMIC_THRESHOLD_TWO, 15),
+	WCN36XX_CFG_VAL(FIXED_RATE, 0),
+	WCN36XX_CFG_VAL(RETRYRATE_POLICY, 4),
+	WCN36XX_CFG_VAL(RETRYRATE_SECONDARY, 131),
+	WCN36XX_CFG_VAL(RETRYRATE_TERTIARY, 129),
+	WCN36XX_CFG_VAL(FORCE_POLICY_PROTECTION, 5),
+	WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_24GHZ, 1),
+	WCN36XX_CFG_VAL(FIXED_RATE_MULTICAST_5GHZ, 5),
+	WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_5GHZ, 5),
+	WCN36XX_CFG_VAL(DEFAULT_RATE_INDEX_24GHZ, 6),
+	WCN36XX_CFG_VAL(MAX_BA_SESSIONS, 40),
+	WCN36XX_CFG_VAL(PS_DATA_INACTIVITY_TIMEOUT, 200),
+	WCN36XX_CFG_VAL(PS_ENABLE_BCN_FILTER, 1),
+	WCN36XX_CFG_VAL(PS_ENABLE_RSSI_MONITOR, 1),
+	WCN36XX_CFG_VAL(NUM_BEACON_PER_RSSI_AVERAGE, 20),
+	WCN36XX_CFG_VAL(STATS_PERIOD, 10),
+	WCN36XX_CFG_VAL(CFP_MAX_DURATION, 30000),
+	WCN36XX_CFG_VAL(FRAME_TRANS_ENABLED, 0),
+	WCN36XX_CFG_VAL(BA_THRESHOLD_HIGH, 128),
+	WCN36XX_CFG_VAL(MAX_BA_BUFFERS, 2560),
+	WCN36XX_CFG_VAL(DYNAMIC_PS_POLL_VALUE, 0),
+	WCN36XX_CFG_VAL(TX_PWR_CTRL_ENABLE, 1),
+	WCN36XX_CFG_VAL(ENABLE_CLOSE_LOOP, 1),
+	WCN36XX_CFG_VAL(ENABLE_LPWR_IMG_TRANSITION, 0),
+	/*
+	 * BTC_EXECUTION_MODE
+	 * 0: SMART_COEX
+	 * 1: WLAN_ONLY
+	 * 2: PTA_ONLY
+	 * 3: SMART_MAX_WLAN
+	 * 4: SMART_MAX_BT
+	 * 5: SMART_BT_A2DP
+	 */
+	WCN36XX_CFG_VAL(BTC_EXECUTION_MODE, 2),
+	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_WLAN_LEN, 90000),
+	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_ACTIVE_BT_LEN, 60000),
+	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_WLAN_LEN, 30000),
+	WCN36XX_CFG_VAL(BTC_STATIC_OPP_WLAN_IDLE_BT_LEN, 120000),
+	WCN36XX_CFG_VAL(BTC_FAST_WLAN_CONN_PREF, 1),
+	WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_BT, 120000),
+	WCN36XX_CFG_VAL(BTC_STATIC_LEN_LE_WLAN, 30000),
+	WCN36XX_CFG_VAL(MAX_ASSOC_LIMIT, 10),
+	WCN36XX_CFG_VAL(ENABLE_MCC_ADAPTIVE_SCHEDULER, 0),
+	WCN36XX_CFG_VAL(ENABLE_DYNAMIC_RA_START_RATE, 0), /* Let the firmware handle it */
+	WCN36XX_CFG_VAL(LINK_FAIL_TX_CNT, 1000),
+};
+
 static struct wcn36xx_cfg_val wcn3680_cfg_vals[] = {
 	WCN36XX_CFG_VAL(CURRENT_TX_ANTENNA, 1),
 	WCN36XX_CFG_VAL(CURRENT_RX_ANTENNA, 1),
@@ -632,6 +696,9 @@ int wcn36xx_smd_start(struct wcn36xx *wcn)
 	if (wcn->rf_id == RF_IRIS_WCN3680) {
 		cfg_vals = wcn3680_cfg_vals;
 		cfg_elements = ARRAY_SIZE(wcn3680_cfg_vals);
+	} else if (wcn->rf_id == RF_IRIS_WCN3610) {
+		cfg_vals = wcn3610_cfg_vals;
+		cfg_elements = ARRAY_SIZE(wcn3610_cfg_vals);
 	} else {
 		cfg_vals = wcn36xx_cfg_vals;
 		cfg_elements = ARRAY_SIZE(wcn36xx_cfg_vals);
@@ -2380,7 +2447,8 @@ int wcn36xx_smd_feature_caps_exchange(struct wcn36xx *wcn)
 	mutex_lock(&wcn->hal_mutex);
 	INIT_HAL_MSG(msg_body, WCN36XX_HAL_FEATURE_CAPS_EXCHANGE_REQ);
 
-	wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
+	if (wcn->rf_id != RF_IRIS_WCN3610)
+		wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, STA_POWERSAVE);
 	if (wcn->rf_id == RF_IRIS_WCN3680) {
 		wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, DOT11AC);
 		wcn36xx_firmware_set_feat_caps(msg_body.feat_caps, WLAN_CH144);
diff --git a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
index 7ee79593cd..cb409d48f7 100644
--- a/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
+++ b/drivers/net/wireless/ath/wcn36xx/wcn36xx.h
@@ -96,6 +96,7 @@ enum wcn36xx_ampdu_state {
 #define WCN36XX_MAX_POWER(__wcn) (__wcn->hw->conf.chandef.chan->max_power)
 
 #define RF_UNKNOWN	0x0000
+#define RF_IRIS_WCN3610	0x3610
 #define RF_IRIS_WCN3620	0x3620
 #define RF_IRIS_WCN3660	0x3660
 #define RF_IRIS_WCN3680	0x3680
-- 
2.53.0


^ permalink raw reply related

* Re: 6.18.13 iwlwifi deadlock allocating cma while work-item is active.
From: Tejun Heo @ 2026-03-04 17:14 UTC (permalink / raw)
  To: Ben Greear
  Cc: Johannes Berg, linux-wireless, Korenblit, Miriam Rachel, linux-mm,
	linux-kernel
In-Reply-To: <de003dc3-3e37-f238-4250-2df16eeb77d6@candelatech.com>

Hello,

(Partially drafted with the help of Claude)

On Tue, Mar 03, 2026 at 04:02:14PM -0800, Ben Greear wrote:
> Could the logic that detects blocked work-queues instead be instrumented
> to print out more useful information so that just reproducing the problem
> and providing dmesg output will be sufficient?  Or does dmesg already provide
> enough that would give you a clue as to what is going on?

It may not be exactly the same issue, but Breno just posted a patch that
might help. The current watchdog only prints backtraces for workers that
are actively running on CPU, so sleeping culprits are invisible. His
patch removes that filter so all in-flight workers get printed:

  http://lkml.kernel.org/r/aag4tTyeiZyw0jID@gmail.com

Might be worth trying.

> If I were to attempt to use AI on the coredump, would echoing 'c' to
> /proc/sysrq-trigger with kdump enabled (when deadlock is happening) be
> the appropriate action to grab the core file?

Yes, that's right, but you need to set up kdump first. The quickest way
depends on your distro:

 - Fedora/RHEL: dnf install kexec-tools, then kdumpctl reset-crashkernel,
   systemctl enable --now kdump
 - Ubuntu/Debian: apt install kdump-tools (say Yes to enable), reboot
 - Arch: Install kexec-tools, add crashkernel=512M to your kernel
   cmdline, create a kdump.service that runs
   kexec -p /boot/vmlinuz-linux --initrd=/boot/initramfs-linux.img \
     --append="root=<your-root> irqpoll nr_cpus=1 reset_devices"

After reboot, verify with: cat /sys/kernel/kexec_crash_size (should be
non-zero). Then when the deadlock happens:

  echo c > /proc/sysrq-trigger

The system will panic and boot into the kdump kernel. Note that the
kdump kernel runs with very limited memory, so you can't do much there
directly. Use makedumpfile to save a compressed dump to disk:

  makedumpfile -l -d 31 /proc/vmcore /var/crash/vmcore

Most distros' kdump setups do this automatically. Once the dump is saved,
the system reboots back to normal and you can analyze it at your leisure
with drgn:

  drgn -c /var/crash/vmcore

Thanks.

--
tejun

^ permalink raw reply

* Re: [PATCH wireless-next 33/35] mmc: sdio: add Morse Micro vendor ids
From: Ulf Hansson @ 2026-03-04 16:45 UTC (permalink / raw)
  To: Lachlan Hodges
  Cc: johannes, arien.judge, dan.callaghan, ayman.grais, linux-wireless,
	linux-mmc, linux-kernel
In-Reply-To: <20260227041108.66508-34-lachlan.hodges@morsemicro.com>

On Fri, 27 Feb 2026 at 05:15, Lachlan Hodges
<lachlan.hodges@morsemicro.com> wrote:
>
> Add the Morse Micro mm81x series vendor ids.
>
> Signed-off-by: Lachlan Hodges <lachlan.hodges@morsemicro.com>

I understand that those vendor ids will be used by the sdio func
driver to match against. Although, the way the series is ordered makes
no sense to me. Each patch doesn't compile by itself.

Anyway, feel free to add my ack, once you have sorted out how
re-structure your series.

Acked-by: Ulf Hansson <ulf.hansson@linaro.org>

Kind regards
Uffe


> ---
>  include/linux/mmc/sdio_ids.h | 4 ++++
>  1 file changed, 4 insertions(+)
>
> diff --git a/include/linux/mmc/sdio_ids.h b/include/linux/mmc/sdio_ids.h
> index 673cbdf43453..3ccfe3679c91 100644
> --- a/include/linux/mmc/sdio_ids.h
> +++ b/include/linux/mmc/sdio_ids.h
> @@ -116,6 +116,10 @@
>  #define SDIO_VENDOR_ID_MICROCHIP_WILC          0x0296
>  #define SDIO_DEVICE_ID_MICROCHIP_WILC1000      0x5347
>
> +#define SDIO_VENDOR_ID_MORSEMICRO              0x325B
> +#define SDIO_VENDOR_ID_MORSEMICRO_MM81XB1      0x0709
> +#define SDIO_VENDOR_ID_MORSEMICRO_MM81XB2      0x0809
> +
>  #define SDIO_VENDOR_ID_REALTEK                 0x024c
>  #define SDIO_DEVICE_ID_REALTEK_RTW8723BS       0xb723
>  #define SDIO_DEVICE_ID_REALTEK_RTW8821BS       0xb821
> --
> 2.43.0
>

^ permalink raw reply

* [PATCH wireless-next] wifi: ieee80211: fix UHR operation DBE vs. P-EDCA order
From: Johannes Berg @ 2026-03-04 13:41 UTC (permalink / raw)
  To: linux-wireless; +Cc: Johannes Berg

From: Johannes Berg <johannes.berg@intel.com>

Draft P802.11bn_D1.3 switched the order here to align with
the order of the fields. Adjust the code accordingly.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
---
 include/linux/ieee80211-uhr.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/include/linux/ieee80211-uhr.h b/include/linux/ieee80211-uhr.h
index 9729d23e4766..d199f3ebdba0 100644
--- a/include/linux/ieee80211-uhr.h
+++ b/include/linux/ieee80211-uhr.h
@@ -12,8 +12,8 @@
 
 #define IEEE80211_UHR_OPER_PARAMS_DPS_ENA		0x0001
 #define IEEE80211_UHR_OPER_PARAMS_NPCA_ENA		0x0002
-#define IEEE80211_UHR_OPER_PARAMS_DBE_ENA		0x0004
-#define IEEE80211_UHR_OPER_PARAMS_PEDCA_ENA		0x0008
+#define IEEE80211_UHR_OPER_PARAMS_PEDCA_ENA		0x0004
+#define IEEE80211_UHR_OPER_PARAMS_DBE_ENA		0x0008
 
 struct ieee80211_uhr_operation {
 	__le16 params;
-- 
2.53.0


^ permalink raw reply related

* [PATCH RFC 3/3] net: ath11k: add lockup simulation via debugfs
From: Matthew Leach @ 2026-03-04 12:47 UTC (permalink / raw)
  To: Jeff Johnson; +Cc: linux-wireless, ath11k, linux-kernel, kernel, Matthew Leach
In-Reply-To: <20260304-ath11k-lockup-fixes-v1-0-67143c2fe2a1@collabora.com>

Add a debugfs command to simulate a firmware lockup.

This does not hang the hardware. Instead, it forces the driver down an
error path that reproduces the sequence observed during real lockups:

  ath11k_pci 0000:03:00.0: failed to transmit frame -12
  ath11k_pci 0000:03:00.0: failed to transmit frame -12
  ath11k_pci 0000:03:00.0: failed to transmit frame -12
  ...
  ath11k_pci 0000:03:00.0: wmi command 28680 timeout
  ath11k_pci 0000:03:00.0: failed to submit WMI_MGMT_TX_SEND_CMDID cmd
  ath11k_pci 0000:03:00.0: failed to send mgmt frame: -11

This allows validation of the firmware lockup detection and recovery
mechanism without requiring a real hardware failure.

Signed-off-by: Matthew Leach <matthew.leach@collabora.com>
---
 drivers/net/wireless/ath/ath11k/core.h    | 1 +
 drivers/net/wireless/ath/ath11k/debugfs.c | 7 ++++++-
 drivers/net/wireless/ath/ath11k/hal.c     | 7 +++++--
 drivers/net/wireless/ath/ath11k/htc.c     | 2 +-
 drivers/net/wireless/ath/ath11k/wmi.c     | 6 +++++-
 5 files changed, 18 insertions(+), 5 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index 221dcd23b3dd..44b02ae1e85b 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -1041,6 +1041,7 @@ struct ath11k_base {
 	struct ath11k_dbring_cap *db_caps;
 	u32 num_db_cap;
 	u64 last_frame_tx_error_jiffies;
+	bool simulate_lockup;
 
 	/* To synchronize 11d scan vdev id */
 	struct mutex vdev_id_11d_lock;
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
index 0c1138407838..ca0b72a3e0b0 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
@@ -356,7 +356,8 @@ static ssize_t ath11k_read_simulate_fw_crash(struct file *file,
 	const char buf[] =
 		"To simulate firmware crash write one of the keywords to this file:\n"
 		"`assert` - this will send WMI_FORCE_FW_HANG_CMDID to firmware to cause assert.\n"
-		"`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n";
+		"`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n"
+		"`lockup` - simulate a firmware lockup without the h/w actually hanging.\n";
 
 	return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
 }
@@ -413,6 +414,10 @@ static ssize_t ath11k_write_simulate_fw_crash(struct file *file,
 		ath11k_info(ab, "user requested hw restart\n");
 		queue_work(ab->workqueue_aux, &ab->reset_work);
 		ret = 0;
+	} else if (!strcmp(buf, "lockup")) {
+		ath11k_info(ab, "simulating lockup\n");
+		ab->simulate_lockup = true;
+		ret = 0;
 	} else {
 		ret = -EINVAL;
 		goto exit;
diff --git a/drivers/net/wireless/ath/ath11k/hal.c b/drivers/net/wireless/ath/ath11k/hal.c
index e821e5a62c1c..e01fb17a4734 100644
--- a/drivers/net/wireless/ath/ath11k/hal.c
+++ b/drivers/net/wireless/ath/ath11k/hal.c
@@ -691,7 +691,7 @@ int ath11k_hal_srng_dst_num_free(struct ath11k_base *ab, struct hal_srng *srng,
 
 	tp = srng->u.dst_ring.tp;
 
-	if (sync_hw_ptr) {
+	if (sync_hw_ptr && !ab->simulate_lockup) {
 		hp = *srng->u.dst_ring.hp_addr;
 		srng->u.dst_ring.cached_hp = hp;
 	} else {
@@ -743,7 +743,7 @@ u32 *ath11k_hal_srng_src_get_next_entry(struct ath11k_base *ab,
 	 */
 	next_hp = (srng->u.src_ring.hp + srng->entry_size) % srng->ring_size;
 
-	if (next_hp == srng->u.src_ring.cached_tp)
+	if (next_hp == srng->u.src_ring.cached_tp || ab->simulate_lockup)
 		return NULL;
 
 	desc = srng->ring_base_vaddr + srng->u.src_ring.hp;
@@ -828,6 +828,9 @@ void ath11k_hal_srng_access_begin(struct ath11k_base *ab, struct hal_srng *srng)
 
 	lockdep_assert_held(&srng->lock);
 
+	if (ab->simulate_lockup)
+		return;
+
 	if (srng->ring_dir == HAL_SRNG_DIR_SRC) {
 		srng->u.src_ring.cached_tp =
 			*(volatile u32 *)srng->u.src_ring.tp_addr;
diff --git a/drivers/net/wireless/ath/ath11k/htc.c b/drivers/net/wireless/ath/ath11k/htc.c
index 4571d01cc33d..b05d04a1f5e8 100644
--- a/drivers/net/wireless/ath/ath11k/htc.c
+++ b/drivers/net/wireless/ath/ath11k/htc.c
@@ -208,7 +208,7 @@ static int ath11k_htc_process_trailer(struct ath11k_htc *htc,
 			break;
 		}
 
-		if (ab->hw_params.credit_flow) {
+		if (ab->hw_params.credit_flow && !ab->simulate_lockup) {
 			switch (record->hdr.id) {
 			case ATH11K_HTC_RECORD_CREDITS:
 				len = sizeof(struct ath11k_htc_credit_report);
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 7d9f0bcbb3b0..27d6d4a2f803 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -345,9 +345,13 @@ int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb,
 
 		if (time_in_range64(ab->last_frame_tx_error_jiffies,
 				    range_start, jiffies_64) &&
-		    queue_work(ab->workqueue_aux, &ab->reset_work))
+		    queue_work(ab->workqueue_aux, &ab->reset_work)) {
 			ath11k_err(wmi_ab->ab,
 				   "Firmware lockup detected.  Resetting.");
+
+			/* Assume that reset gets us out of lockup. */
+			ab->simulate_lockup = false;
+		}
 	}
 
 	if (ret == -ENOBUFS)

-- 
2.53.0


^ permalink raw reply related

* [PATCH RFC 2/3] net: ath11k: add firmware lockup detection and recovery
From: Matthew Leach @ 2026-03-04 12:47 UTC (permalink / raw)
  To: Jeff Johnson; +Cc: linux-wireless, ath11k, linux-kernel, kernel, Matthew Leach
In-Reply-To: <20260304-ath11k-lockup-fixes-v1-0-67143c2fe2a1@collabora.com>

Detect firmware lockup when a WMI command times out and TX descriptor
exhaustion occurs within ATH11K_LOCKUP_DESC_ERR_RANGE_HZ (1 minute). In
this case, consider the firmware dead.

When a lockup is detected, queue reset work to restart the chip.
After reset completes, clear the lockup detection state.

Signed-off-by: Matthew Leach <matthew.leach@collabora.com>
---
 drivers/net/wireless/ath/ath11k/core.h |  2 ++
 drivers/net/wireless/ath/ath11k/mac.c  |  6 ++++++
 drivers/net/wireless/ath/ath11k/wmi.c  | 24 +++++++++++++++++++++++-
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index a0d725923ef2..221dcd23b3dd 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -70,6 +70,7 @@ extern bool ath11k_ftm_mode;
 #define ATH11K_RESET_FAIL_TIMEOUT_HZ (20 * HZ)
 #define ATH11K_RECONFIGURE_TIMEOUT_HZ (10 * HZ)
 #define ATH11K_RECOVER_START_TIMEOUT_HZ (20 * HZ)
+#define ATH11K_LOCKUP_DESC_ERR_RANGE_HZ (60 * HZ)
 
 enum ath11k_supported_bw {
 	ATH11K_BW_20	= 0,
@@ -1039,6 +1040,7 @@ struct ath11k_base {
 
 	struct ath11k_dbring_cap *db_caps;
 	u32 num_db_cap;
+	u64 last_frame_tx_error_jiffies;
 
 	/* To synchronize 11d scan vdev id */
 	struct mutex vdev_id_11d_lock;
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 748f779b3d1b..a0b4d60da330 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -9,6 +9,7 @@
 #include <linux/etherdevice.h>
 #include <linux/bitfield.h>
 #include <linux/inetdevice.h>
+#include <linux/jiffies.h>
 #include <net/if_inet6.h>
 #include <net/ipv6.h>
 
@@ -6546,6 +6547,10 @@ static void ath11k_mac_op_tx(struct ieee80211_hw *hw,
 
 	ret = ath11k_dp_tx(ar, arvif, arsta, skb);
 	if (unlikely(ret)) {
+		scoped_guard(spinlock_bh, &ar->ab->base_lock) {
+			ar->ab->last_frame_tx_error_jiffies = jiffies_64;
+		}
+
 		ath11k_warn(ar->ab, "failed to transmit frame %d\n", ret);
 		ieee80211_free_txskb(ar->hw, skb);
 	}
@@ -9281,6 +9286,7 @@ ath11k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
 				atomic_dec(&ab->reset_count);
 				complete(&ab->reset_complete);
 				ab->is_reset = false;
+				ab->last_frame_tx_error_jiffies = 0;
 				atomic_set(&ab->fail_cont_count, 0);
 				ath11k_dbg(ab, ATH11K_DBG_BOOT, "reset success\n");
 			}
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 40747fba3b0c..7d9f0bcbb3b0 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -7,8 +7,11 @@
 #include <linux/ctype.h>
 #include <net/mac80211.h>
 #include <net/cfg80211.h>
+#include <linux/cleanup.h>
 #include <linux/completion.h>
 #include <linux/if_ether.h>
+#include <linux/jiffies.h>
+#include <linux/spinlock.h>
 #include <linux/types.h>
 #include <linux/pci.h>
 #include <linux/uuid.h>
@@ -325,9 +328,28 @@ int ath11k_wmi_cmd_send(struct ath11k_pdev_wmi *wmi, struct sk_buff *skb,
 			}), WMI_SEND_TIMEOUT_HZ);
 	}
 
-	if (ret == -EAGAIN)
+	if (ret == -EAGAIN) {
+		u64 range_start;
+
 		ath11k_warn(wmi_ab->ab, "wmi command %d timeout\n", cmd_id);
 
+		guard(spinlock_bh)(&ab->base_lock);
+
+		if (ab->last_frame_tx_error_jiffies == 0)
+			return ret;
+
+		range_start =
+			(jiffies_64 > ATH11K_LOCKUP_DESC_ERR_RANGE_HZ) ?
+				jiffies_64 - ATH11K_LOCKUP_DESC_ERR_RANGE_HZ :
+				0;
+
+		if (time_in_range64(ab->last_frame_tx_error_jiffies,
+				    range_start, jiffies_64) &&
+		    queue_work(ab->workqueue_aux, &ab->reset_work))
+			ath11k_err(wmi_ab->ab,
+				   "Firmware lockup detected.  Resetting.");
+	}
+
 	if (ret == -ENOBUFS)
 		ath11k_warn(wmi_ab->ab, "ce desc not available for wmi command %d\n",
 			    cmd_id);

-- 
2.53.0


^ permalink raw reply related

* [PATCH RFC 1/3] net: ath11k: fix redundant reset from stale pending workqueue bit
From: Matthew Leach @ 2026-03-04 12:47 UTC (permalink / raw)
  To: Jeff Johnson; +Cc: linux-wireless, ath11k, linux-kernel, kernel, Matthew Leach
In-Reply-To: <20260304-ath11k-lockup-fixes-v1-0-67143c2fe2a1@collabora.com>

During a firmware lockup, WMI commands time out in rapid succession,
each calling queue_work() to schedule ath11k_core_reset().  This can
cause a spurious extra reset after recovery completes:

1. First WMI timeout calls queue_work(), sets the pending bit and
   schedules ath11k_core_reset(). The workqueue clears the pending bit
   before invoking the work function. reset_count becomes 1 and the reset
   is kicked off asynchronously. ath11k_core_reset() returns.

2. Second WMI timeout calls queue_work() and re-queues the work. When it
   runs after step 1 returns, it sees reset_count > 1 and blocks in
   wait_for_completion(). The pending bit is again cleared.

3. Third WMI timeout calls queue_work(), the pending bit was cleared in
   step 2, so this succeeds and arms another execution.

4. The asynchronous reset finishes. ath11k_mac_op_reconfig_complete()
   decrements reset_count and calls complete(). The blocked worker from
   step 2 wakes, takes the early-exit path, and decrements reset_count to
   0.

5. The workqueue sees the pending bit from step 3 and runs
   ath11k_core_reset() again. reset_count is 0, triggering a
   full redundant hardware reset.

Fix this by calling cancel_work() on reset_work in
ath11k_mac_op_reconfig_complete() before signalling completion. This
clears any stale pending bit, preventing the spurious re-execution.

Signed-off-by: Matthew Leach <matthew.leach@collabora.com>
---
 drivers/net/wireless/ath/ath11k/mac.c | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index e4ee2ba1f669..748f779b3d1b 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -9274,6 +9274,10 @@ ath11k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
 			 * the recovery has to be done for each radio
 			 */
 			if (recovery_count == ab->num_radios) {
+				/* Cancel any pending work, preventing a second redudant
+				 * reset.
+				 */
+				cancel_work(&ab->reset_work);
 				atomic_dec(&ab->reset_count);
 				complete(&ab->reset_complete);
 				ab->is_reset = false;

-- 
2.53.0


^ permalink raw reply related

* [PATCH RFC 0/3] net: ath11k: Firmware lockup detection & mitigation
From: Matthew Leach @ 2026-03-04 12:47 UTC (permalink / raw)
  To: Jeff Johnson; +Cc: linux-wireless, ath11k, linux-kernel, kernel, Matthew Leach

When sat idle for approx 24 hours, a user experienced a firmware lockup on a
ath11k chip, resulting in the following log output:

  systemd-timesyncd[558]: Timed out waiting for reply from 23.95.49.216:123 (2.arch.pool.ntp.org).
  systemd-timesyncd[558]: Timed out waiting for reply from 23.186.168.125:123 (2.arch.pool.ntp.org).
  systemd-timesyncd[558]: Timed out waiting for reply from 64.79.100.197:123 (2.arch.pool.ntp.org).
  systemd-timesyncd[558]: Timed out waiting for reply from 69.89.207.199:123 (2.arch.pool.ntp.org).
  kernel: ath11k_pci 0000:03:00.0: failed to transmit frame -12
  kernel: ath11k_pci 0000:03:00.0: failed to transmit frame -12
  kernel: ath11k_pci 0000:03:00.0: failed to transmit frame -12

  [...]

  kernel: ath11k_pci 0000:03:00.0: failed to flush transmit queue, data pkts pending 564
  kernel: ath11k_pci 0000:03:00.0: wmi command 20486 timeout
  kernel: ath11k_pci 0000:03:00.0: failed to submit WMI_VDEV_STOP cmd
  kernel: ath11k_pci 0000:03:00.0: failed to stop WMI vdev 0: -11
  kernel: ath11k_pci 0000:03:00.0: failed to stop vdev 0: -11
  kernel: ath11k_pci 0000:03:00.0: failed to do early vdev stop: -11
  kernel: ath11k_pci 0000:03:00.0: Failed to remove station: xx:xx:xx:xx:xx:xx for VDEV: 0
  kernel: ath11k_pci 0000:03:00.0: Found peer entry xx:xx:xx:xx:xx:xx n vdev 0 after it was supposedly removed
  kernel: ------------[ cut here ]------------
  kernel: WARNING: CPU: 0 PID: 1229 at net/mac80211/sta_info.c:1490 __sta_info_destroy_part2+0x14e/0x180 [mac80211]

This patch series:

 - Fixes a bug in the core reset logic which could cause a second redundant reset
   after the original reset completes.
 - Implements the error correlation logic and queues a chip reset when detected.
 - Adds a simulation to the simulate_fw_crash debugfs file to test the
   detection logic.

Signed-off-by: Matthew Leach <matthew.leach@collabora.com>
---
Matthew Leach (3):
      net: ath11k: fix redundant reset from stale pending workqueue bit
      net: ath11k: add firmware lockup detection and recovery
      net: ath11k: add lockup simulation via debugfs

 drivers/net/wireless/ath/ath11k/core.h    |  3 +++
 drivers/net/wireless/ath/ath11k/debugfs.c |  7 ++++++-
 drivers/net/wireless/ath/ath11k/hal.c     |  7 +++++--
 drivers/net/wireless/ath/ath11k/htc.c     |  2 +-
 drivers/net/wireless/ath/ath11k/mac.c     | 10 ++++++++++
 drivers/net/wireless/ath/ath11k/wmi.c     | 28 +++++++++++++++++++++++++++-
 6 files changed, 52 insertions(+), 5 deletions(-)
---
base-commit: 11439c4635edd669ae435eec308f4ab8a0804808
change-id: 20260304-ath11k-lockup-fixes-b808b5c7318b

Best regards,
-- 
Matthew Leach <matthew.leach@collabora.com>


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox