| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/25 19:05 | flow | patch-triage |
3mArgs:null Results: {
"EnableConfigs": [
"MT7663U",
"MT7921U",
"MT7925U"
],
"FocusSymbols": [
"mt7663_usb_sdio_tx_prepare_skb",
"mt76_connac2_mac_fill_rx_rate",
"mt76_connac_mcu_sta_tlv",
"mt76_dma_rx_poll",
"mt76_abort_scan",
"mt76_scan_work"
],
"Reasoning": "The patch modifies the MediaTek mt76 wireless driver, including core DMA, MAC, MCU, and scanning logic, as well as specific drivers like mt7615, mt7915, and mt7996. While mt7915 and mt7996 are PCIe-only and not reachable in standard QEMU, the mt76 core and mt7615 driver have USB support (e.g., MT7663U, MT7921U, MT7925U) which can be fuzzed via USB emulation (dummy_hcd). The changes include functional modifications to RX rate reporting, STA HE TLV parsing, DMA buffer handling, and scan channel locking, all of which are reachable via the USB driver paths.",
"WorthFuzzing": true
} |
| 1/1 | 2026/07/25 19:05 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit d52f0f64e49b482c9aa9daefd7de92560bde4bee\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Sat Jul 25 19:05:37 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c\nindex f8c2fe5f2f5877..acb18c237b0a4f 100644\n--- a/drivers/net/wireless/mediatek/mt76/dma.c\n+++ b/drivers/net/wireless/mediatek/mt76/dma.c\n@@ -534,8 +534,13 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,\n \t\tt-\u003eptr = NULL;\n \n \t\tmt76_put_rxwi(dev, t);\n-\t\tif (drop)\n+#ifdef CONFIG_NET_MEDIATEK_SOC_WED\n+\t\t/* the WO MCU owns the RX path only on WED v2, on newer\n+\t\t * versions this buf1 bit carries no drop information\n+\t\t */\n+\t\tif (drop \u0026\u0026 dev-\u003emmio.wed.version == 2)\n \t\t\t*drop |= !!(buf1 \u0026 MT_DMA_CTL_WO_DROP);\n+#endif\n \t} else {\n \t\tdma_sync_single_for_cpu(dev-\u003edma_dev, e-\u003edma_addr[0],\n \t\t\t\tSKB_WITH_OVERHEAD(q-\u003ebuf_size),\ndiff --git a/drivers/net/wireless/mediatek/mt76/dma.h b/drivers/net/wireless/mediatek/mt76/dma.h\nindex 2a0226c83f3c92..ffd81bb946134c 100644\n--- a/drivers/net/wireless/mediatek/mt76/dma.h\n+++ b/drivers/net/wireless/mediatek/mt76/dma.h\n@@ -5,6 +5,8 @@\n #ifndef __MT76_DMA_H\n #define __MT76_DMA_H\n \n+#include \u003clinux/regmap.h\u003e\n+\n #define DMA_DUMMY_DATA\t\t\t((void *)~0)\n \n #define MT_RING_SIZE\t\t\t0x10\n@@ -46,73 +48,75 @@\n #define MT_FCE_INFO_LEN\t\t\t4\n #define MT_RX_RXWI_LEN\t\t\t32\n \n+static inline bool\n+mt76_dma_handle_read(struct mt76_queue *q, u32 offset, u32 *val)\n+{\n #if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)\n+\tif (q-\u003eflags \u0026 MT_QFLAG_WED) {\n+\t\t*val = mtk_wed_device_reg_read(q-\u003ewed, q-\u003ewed_regs + offset);\n \n-#define Q_READ(_q, _field) ({\t\t\t\t\t\t\\\n-\tu32 _offset = offsetof(struct mt76_queue_regs, _field);\t\t\\\n-\tu32 _val;\t\t\t\t\t\t\t\\\n-\tif ((_q)-\u003eflags \u0026 MT_QFLAG_WED)\t\t\t\t\t\\\n-\t\t_val = mtk_wed_device_reg_read((_q)-\u003ewed,\t\t\\\n-\t\t\t\t\t ((_q)-\u003ewed_regs +\t\\\n-\t\t\t\t\t\t_offset));\t\t\\\n-\telse\t\t\t\t\t\t\t\t\\\n-\t\t_val = readl(\u0026(_q)-\u003eregs-\u003e_field);\t\t\t\\\n-\t_val;\t\t\t\t\t\t\t\t\\\n-})\n+\t\treturn true;\n+\t}\n+#endif\n+#if IS_ENABLED(CONFIG_MT76_NPU)\n+\tif (q-\u003eflags \u0026 MT_QFLAG_NPU) {\n+\t\tstruct airoha_npu *npu;\n+\n+\t\t*val = 0;\n+\t\trcu_read_lock();\n+\t\tnpu = rcu_dereference(q-\u003edev-\u003emmio.npu);\n+\t\tif (npu)\n+\t\t\tregmap_read(npu-\u003eregmap, q-\u003ewed_regs + offset, val);\n+\t\trcu_read_unlock();\n+\n+\t\treturn true;\n+\t}\n+#endif\n \n-#define Q_WRITE(_q, _field, _val)\tdo {\t\t\t\t\\\n-\tu32 _offset = offsetof(struct mt76_queue_regs, _field);\t\t\\\n-\tif ((_q)-\u003eflags \u0026 MT_QFLAG_WED)\t\t\t\t\t\\\n-\t\tmtk_wed_device_reg_write((_q)-\u003ewed,\t\t\t\\\n-\t\t\t\t\t ((_q)-\u003ewed_regs + _offset),\t\\\n-\t\t\t\t\t _val);\t\t\t\t\\\n-\telse\t\t\t\t\t\t\t\t\\\n-\t\twritel(_val, \u0026(_q)-\u003eregs-\u003e_field);\t\t\t\\\n-} while (0)\n+\treturn false;\n+}\n \n-#elif IS_ENABLED(CONFIG_MT76_NPU)\n+static inline bool\n+mt76_dma_handle_write(struct mt76_queue *q, u32 offset, u32 val)\n+{\n+#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)\n+\tif (q-\u003eflags \u0026 MT_QFLAG_WED) {\n+\t\tmtk_wed_device_reg_write(q-\u003ewed, q-\u003ewed_regs + offset, val);\n+\n+\t\treturn true;\n+\t}\n+#endif\n+#if IS_ENABLED(CONFIG_MT76_NPU)\n+\tif (q-\u003eflags \u0026 MT_QFLAG_NPU) {\n+\t\tstruct airoha_npu *npu;\n+\n+\t\trcu_read_lock();\n+\t\tnpu = rcu_dereference(q-\u003edev-\u003emmio.npu);\n+\t\tif (npu)\n+\t\t\tregmap_write(npu-\u003eregmap, q-\u003ewed_regs + offset, val);\n+\t\trcu_read_unlock();\n+\n+\t\treturn true;\n+\t}\n+#endif\n+\n+\treturn false;\n+}\n \n #define Q_READ(_q, _field) ({\t\t\t\t\t\t\\\n \tu32 _offset = offsetof(struct mt76_queue_regs, _field);\t\t\\\n-\tu32 _val = 0;\t\t\t\t\t\t\t\\\n-\tif ((_q)-\u003eflags \u0026 MT_QFLAG_NPU) {\t\t\t\t\\\n-\t\tstruct airoha_npu *npu;\t\t\t\t\t\\\n-\t\t\t\t\t\t\t\t\t\\\n-\t\trcu_read_lock();\t\t\t\t\t\\\n-\t\tnpu = rcu_dereference(q-\u003edev-\u003emmio.npu);\t\t\\\n-\t\tif (npu)\t\t\t\t\t\t\\\n-\t\t\tregmap_read(npu-\u003eregmap,\t\t\t\\\n-\t\t\t\t ((_q)-\u003ewed_regs + _offset), \u0026_val);\t\\\n-\t\trcu_read_unlock();\t\t\t\t\t\\\n-\t} else {\t\t\t\t\t\t\t\\\n+\tu32 _val;\t\t\t\t\t\t\t\\\n+\tif (!mt76_dma_handle_read(_q, _offset, \u0026_val))\t\t\t\\\n \t\t_val = readl(\u0026(_q)-\u003eregs-\u003e_field);\t\t\t\\\n-\t}\t\t\t\t\t\t\t\t\\\n \t_val;\t\t\t\t\t\t\t\t\\\n })\n \n #define Q_WRITE(_q, _field, _val)\tdo {\t\t\t\t\\\n \tu32 _offset = offsetof(struct mt76_queue_regs, _field);\t\t\\\n-\tif ((_q)-\u003eflags \u0026 MT_QFLAG_NPU) {\t\t\t\t\\\n-\t\tstruct airoha_npu *npu;\t\t\t\t\t\\\n-\t\t\t\t\t\t\t\t\t\\\n-\t\trcu_read_lock();\t\t\t\t\t\\\n-\t\tnpu = rcu_dereference(q-\u003edev-\u003emmio.npu);\t\t\\\n-\t\tif (npu)\t\t\t\t\t\t\\\n-\t\t\tregmap_write(npu-\u003eregmap,\t\t\t\\\n-\t\t\t\t ((_q)-\u003ewed_regs + _offset), _val);\t\\\n-\t\trcu_read_unlock();\t\t\t\t\t\\\n-\t} else {\t\t\t\t\t\t\t\\\n+\tif (!mt76_dma_handle_write(_q, _offset, _val))\t\t\t\\\n \t\twritel(_val, \u0026(_q)-\u003eregs-\u003e_field);\t\t\t\\\n-\t}\t\t\t\t\t\t\t\t\\\n } while (0)\n \n-#else\n-\n-#define Q_READ(_q, _field)\t\treadl(\u0026(_q)-\u003eregs-\u003e_field)\n-#define Q_WRITE(_q, _field, _val)\twritel(_val, \u0026(_q)-\u003eregs-\u003e_field)\n-\n-#endif\n-\n struct mt76_desc {\n \t__le32 buf0;\n \t__le32 ctrl;\ndiff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c\nindex 05d74cd7248e97..73d47608bf428d 100644\n--- a/drivers/net/wireless/mediatek/mt76/mmio.c\n+++ b/drivers/net/wireless/mediatek/mt76/mmio.c\n@@ -35,9 +35,16 @@ static void mt76_mmio_write_copy(struct mt76_dev *dev, u32 offset,\n {\n \tint i;\n \n-\tfor (i = 0; i \u003c ALIGN(len, 4); i += 4)\n+\tfor (i = 0; i + 4 \u003c= len; i += 4)\n \t\twritel(get_unaligned_le32(data + i),\n \t\t dev-\u003emmio.regs + offset + i);\n+\n+\tif (i \u003c len) {\n+\t\tu8 tmp[4] = {};\n+\n+\t\tmemcpy(tmp, data + i, len - i);\n+\t\twritel(get_unaligned_le32(tmp), dev-\u003emmio.regs + offset + i);\n+\t}\n }\n \n static void mt76_mmio_read_copy(struct mt76_dev *dev, u32 offset,\n@@ -45,9 +52,16 @@ static void mt76_mmio_read_copy(struct mt76_dev *dev, u32 offset,\n {\n \tint i;\n \n-\tfor (i = 0; i \u003c ALIGN(len, 4); i += 4)\n+\tfor (i = 0; i + 4 \u003c= len; i += 4)\n \t\tput_unaligned_le32(readl(dev-\u003emmio.regs + offset + i),\n \t\t\t\t data + i);\n+\n+\tif (i \u003c len) {\n+\t\tu8 tmp[4];\n+\n+\t\tput_unaligned_le32(readl(dev-\u003emmio.regs + offset + i), tmp);\n+\t\tmemcpy(data + i, tmp, len - i);\n+\t}\n }\n \n static int mt76_mmio_wr_rp(struct mt76_dev *dev, u32 base,\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c\nindex 53cb1eed1e4fb3..0aca590f2bae5d 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c\n+++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c\n@@ -68,10 +68,11 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,\n \tint pid, id;\n \tu8 *txwi = (u8 *)txwi_ptr;\n \tstruct mt76_txwi_cache *t;\n-\tstruct mt7615_sta *msta;\n+\tstruct mt7615_sta *msta = NULL;\n \tvoid *txp;\n \n-\tmsta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL;\n+\tif (wcid \u0026\u0026 wcid-\u003esta)\n+\t\tmsta = container_of(wcid, struct mt7615_sta, wcid);\n \tif (!wcid)\n \t\twcid = \u0026dev-\u003emt76.global_wcid;\n \ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c\nindex f4169de939c487..9525d8062b4439 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c\n+++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c\n@@ -187,10 +187,11 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,\n \tstruct sk_buff *skb = tx_info-\u003eskb;\n \tstruct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);\n \tstruct ieee80211_key_conf *key = info-\u003econtrol.hw_key;\n-\tstruct mt7615_sta *msta;\n+\tstruct mt7615_sta *msta = NULL;\n \tint pad, err, pktid;\n \n-\tmsta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL;\n+\tif (wcid \u0026\u0026 wcid-\u003esta)\n+\t\tmsta = container_of(wcid, struct mt7615_sta, wcid);\n \tif (!wcid)\n \t\twcid = \u0026dev-\u003emt76.global_wcid;\n \ndiff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c\nindex fc9f782032ef2b..976043521f44ff 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c\n+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c\n@@ -1069,6 +1069,10 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,\n \t\tbw = FIELD_GET(MT_CRXV_FRAME_MODE, v2);\n \t}\n \n+\t/* the hardware reports NSTS; report the data NSS for STBC frames */\n+\tif (stbc \u0026\u0026 nss \u003e 1)\n+\t\tnss \u003e\u003e= 1;\n+\n \tswitch (*mode) {\n \tcase MT_PHY_TYPE_CCK:\n \t\tcck = true;\n@@ -1114,7 +1118,7 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,\n \tcase IEEE80211_STA_RX_BW_20:\n \t\tbreak;\n \tcase IEEE80211_STA_RX_BW_40:\n-\t\tif (*mode \u0026 MT_PHY_TYPE_HE_EXT_SU \u0026\u0026\n+\t\tif (*mode == MT_PHY_TYPE_HE_EXT_SU \u0026\u0026\n \t\t (idx \u0026 MT_PRXV_TX_ER_SU_106T)) {\n \t\t\tstatus-\u003ebw = RATE_INFO_BW_HE_RU;\n \t\t\tstatus-\u003ehe_ru =\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c\nindex 6596c9e198f425..f002ad5ec19d4c 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c\n+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c\n@@ -753,7 +753,7 @@ mt76_connac_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)\n \t\tHE_PHY(CAP3_DCM_MAX_CONST_RX_MASK, elem-\u003ephy_cap_info[3]);\n \the-\u003edcm_rx_max_nss =\n \t\tHE_PHY(CAP3_DCM_MAX_RX_NSS_2, elem-\u003ephy_cap_info[3]);\n-\the-\u003edcm_rx_max_nss =\n+\the-\u003edcm_max_ru =\n \t\tHE_PHY(CAP8_DCM_MAX_RU_MASK, elem-\u003ephy_cap_info[8]);\n \n \the-\u003epkt_ext = 2;\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h\nindex 78f633ad81a076..55b1befa42ee41 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h\n+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h\n@@ -842,6 +842,7 @@ enum {\n \tSTA_REC_HDRT = 0x28,\n \tSTA_REC_EML_OP = 0x29,\n \tSTA_REC_HDR_TRANS = 0x2B,\n+\tSTA_REC_PS_LEAVE = 0x45,\n \tSTA_REC_MAX_NUM\n };\n \ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c\nindex 250c2d2479b0c6..a4ca8a46b73d59 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c\n+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c\n@@ -1295,6 +1295,8 @@ int mt7915_register_device(struct mt7915_dev *dev)\n void mt7915_unregister_device(struct mt7915_dev *dev)\n {\n \tcancel_work_sync(\u0026dev-\u003edump_work);\n+\tcancel_work_sync(\u0026dev-\u003ereset_work);\n+\tcancel_work_sync(\u0026dev-\u003erc_work);\n \tmt7915_unregister_ext_phy(dev);\n \tmt7915_coredump_unregister(dev);\n \tmt7915_unregister_thermal(\u0026dev-\u003ephy);\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c\nindex 334c19ab2b22ca..1fc7efcce273b4 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c\n+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c\n@@ -1464,6 +1464,10 @@ mt7915_mac_full_reset(struct mt7915_dev *dev)\n \n \tmutex_unlock(\u0026dev-\u003emt76.mutex);\n \n+\tieee80211_wake_queues(mt76_hw(dev));\n+\tif (ext_phy)\n+\t\tieee80211_wake_queues(ext_phy-\u003ehw);\n+\n \tieee80211_restart_hw(mt76_hw(dev));\n \tif (ext_phy)\n \t\tieee80211_restart_hw(ext_phy-\u003ehw);\n@@ -1925,7 +1929,7 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy)\n static void mt7915_mac_severe_check(struct mt7915_phy *phy)\n {\n \tstruct mt7915_dev *dev = phy-\u003edev;\n-\tu32 trb;\n+\tu32 trb, ple_err;\n \n \tif (!phy-\u003eomac_mask)\n \t\treturn;\n@@ -1945,6 +1949,17 @@ static void mt7915_mac_severe_check(struct mt7915_phy *phy)\n \t\t\t\t phy-\u003emt76-\u003eband_idx);\n \n \tphy-\u003etrb_ts = trb;\n+\n+\tple_err = mt76_rr(dev, MT_SWDEF_PLE1_STATS);\n+\tif ((ple_err \u0026 MT_SWDEF_PLE1_MDP_RIOC_HANG_ERR) \u0026\u0026\n+\t !(dev-\u003eple1_sts \u0026 MT_SWDEF_PLE1_MDP_RIOC_HANG_ERR)) {\n+\t\tdev_warn(dev-\u003emt76.dev,\n+\t\t\t \"band%d: PLE error 0x%x detected, triggering L1 SER\\n\",\n+\t\t\t phy-\u003emt76-\u003eband_idx, ple_err);\n+\t\tmt7915_mcu_set_ser(dev, SER_RECOVER, SER_SET_RECOVER_L1,\n+\t\t\t\t phy-\u003emt76-\u003eband_idx);\n+\t}\n+\tdev-\u003eple1_sts = ple_err;\n }\n \n void mt7915_mac_sta_rc_work(struct work_struct *work)\n@@ -2345,8 +2360,10 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw,\n \t}\n \tflow-\u003etsf = le64_to_cpu(twt_agrt-\u003etwt);\n \n-\tif (mt7915_mcu_twt_agrt_update(dev, msta-\u003evif, flow, MCU_TWT_AGRT_ADD))\n+\tif (mt7915_mcu_twt_agrt_update(dev, msta-\u003evif, flow, MCU_TWT_AGRT_ADD)) {\n+\t\tlist_del(\u0026flow-\u003elist);\n \t\tgoto unlock;\n+\t}\n \n \tsetup_cmd = TWT_SETUP_CMD_ACCEPT;\n \tdev-\u003etwt.table_mask |= BIT(table_id);\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c\nindex 51643a48ed1515..8fa5022b79af2b 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c\n+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c\n@@ -249,7 +249,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,\n \tidx = mt76_wcid_alloc(dev-\u003emt76.wcid_mask, mt7915_wtbl_size(dev));\n \tif (idx \u003c 0) {\n \t\tret = -ENOSPC;\n-\t\tgoto out;\n+\t\tgoto err;\n \t}\n \n \tINIT_LIST_HEAD(\u0026mvif-\u003esta.rc_list);\n@@ -277,7 +277,17 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,\n \tmt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, true);\n \trcu_assign_pointer(dev-\u003emt76.wcid[idx], \u0026mvif-\u003esta.wcid);\n \n+\tmutex_unlock(\u0026dev-\u003emt76.mutex);\n+\n+\treturn 0;\n+\n+err:\n+\tdev-\u003emt76.vif_mask \u0026= ~BIT_ULL(mvif-\u003emt76.idx);\n+\tphy-\u003eomac_mask \u0026= ~BIT_ULL(mvif-\u003emt76.omac_idx);\n+\tmt7915_mcu_add_dev_info(phy, vif, false);\n out:\n+\tif (phy-\u003emonitor_vif == vif)\n+\t\tphy-\u003emonitor_vif = NULL;\n \tmutex_unlock(\u0026dev-\u003emt76.mutex);\n \n \treturn ret;\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c\nindex 4a381d351e6154..4760d725e1f739 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c\n+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c\n@@ -576,9 +576,9 @@ mt7915_mcu_bss_ra_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,\n \tra-\u003erx_streams = max_nss;\n \tra-\u003ealgo = 4;\n \tra-\u003etrain_up_rule = 2;\n-\tra-\u003etrain_up_high_thres = 110;\n-\tra-\u003etrain_up_rule_rssi = -70;\n-\tra-\u003elow_traffic_thres = 2;\n+\tra-\u003etrain_up_high_thres = cpu_to_le16(110);\n+\tra-\u003etrain_up_rule_rssi = cpu_to_le16(-70);\n+\tra-\u003elow_traffic_thres = cpu_to_le16(2);\n \tra-\u003ephy_cap = cpu_to_le32(0xfdf);\n \tra-\u003einterval = cpu_to_le32(500);\n \tra-\u003efast_interval = cpu_to_le32(100);\n@@ -900,7 +900,7 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,\n \t\tHE_PHY(CAP3_DCM_MAX_CONST_RX_MASK, elem-\u003ephy_cap_info[3]);\n \the-\u003edcm_rx_max_nss =\n \t\tHE_PHY(CAP3_DCM_MAX_RX_NSS_2, elem-\u003ephy_cap_info[3]);\n-\the-\u003edcm_rx_max_nss =\n+\the-\u003edcm_max_ru =\n \t\tHE_PHY(CAP8_DCM_MAX_RU_MASK, elem-\u003ephy_cap_info[8]);\n \n \the-\u003epkt_ext = 2;\n@@ -1617,7 +1617,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,\n \t\t\tcap |= STA_CAP_VHT_SGI_160;\n \t\tif (sta-\u003edeflink.vht_cap.cap \u0026 IEEE80211_VHT_CAP_TXSTBC)\n \t\t\tcap |= STA_CAP_VHT_TX_STBC;\n-\t\tif (sta-\u003edeflink.vht_cap.cap \u0026 IEEE80211_VHT_CAP_RXSTBC_1)\n+\t\tif (sta-\u003edeflink.vht_cap.cap \u0026 IEEE80211_VHT_CAP_RXSTBC_MASK)\n \t\t\tcap |= STA_CAP_VHT_RX_STBC;\n \t\tif (mvif-\u003ecap.vht_ldpc \u0026\u0026\n \t\t (sta-\u003edeflink.vht_cap.cap \u0026 IEEE80211_VHT_CAP_RXLDPC))\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h\nindex 22f73a5ed42590..7c472062a90e1c 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h\n+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h\n@@ -318,9 +318,9 @@ struct bss_info_ra {\n \tu8 antenna_idx;\n \tu8 train_up_rule;\n \tu8 rsv[3];\n-\tunsigned short train_up_high_thres;\n-\tshort train_up_rule_rssi;\n-\tunsigned short low_traffic_thres;\n+\t__le16 train_up_high_thres;\n+\t__le16 train_up_rule_rssi;\n+\t__le16 low_traffic_thres;\n \t__le16 max_phyrate;\n \t__le32 phy_cap;\n \t__le32 interval;\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h\nindex bf1d915a3ca238..44253196749fea 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h\n+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h\n@@ -295,6 +295,7 @@ struct mt7915_dev {\n \tspinlock_t reg_lock;\n \n \tu32 hw_pattern;\n+\tu32 ple1_sts;\n \n \tbool dbdc_support;\n \tbool flash_mode;\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h\nindex 307bf6a7567495..dc7bb9a1f223e9 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h\n+++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h\n@@ -1044,6 +1044,7 @@ enum offs_rev {\n #define MT_SWDEF_SER_STATS\t\tMT_SWDEF(0x040)\n #define MT_SWDEF_PLE_STATS\t\tMT_SWDEF(0x044)\n #define MT_SWDEF_PLE1_STATS\t\tMT_SWDEF(0x048)\n+#define MT_SWDEF_PLE1_MDP_RIOC_HANG_ERR\tBIT(3)\n #define MT_SWDEF_PLE_AMSDU_STATS\tMT_SWDEF(0x04C)\n #define MT_SWDEF_PSE_STATS\t\tMT_SWDEF(0x050)\n #define MT_SWDEF_PSE1_STATS\t\tMT_SWDEF(0x054)\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c\nindex d6f9aa1ab52d12..7415fb595b586f 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c\n+++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c\n@@ -559,6 +559,9 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band)\n {\n \tu32 mask, set;\n \n+\tif (!mt7996_band_valid(dev, band))\n+\t\treturn;\n+\n \t/* clear estimated value of EIFS for Rx duration \u0026 OBSS time */\n \tmt76_wr(dev, MT_WF_RMAC_RSVD0(band), MT_WF_RMAC_RSVD0_EIFS_CLR);\n \n@@ -590,6 +593,9 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band)\n \t * MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set.\n \t */\n \tmt76_set(dev, MT_AGG_ACR4(band), MT_AGG_ACR_PPDU_TXS2H);\n+\n+\tif (!is_mt7996(\u0026dev-\u003emt76))\n+\t\tmt7996_mcu_set_bssid_mapping_addr(\u0026dev-\u003emt76, band);\n }\n \n static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)\n@@ -1799,6 +1805,8 @@ void mt7996_unregister_device(struct mt7996_dev *dev)\n {\n \tcancel_work_sync(\u0026dev-\u003edump_work);\n \tcancel_work_sync(\u0026dev-\u003ewed_rro.work);\n+\tcancel_work_sync(\u0026dev-\u003ereset_work);\n+\tcancel_work_sync(\u0026dev-\u003erc_work);\n \tmt7996_unregister_phy(mt7996_phy3(dev));\n \tmt7996_unregister_phy(mt7996_phy2(dev));\n \tmt7996_unregister_thermal(\u0026dev-\u003ephy);\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c\nindex 0eebc8182ca9aa..9583870628b45c 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c\n+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c\n@@ -294,6 +294,10 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,\n \tdcm = FIELD_GET(MT_PRXV_DCM, v2);\n \tbw = FIELD_GET(MT_PRXV_FRAME_MODE, v2);\n \n+\t/* the hardware reports NSTS; report the data NSS for STBC frames */\n+\tif (stbc \u0026\u0026 nss \u003e 1)\n+\t\tnss \u003e\u003e= 1;\n+\n \tswitch (*mode) {\n \tcase MT_PHY_TYPE_CCK:\n \t\tcck = true;\n@@ -349,7 +353,7 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,\n \tcase IEEE80211_STA_RX_BW_20:\n \t\tbreak;\n \tcase IEEE80211_STA_RX_BW_40:\n-\t\tif (*mode \u0026 MT_PHY_TYPE_HE_EXT_SU \u0026\u0026\n+\t\tif (*mode == MT_PHY_TYPE_HE_EXT_SU \u0026\u0026\n \t\t (idx \u0026 MT_PRXV_TX_ER_SU_106T)) {\n \t\t\tstatus-\u003ebw = RATE_INFO_BW_HE_RU;\n \t\t\tstatus-\u003ehe_ru =\n@@ -2383,6 +2387,7 @@ mt7996_mac_reset_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)\n \t\trcu_assign_pointer(mvif-\u003elink[i], NULL);\n \t\tkfree_rcu(mlink, rcu_head);\n \t}\n+\tmvif-\u003evalid_links = 0;\n \trcu_read_unlock();\n }\n \n@@ -2416,12 +2421,14 @@ mt7996_mac_full_reset(struct mt7996_dev *dev)\n \n \tmt7996_for_each_phy(dev, phy)\n \t\tphy-\u003eomac_mask = 0;\n+\tdev-\u003emld_idx_mask = 0;\n+\tdev-\u003emld_remap_idx_mask = 0;\n \n \tieee80211_iterate_stations_atomic(hw, mt7996_mac_reset_sta_iter, dev);\n+\tmt76_reset_device(\u0026dev-\u003emt76);\n \tieee80211_iterate_active_interfaces_atomic(hw,\n \t\t\t\t\t\t IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER,\n \t\t\t\t\t\t mt7996_mac_reset_vif_iter, dev);\n-\tmt76_reset_device(\u0026dev-\u003emt76);\n \n \tINIT_LIST_HEAD(\u0026dev-\u003esta_rc_list);\n \tINIT_LIST_HEAD(\u0026dev-\u003etwt_list);\n@@ -2445,6 +2452,8 @@ mt7996_mac_full_reset(struct mt7996_dev *dev)\n \n \tmutex_unlock(\u0026dev-\u003emt76.mutex);\n \n+\tieee80211_wake_queues(mt76_hw(dev));\n+\n \tieee80211_restart_hw(mt76_hw(dev));\n }\n \n@@ -2500,8 +2509,8 @@ void mt7996_mac_reset_work(struct work_struct *work)\n \n \tset_bit(MT76_RESET, \u0026dev-\u003emphy.state);\n \tset_bit(MT76_MCU_RESET, \u0026dev-\u003emphy.state);\n-\tmt76_abort_scan(\u0026dev-\u003emt76);\n \twake_up(\u0026dev-\u003emt76.mcu.wait);\n+\tmt76_abort_scan(\u0026dev-\u003emt76);\n \n \tcancel_work_sync(\u0026dev-\u003ewed_rro.work);\n \tmt7996_for_each_phy(dev, phy) {\n@@ -2510,6 +2519,8 @@ void mt7996_mac_reset_work(struct work_struct *work)\n \t\tcancel_delayed_work_sync(\u0026phy-\u003emt76-\u003emac_work);\n \t}\n \n+\tmutex_lock(\u0026dev-\u003emt76.mutex);\n+\n \tmt76_worker_disable(\u0026dev-\u003emt76.tx_worker);\n \tmt76_for_each_q_rx(\u0026dev-\u003emt76, i) {\n \t\tif (mtk_wed_device_active(\u0026dev-\u003emt76.mmio.wed) \u0026\u0026\n@@ -2527,8 +2538,6 @@ void mt7996_mac_reset_work(struct work_struct *work)\n \t}\n \tnapi_disable(\u0026dev-\u003emt76.tx_napi);\n \n-\tmutex_lock(\u0026dev-\u003emt76.mutex);\n-\n \tmt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);\n \n \tif (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c\nindex afbcc8c7b18b2f..bd624c2eaf857b 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c\n+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c\n@@ -372,7 +372,8 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,\n \t\t\t\t CONN_STATE_PORT_SECURE, true);\n \trcu_assign_pointer(dev-\u003emt76.wcid[idx], \u0026msta_link-\u003ewcid);\n \n-\tieee80211_iter_keys(mphy-\u003ehw, vif, mt7996_key_iter, \u0026it);\n+\tif (!mlink-\u003ewcid-\u003eoffchannel)\n+\t\tieee80211_iter_keys(mphy-\u003ehw, vif, mt7996_key_iter, \u0026it);\n \n \tif (!mlink-\u003ewcid-\u003eoffchannel) {\n \t\tif (vif-\u003etxq \u0026\u0026\n@@ -605,6 +606,8 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,\n \tunsigned int link_id;\n \tint i;\n \n+\tmutex_lock(\u0026dev-\u003emt76.mutex);\n+\n \t/* Remove all active links */\n \tfor_each_set_bit(link_id, \u0026rem_links, IEEE80211_MLD_MAX_NUM_LINKS) {\n \t\tstruct mt7996_vif_link *link;\n@@ -621,6 +624,8 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,\n \t\tmt7996_vif_link_destroy(phy, link, vif, NULL);\n \t}\n \n+\tmutex_unlock(\u0026dev-\u003emt76.mutex);\n+\n \tieee80211_iterate_active_interfaces_mtx(hw, 0, mt7996_remove_iter,\n \t\t\t\t\t\t\u0026rdata);\n \tmt76_vif_cleanup(\u0026dev-\u003emt76, vif);\n@@ -2069,6 +2074,14 @@ static void mt7996_sta_set_decap_offload(struct ieee80211_hw *hw,\n \t\t\tcontinue;\n \n \t\tmt7996_mcu_wtbl_update_hdr_trans(dev, vif, link, msta_link);\n+\n+\t\t/* HW cannot derive the BSSID from 4-address non-AMSDU frames,\n+\t\t * so PS exit is missed on links other than the setup link.\n+\t\t * Let the firmware wake those links instead.\n+\t\t */\n+\t\tif (enabled \u0026\u0026 msta-\u003edeflink_id != link_id \u0026\u0026\n+\t\t is_mt7996(\u0026dev-\u003emt76))\n+\t\t\tmt7996_mcu_ps_leave(dev, link, msta_link);\n \t}\n \n \tmutex_unlock(\u0026dev-\u003emt76.mutex);\n@@ -2436,6 +2449,23 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,\n \treturn 0;\n }\n \n+#if defined(CONFIG_NET_MEDIATEK_SOC_WED) || defined(CONFIG_MT7996_NPU)\n+static int\n+mt7996_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,\n+\t\t struct net_device *netdev, enum tc_setup_type type,\n+\t\t void *type_data)\n+{\n+#ifdef CONFIG_NET_MEDIATEK_SOC_WED\n+\tstruct mt7996_dev *dev = mt7996_hw_dev(hw);\n+\n+\tif (mtk_wed_device_active(\u0026dev-\u003emt76.mmio.wed))\n+\t\treturn mt76_wed_net_setup_tc(hw, vif, netdev, type,\n+\t\t\t\t\t type_data);\n+#endif\n+\treturn mt76_npu_net_setup_tc(hw, vif, netdev, type, type_data);\n+}\n+#endif\n+\n static int\n mt7996_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,\n \t\t\tu16 old_links, u16 new_links,\n@@ -2460,6 +2490,7 @@ mt7996_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,\n \n \t\tidx = get_free_idx(dev-\u003emld_remap_idx_mask, 0, 15) - 1;\n \t\tif (idx \u003c 0) {\n+\t\t\tdev-\u003emld_idx_mask \u0026= ~BIT_ULL(mvif-\u003emld_group_idx);\n \t\t\tret = -ENOSPC;\n \t\t\tgoto out;\n \t\t}\n@@ -2562,10 +2593,8 @@ const struct ieee80211_ops mt7996_ops = {\n #endif\n \t.set_radar_background = mt7996_set_radar_background,\n \t.net_fill_forward_path = mt7996_net_fill_forward_path,\n-#ifdef CONFIG_NET_MEDIATEK_SOC_WED\n-\t.net_setup_tc = mt76_wed_net_setup_tc,\n-#elif defined(CONFIG_MT7996_NPU)\n-\t.net_setup_tc = mt76_npu_net_setup_tc,\n+#if defined(CONFIG_NET_MEDIATEK_SOC_WED) || defined(CONFIG_MT7996_NPU)\n+\t.net_setup_tc = mt7996_net_setup_tc,\n #endif\n \t.change_vif_links = mt7996_change_vif_links,\n \t.change_sta_links = mt7996_mac_sta_change_links,\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c\nindex f119f023bcd579..7abe3aba85db15 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c\n+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c\n@@ -2476,7 +2476,7 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,\n \t\t\tcap |= STA_CAP_VHT_SGI_160;\n \t\tif (link_sta-\u003evht_cap.cap \u0026 IEEE80211_VHT_CAP_TXSTBC)\n \t\t\tcap |= STA_CAP_VHT_TX_STBC;\n-\t\tif (link_sta-\u003evht_cap.cap \u0026 IEEE80211_VHT_CAP_RXSTBC_1)\n+\t\tif (link_sta-\u003evht_cap.cap \u0026 IEEE80211_VHT_CAP_RXSTBC_MASK)\n \t\t\tcap |= STA_CAP_VHT_RX_STBC;\n \t\tif ((vif-\u003etype != NL80211_IFTYPE_AP || link_conf-\u003evht_ldpc) \u0026\u0026\n \t\t (link_sta-\u003evht_cap.cap \u0026 IEEE80211_VHT_CAP_RXLDPC))\n@@ -4016,6 +4016,9 @@ int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,\n \tstruct mt7996_dev *dev = phy-\u003edev;\n \tint err, region, rdd_idx = mt7996_get_rdd_idx(phy, true);\n \n+\tif (rdd_idx \u003c 0)\n+\t\treturn -EINVAL;\n+\n \tif (!chandef) { /* disable offchain */\n \t\terr = mt7996_mcu_rdd_cmd(dev, RDD_STOP, rdd_idx, 0);\n \t\tif (err)\n@@ -4431,21 +4434,31 @@ int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap)\n \t\treturn ret;\n \n \t/* fixed field */\n+\tif (skb-\u003elen \u003c 4) {\n+\t\tdev_kfree_skb(skb);\n+\t\treturn -EINVAL;\n+\t}\n \tskb_pull(skb, 4);\n \n \tbuf = skb-\u003edata;\n-\twhile (buf - skb-\u003edata \u003c skb-\u003elen) {\n+\twhile (buf - skb-\u003edata + sizeof(struct tlv) \u003c= skb-\u003elen) {\n \t\tstruct tlv *tlv = (struct tlv *)buf;\n+\t\tu16 tlv_len = le16_to_cpu(tlv-\u003elen);\n+\n+\t\tif (tlv_len \u003c sizeof(*tlv) ||\n+\t\t tlv_len \u003e skb-\u003elen - (buf - skb-\u003edata))\n+\t\t\tbreak;\n \n \t\tswitch (le16_to_cpu(tlv-\u003etag)) {\n \t\tcase UNI_EVENT_CHIP_CONFIG_EFUSE_VERSION:\n-\t\t\t*cap = le32_to_cpu(*(__le32 *)(buf + sizeof(*tlv)));\n+\t\t\tif (tlv_len \u003e= sizeof(*tlv) + sizeof(__le32))\n+\t\t\t\t*cap = le32_to_cpu(*(__le32 *)(buf + sizeof(*tlv)));\n \t\t\tbreak;\n \t\tdefault:\n \t\t\tbreak;\n \t\t}\n \n-\t\tbuf += le16_to_cpu(tlv-\u003elen);\n+\t\tbuf += tlv_len;\n \t}\n \n \tdev_kfree_skb(skb);\n@@ -5022,6 +5035,32 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,\n \t\t\t\t \u0026req, sizeof(req), true);\n }\n \n+int mt7996_mcu_set_bssid_mapping_addr(struct mt76_dev *dev, u8 band_idx)\n+{\n+\tenum {\n+\t\tBSSID_MAPPING_ADDR1,\n+\t\tBSSID_MAPPING_ADDR2,\n+\t\tBSSID_MAPPING_ADDR3,\n+\t};\n+\tstruct {\n+\t\tu8 band_idx;\n+\t\tu8 _rsv1[3];\n+\n+\t\t__le16 tag;\n+\t\t__le16 len;\n+\t\tu8 addr;\n+\t\tu8 _rsv2[3];\n+\t} __packed req = {\n+\t\t.band_idx = band_idx,\n+\t\t.tag = cpu_to_le16(UNI_BAND_CONFIG_BSSID_MAPPING_ADDR),\n+\t\t.len = cpu_to_le16(sizeof(req) - 4),\n+\t\t.addr = BSSID_MAPPING_ADDR1,\n+\t};\n+\n+\treturn mt76_mcu_send_msg(dev, MCU_WM_UNI_CMD(BAND_CONFIG),\n+\t\t\t\t \u0026req, sizeof(req), true);\n+}\n+\n int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val)\n {\n \tstruct {\n@@ -5138,6 +5177,24 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,\n \t\t\t\t MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);\n }\n \n+int mt7996_mcu_ps_leave(struct mt7996_dev *dev, struct mt7996_vif_link *link,\n+\t\t\tstruct mt7996_sta_link *msta_link)\n+{\n+\tstruct sk_buff *skb;\n+\n+\tskb = __mt76_connac_mcu_alloc_sta_req(\u0026dev-\u003emt76, \u0026link-\u003emt76,\n+\t\t\t\t\t \u0026msta_link-\u003ewcid,\n+\t\t\t\t\t MT7996_STA_UPDATE_MAX_SIZE);\n+\tif (IS_ERR(skb))\n+\t\treturn PTR_ERR(skb);\n+\n+\tmt76_connac_mcu_add_tlv(skb, STA_REC_PS_LEAVE,\n+\t\t\t\tsizeof(struct sta_rec_ps_leave));\n+\n+\treturn mt76_mcu_skb_send_msg(\u0026dev-\u003emt76, skb,\n+\t\t\t\t MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);\n+}\n+\n int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,\n \t\t\t\t u16 rate_idx, bool beacon)\n {\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h\nindex 8902e16508b75e..1487d33a8dbb05 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h\n+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h\n@@ -680,6 +680,12 @@ struct sta_rec_hdr_trans {\n \tu8 mesh;\n } __packed;\n \n+struct sta_rec_ps_leave {\n+\t__le16 tag;\n+\t__le16 len;\n+\tu8 __rsv[4];\n+} __packed;\n+\n struct sta_rec_mld_setup {\n \t__le16 tag;\n \t__le16 len;\n@@ -917,7 +923,7 @@ enum {\n #define MT7996_BEACON_UPDATE_SIZE\t(sizeof(struct bss_req_hdr) +\t\t\\\n \t\t\t\t\t sizeof(struct bss_bcn_content_tlv) +\t\\\n \t\t\t\t\t 4 + MT_TXD_SIZE +\t\t\t\\\n-\t\t\t\t\t sizeof(struct bss_bcn_cntdwn_tlv) +\t\\\n+\t\t\t\t\t sizeof(struct bss_bcn_cntdwn_tlv) * 2 +\t\\\n \t\t\t\t\t sizeof(struct bss_bcn_mbss_tlv))\n #define MT7996_MAX_BSS_OFFLOAD_SIZE\t2048\n #define MT7996_MAX_BEACON_SIZE\t\t(MT7996_MAX_BSS_OFFLOAD_SIZE - \\\n@@ -927,6 +933,7 @@ enum {\n \tUNI_BAND_CONFIG_RADIO_ENABLE,\n \tUNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,\n \tUNI_BAND_CONFIG_MAC_ENABLE_CTRL = 0x0c,\n+\tUNI_BAND_CONFIG_BSSID_MAPPING_ADDR = 0x12,\n };\n \n enum {\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h\nindex 0d6488522ba711..cab7bd59e380a0 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h\n+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h\n@@ -771,6 +771,7 @@ int mt7996_mcu_set_protection(struct mt7996_phy *phy, struct mt7996_vif_link *li\n \t\t\t u8 ht_mode, bool use_cts_prot);\n int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif,\n \t\t\t struct ieee80211_bss_conf *link_conf);\n+int mt7996_mcu_set_bssid_mapping_addr(struct mt76_dev *dev, u8 band_idx);\n int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);\n int mt7996_mcu_get_temperature(struct mt7996_phy *phy);\n int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state);\n@@ -925,6 +926,8 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,\n \t\t\t\t struct ieee80211_vif *vif,\n \t\t\t\t struct mt7996_vif_link *link,\n \t\t\t\t struct mt7996_sta_link *msta_link);\n+int mt7996_mcu_ps_leave(struct mt7996_dev *dev, struct mt7996_vif_link *link,\n+\t\t\tstruct mt7996_sta_link *msta_link);\n int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode);\n int mt7996_mcu_set_emlsr_mode(struct mt7996_dev *dev,\n \t\t\t struct ieee80211_vif *vif,\ndiff --git a/drivers/net/wireless/mediatek/mt76/scan.c b/drivers/net/wireless/mediatek/mt76/scan.c\nindex 7fe1b1fbb699b7..d95614b808d731 100644\n--- a/drivers/net/wireless/mediatek/mt76/scan.c\n+++ b/drivers/net/wireless/mediatek/mt76/scan.c\n@@ -11,15 +11,24 @@ static void mt76_scan_complete(struct mt76_dev *dev, bool abort)\n \t\t.aborted = abort,\n \t};\n \n+\tlockdep_assert_held(\u0026dev-\u003emutex);\n+\n \tif (!phy)\n \t\treturn;\n \n \tclear_bit(MT76_SCANNING, \u0026phy-\u003estate);\n \n-\tif (dev-\u003escan.chan \u0026\u0026 phy-\u003emain_chandef.chan \u0026\u0026 phy-\u003eoffchannel \u0026\u0026\n+\t/* Re-program the operating channel even when the scan never left it:\n+\t * any channel set during the scan ran with MT76_SCANNING held, which\n+\t * left DFS radar detection disabled\n+\t */\n+\tif (phy-\u003emain_chandef.chan \u0026\u0026\n \t !test_bit(MT76_MCU_RESET, \u0026dev-\u003ephy.state)) {\n-\t\tmt76_set_channel(phy, \u0026phy-\u003emain_chandef, false);\n-\t\tmt76_offchannel_notify(phy, false);\n+\t\tbool offchannel = phy-\u003eoffchannel;\n+\n+\t\t__mt76_set_channel(phy, \u0026phy-\u003emain_chandef, false);\n+\t\tif (offchannel)\n+\t\t\tmt76_offchannel_notify(phy, false);\n \t}\n \tmt76_put_vif_phy_link(phy, dev-\u003escan.vif, dev-\u003escan.mlink);\n \tmemset(\u0026dev-\u003escan, 0, sizeof(dev-\u003escan));\n@@ -34,7 +43,10 @@ void mt76_abort_scan(struct mt76_dev *dev)\n \tspin_unlock_bh(\u0026dev-\u003escan_lock);\n \n \tcancel_delayed_work_sync(\u0026dev-\u003escan_work);\n+\n+\tmutex_lock(\u0026dev-\u003emutex);\n \tmt76_scan_complete(dev, true);\n+\tmutex_unlock(\u0026dev-\u003emutex);\n }\n EXPORT_SYMBOL_GPL(mt76_abort_scan);\n \n@@ -127,7 +139,9 @@ void mt76_scan_work(struct work_struct *work)\n \t\tgoto probe;\n \n \tif (dev-\u003escan.chan_idx \u003e= req-\u003en_channels) {\n+\t\tmutex_lock(\u0026dev-\u003emutex);\n \t\tmt76_scan_complete(dev, false);\n+\t\tmutex_unlock(\u0026dev-\u003emutex);\n \t\treturn;\n \t}\n \n@@ -206,6 +220,7 @@ int mt76_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,\n \tdev-\u003escan.vif = vif;\n \tdev-\u003escan.phy = phy;\n \tdev-\u003escan.mlink = mlink;\n+\tset_bit(MT76_SCANNING, \u0026phy-\u003estate);\n \tieee80211_queue_delayed_work(dev-\u003ephy.hw, \u0026dev-\u003escan_work, 0);\n \n out:\n"
} |
| 2/1 | 2026/07/25 19:05 | agent | patch-evaluator |
3mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"MT7663U",
"MT7921U",
"MT7925U"
],
"FocusSymbols": [
"mt7663_usb_sdio_tx_prepare_skb",
"mt76_connac2_mac_fill_rx_rate",
"mt76_connac_mcu_sta_tlv",
"mt76_dma_rx_poll",
"mt76_abort_scan",
"mt76_scan_work"
],
"Reasoning": "The patch modifies the MediaTek mt76 wireless driver, including core DMA, MAC, MCU, and scanning logic, as well as specific drivers like mt7615, mt7915, and mt7996. While mt7915 and mt7996 are PCIe-only and not reachable in standard QEMU, the mt76 core and mt7615 driver have USB support (e.g., MT7663U, MT7921U, MT7925U) which can be fuzzed via USB emulation (dummy_hcd). The changes include functional modifications to RX rate reporting, STA HE TLV parsing, DMA buffer handling, and scan channel locking, all of which are reachable via the USB driver paths.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). - Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU. - Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove) that are executed only during PCI hot-unplug or sysfs driver unbind operations. If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. Prefer non-static, non-inlined API entrypoint functions over internal static helper functions (which are inlined by the compiler and do not have distinct symbol addresses). 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit d52f0f64e49b482c9aa9daefd7de92560bde4bee
Author: syz-cluster <triage@syzkaller.com>
Date: Sat Jul 25 19:05:37 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/wireless/mediatek/mt76/dma.c b/drivers/net/wireless/mediatek/mt76/dma.c
index f8c2fe5f2f5877..acb18c237b0a4f 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.c
+++ b/drivers/net/wireless/mediatek/mt76/dma.c
@@ -534,8 +534,13 @@ mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,
t->ptr = NULL;
mt76_put_rxwi(dev, t);
- if (drop)
+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+ /* the WO MCU owns the RX path only on WED v2, on newer
+ * versions this buf1 bit carries no drop information
+ */
+ if (drop && dev->mmio.wed.version == 2)
*drop |= !!(buf1 & MT_DMA_CTL_WO_DROP);
+#endif
} else {
dma_sync_single_for_cpu(dev->dma_dev, e->dma_addr[0],
SKB_WITH_OVERHEAD(q->buf_size),
diff --git a/drivers/net/wireless/mediatek/mt76/dma.h b/drivers/net/wireless/mediatek/mt76/dma.h
index 2a0226c83f3c92..ffd81bb946134c 100644
--- a/drivers/net/wireless/mediatek/mt76/dma.h
+++ b/drivers/net/wireless/mediatek/mt76/dma.h
@@ -5,6 +5,8 @@
#ifndef __MT76_DMA_H
#define __MT76_DMA_H
+#include <linux/regmap.h>
+
#define DMA_DUMMY_DATA ((void *)~0)
#define MT_RING_SIZE 0x10
@@ -46,73 +48,75 @@
#define MT_FCE_INFO_LEN 4
#define MT_RX_RXWI_LEN 32
+static inline bool
+mt76_dma_handle_read(struct mt76_queue *q, u32 offset, u32 *val)
+{
#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)
+ if (q->flags & MT_QFLAG_WED) {
+ *val = mtk_wed_device_reg_read(q->wed, q->wed_regs + offset);
-#define Q_READ(_q, _field) ({ \
- u32 _offset = offsetof(struct mt76_queue_regs, _field); \
- u32 _val; \
- if ((_q)->flags & MT_QFLAG_WED) \
- _val = mtk_wed_device_reg_read((_q)->wed, \
- ((_q)->wed_regs + \
- _offset)); \
- else \
- _val = readl(&(_q)->regs->_field); \
- _val; \
-})
+ return true;
+ }
+#endif
+#if IS_ENABLED(CONFIG_MT76_NPU)
+ if (q->flags & MT_QFLAG_NPU) {
+ struct airoha_npu *npu;
+
+ *val = 0;
+ rcu_read_lock();
+ npu = rcu_dereference(q->dev->mmio.npu);
+ if (npu)
+ regmap_read(npu->regmap, q->wed_regs + offset, val);
+ rcu_read_unlock();
+
+ return true;
+ }
+#endif
-#define Q_WRITE(_q, _field, _val) do { \
- u32 _offset = offsetof(struct mt76_queue_regs, _field); \
- if ((_q)->flags & MT_QFLAG_WED) \
- mtk_wed_device_reg_write((_q)->wed, \
- ((_q)->wed_regs + _offset), \
- _val); \
- else \
- writel(_val, &(_q)->regs->_field); \
-} while (0)
+ return false;
+}
-#elif IS_ENABLED(CONFIG_MT76_NPU)
+static inline bool
+mt76_dma_handle_write(struct mt76_queue *q, u32 offset, u32 val)
+{
+#if IS_ENABLED(CONFIG_NET_MEDIATEK_SOC_WED)
+ if (q->flags & MT_QFLAG_WED) {
+ mtk_wed_device_reg_write(q->wed, q->wed_regs + offset, val);
+
+ return true;
+ }
+#endif
+#if IS_ENABLED(CONFIG_MT76_NPU)
+ if (q->flags & MT_QFLAG_NPU) {
+ struct airoha_npu *npu;
+
+ rcu_read_lock();
+ npu = rcu_dereference(q->dev->mmio.npu);
+ if (npu)
+ regmap_write(npu->regmap, q->wed_regs + offset, val);
+ rcu_read_unlock();
+
+ return true;
+ }
+#endif
+
+ return false;
+}
#define Q_READ(_q, _field) ({ \
u32 _offset = offsetof(struct mt76_queue_regs, _field); \
- u32 _val = 0; \
- if ((_q)->flags & MT_QFLAG_NPU) { \
- struct airoha_npu *npu; \
- \
- rcu_read_lock(); \
- npu = rcu_dereference(q->dev->mmio.npu); \
- if (npu) \
- regmap_read(npu->regmap, \
- ((_q)->wed_regs + _offset), &_val); \
- rcu_read_unlock(); \
- } else { \
+ u32 _val; \
+ if (!mt76_dma_handle_read(_q, _offset, &_val)) \
_val = readl(&(_q)->regs->_field); \
- } \
_val; \
})
#define Q_WRITE(_q, _field, _val) do { \
u32 _offset = offsetof(struct mt76_queue_regs, _field); \
- if ((_q)->flags & MT_QFLAG_NPU) { \
- struct airoha_npu *npu; \
- \
- rcu_read_lock(); \
- npu = rcu_dereference(q->dev->mmio.npu); \
- if (npu) \
- regmap_write(npu->regmap, \
- ((_q)->wed_regs + _offset), _val); \
- rcu_read_unlock(); \
- } else { \
+ if (!mt76_dma_handle_write(_q, _offset, _val)) \
writel(_val, &(_q)->regs->_field); \
- } \
} while (0)
-#else
-
-#define Q_READ(_q, _field) readl(&(_q)->regs->_field)
-#define Q_WRITE(_q, _field, _val) writel(_val, &(_q)->regs->_field)
-
-#endif
-
struct mt76_desc {
__le32 buf0;
__le32 ctrl;
diff --git a/drivers/net/wireless/mediatek/mt76/mmio.c b/drivers/net/wireless/mediatek/mt76/mmio.c
index 05d74cd7248e97..73d47608bf428d 100644
--- a/drivers/net/wireless/mediatek/mt76/mmio.c
+++ b/drivers/net/wireless/mediatek/mt76/mmio.c
@@ -35,9 +35,16 @@ static void mt76_mmio_write_copy(struct mt76_dev *dev, u32 offset,
{
int i;
- for (i = 0; i < ALIGN(len, 4); i += 4)
+ for (i = 0; i + 4 <= len; i += 4)
writel(get_unaligned_le32(data + i),
dev->mmio.regs + offset + i);
+
+ if (i < len) {
+ u8 tmp[4] = {};
+
+ memcpy(tmp, data + i, len - i);
+ writel(get_unaligned_le32(tmp), dev->mmio.regs + offset + i);
+ }
}
static void mt76_mmio_read_copy(struct mt76_dev *dev, u32 offset,
@@ -45,9 +52,16 @@ static void mt76_mmio_read_copy(struct mt76_dev *dev, u32 offset,
{
int i;
- for (i = 0; i < ALIGN(len, 4); i += 4)
+ for (i = 0; i + 4 <= len; i += 4)
put_unaligned_le32(readl(dev->mmio.regs + offset + i),
data + i);
+
+ if (i < len) {
+ u8 tmp[4];
+
+ put_unaligned_le32(readl(dev->mmio.regs + offset + i), tmp);
+ memcpy(data + i, tmp, len - i);
+ }
}
static int mt76_mmio_wr_rp(struct mt76_dev *dev, u32 base,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c
index 53cb1eed1e4fb3..0aca590f2bae5d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c
@@ -68,10 +68,11 @@ int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
int pid, id;
u8 *txwi = (u8 *)txwi_ptr;
struct mt76_txwi_cache *t;
- struct mt7615_sta *msta;
+ struct mt7615_sta *msta = NULL;
void *txp;
- msta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL;
+ if (wcid && wcid->sta)
+ msta = container_of(wcid, struct mt7615_sta, wcid);
if (!wcid)
wcid = &dev->mt76.global_wcid;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
index f4169de939c487..9525d8062b4439 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c
@@ -187,10 +187,11 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,
struct sk_buff *skb = tx_info->skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_key_conf *key = info->control.hw_key;
- struct mt7615_sta *msta;
+ struct mt7615_sta *msta = NULL;
int pad, err, pktid;
- msta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL;
+ if (wcid && wcid->sta)
+ msta = container_of(wcid, struct mt7615_sta, wcid);
if (!wcid)
wcid = &dev->mt76.global_wcid;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
index fc9f782032ef2b..976043521f44ff 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mac.c
@@ -1069,6 +1069,10 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
bw = FIELD_GET(MT_CRXV_FRAME_MODE, v2);
}
+ /* the hardware reports NSTS; report the data NSS for STBC frames */
+ if (stbc && nss > 1)
+ nss >>= 1;
+
switch (*mode) {
case MT_PHY_TYPE_CCK:
cck = true;
@@ -1114,7 +1118,7 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
case IEEE80211_STA_RX_BW_20:
break;
case IEEE80211_STA_RX_BW_40:
- if (*mode & MT_PHY_TYPE_HE_EXT_SU &&
+ if (*mode == MT_PHY_TYPE_HE_EXT_SU &&
(idx & MT_PRXV_TX_ER_SU_106T)) {
status->bw = RATE_INFO_BW_HE_RU;
status->he_ru =
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index 6596c9e198f425..f002ad5ec19d4c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -753,7 +753,7 @@ mt76_connac_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
HE_PHY(CAP3_DCM_MAX_CONST_RX_MASK, elem->phy_cap_info[3]);
he->dcm_rx_max_nss =
HE_PHY(CAP3_DCM_MAX_RX_NSS_2, elem->phy_cap_info[3]);
- he->dcm_rx_max_nss =
+ he->dcm_max_ru =
HE_PHY(CAP8_DCM_MAX_RU_MASK, elem->phy_cap_info[8]);
he->pkt_ext = 2;
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
index 78f633ad81a076..55b1befa42ee41 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
@@ -842,6 +842,7 @@ enum {
STA_REC_HDRT = 0x28,
STA_REC_EML_OP = 0x29,
STA_REC_HDR_TRANS = 0x2B,
+ STA_REC_PS_LEAVE = 0x45,
STA_REC_MAX_NUM
};
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index 250c2d2479b0c6..a4ca8a46b73d59 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -1295,6 +1295,8 @@ int mt7915_register_device(struct mt7915_dev *dev)
void mt7915_unregister_device(struct mt7915_dev *dev)
{
cancel_work_sync(&dev->dump_work);
+ cancel_work_sync(&dev->reset_work);
+ cancel_work_sync(&dev->rc_work);
mt7915_unregister_ext_phy(dev);
mt7915_coredump_unregister(dev);
mt7915_unregister_thermal(&dev->phy);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index 334c19ab2b22ca..1fc7efcce273b4 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -1464,6 +1464,10 @@ mt7915_mac_full_reset(struct mt7915_dev *dev)
mutex_unlock(&dev->mt76.mutex);
+ ieee80211_wake_queues(mt76_hw(dev));
+ if (ext_phy)
+ ieee80211_wake_queues(ext_phy->hw);
+
ieee80211_restart_hw(mt76_hw(dev));
if (ext_phy)
ieee80211_restart_hw(ext_phy->hw);
@@ -1925,7 +1929,7 @@ void mt7915_mac_update_stats(struct mt7915_phy *phy)
static void mt7915_mac_severe_check(struct mt7915_phy *phy)
{
struct mt7915_dev *dev = phy->dev;
- u32 trb;
+ u32 trb, ple_err;
if (!phy->omac_mask)
return;
@@ -1945,6 +1949,17 @@ static void mt7915_mac_severe_check(struct mt7915_phy *phy)
phy->mt76->band_idx);
phy->trb_ts = trb;
+
+ ple_err = mt76_rr(dev, MT_SWDEF_PLE1_STATS);
+ if ((ple_err & MT_SWDEF_PLE1_MDP_RIOC_HANG_ERR) &&
+ !(dev->ple1_sts & MT_SWDEF_PLE1_MDP_RIOC_HANG_ERR)) {
+ dev_warn(dev->mt76.dev,
+ "band%d: PLE error 0x%x detected, triggering L1 SER\n",
+ phy->mt76->band_idx, ple_err);
+ mt7915_mcu_set_ser(dev, SER_RECOVER, SER_SET_RECOVER_L1,
+ phy->mt76->band_idx);
+ }
+ dev->ple1_sts = ple_err;
}
void mt7915_mac_sta_rc_work(struct work_struct *work)
@@ -2345,8 +2360,10 @@ void mt7915_mac_add_twt_setup(struct ieee80211_hw *hw,
}
flow->tsf = le64_to_cpu(twt_agrt->twt);
- if (mt7915_mcu_twt_agrt_update(dev, msta->vif, flow, MCU_TWT_AGRT_ADD))
+ if (mt7915_mcu_twt_agrt_update(dev, msta->vif, flow, MCU_TWT_AGRT_ADD)) {
+ list_del(&flow->list);
goto unlock;
+ }
setup_cmd = TWT_SETUP_CMD_ACCEPT;
dev->twt.table_mask |= BIT(table_id);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 51643a48ed1515..8fa5022b79af2b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -249,7 +249,7 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
idx = mt76_wcid_alloc(dev->mt76.wcid_mask, mt7915_wtbl_size(dev));
if (idx < 0) {
ret = -ENOSPC;
- goto out;
+ goto err;
}
INIT_LIST_HEAD(&mvif->sta.rc_list);
@@ -277,7 +277,17 @@ static int mt7915_add_interface(struct ieee80211_hw *hw,
mt7915_mcu_add_sta(dev, vif, NULL, CONN_STATE_PORT_SECURE, true);
rcu_assign_pointer(dev->mt76.wcid[idx], &mvif->sta.wcid);
+ mutex_unlock(&dev->mt76.mutex);
+
+ return 0;
+
+err:
+ dev->mt76.vif_mask &= ~BIT_ULL(mvif->mt76.idx);
+ phy->omac_mask &= ~BIT_ULL(mvif->mt76.omac_idx);
+ mt7915_mcu_add_dev_info(phy, vif, false);
out:
+ if (phy->monitor_vif == vif)
+ phy->monitor_vif = NULL;
mutex_unlock(&dev->mt76.mutex);
return ret;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 4a381d351e6154..4760d725e1f739 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -576,9 +576,9 @@ mt7915_mcu_bss_ra_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
ra->rx_streams = max_nss;
ra->algo = 4;
ra->train_up_rule = 2;
- ra->train_up_high_thres = 110;
- ra->train_up_rule_rssi = -70;
- ra->low_traffic_thres = 2;
+ ra->train_up_high_thres = cpu_to_le16(110);
+ ra->train_up_rule_rssi = cpu_to_le16(-70);
+ ra->low_traffic_thres = cpu_to_le16(2);
ra->phy_cap = cpu_to_le32(0xfdf);
ra->interval = cpu_to_le32(500);
ra->fast_interval = cpu_to_le32(100);
@@ -900,7 +900,7 @@ mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta,
HE_PHY(CAP3_DCM_MAX_CONST_RX_MASK, elem->phy_cap_info[3]);
he->dcm_rx_max_nss =
HE_PHY(CAP3_DCM_MAX_RX_NSS_2, elem->phy_cap_info[3]);
- he->dcm_rx_max_nss =
+ he->dcm_max_ru =
HE_PHY(CAP8_DCM_MAX_RU_MASK, elem->phy_cap_info[8]);
he->pkt_ext = 2;
@@ -1617,7 +1617,7 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
cap |= STA_CAP_VHT_SGI_160;
if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC)
cap |= STA_CAP_VHT_TX_STBC;
- if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
+ if (sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK)
cap |= STA_CAP_VHT_RX_STBC;
if (mvif->cap.vht_ldpc &&
(sta->deflink.vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index 22f73a5ed42590..7c472062a90e1c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -318,9 +318,9 @@ struct bss_info_ra {
u8 antenna_idx;
u8 train_up_rule;
u8 rsv[3];
- unsigned short train_up_high_thres;
- short train_up_rule_rssi;
- unsigned short low_traffic_thres;
+ __le16 train_up_high_thres;
+ __le16 train_up_rule_rssi;
+ __le16 low_traffic_thres;
__le16 max_phyrate;
__le32 phy_cap;
__le32 interval;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index bf1d915a3ca238..44253196749fea 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -295,6 +295,7 @@ struct mt7915_dev {
spinlock_t reg_lock;
u32 hw_pattern;
+ u32 ple1_sts;
bool dbdc_support;
bool flash_mode;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h
index 307bf6a7567495..dc7bb9a1f223e9 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/regs.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/regs.h
@@ -1044,6 +1044,7 @@ enum offs_rev {
#define MT_SWDEF_SER_STATS MT_SWDEF(0x040)
#define MT_SWDEF_PLE_STATS MT_SWDEF(0x044)
#define MT_SWDEF_PLE1_STATS MT_SWDEF(0x048)
+#define MT_SWDEF_PLE1_MDP_RIOC_HANG_ERR BIT(3)
#define MT_SWDEF_PLE_AMSDU_STATS MT_SWDEF(0x04C)
#define MT_SWDEF_PSE_STATS MT_SWDEF(0x050)
#define MT_SWDEF_PSE1_STATS MT_SWDEF(0x054)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/init.c b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
index d6f9aa1ab52d12..7415fb595b586f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/init.c
@@ -559,6 +559,9 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band)
{
u32 mask, set;
+ if (!mt7996_band_valid(dev, band))
+ return;
+
/* clear estimated value of EIFS for Rx duration & OBSS time */
mt76_wr(dev, MT_WF_RMAC_RSVD0(band), MT_WF_RMAC_RSVD0_EIFS_CLR);
@@ -590,6 +593,9 @@ mt7996_mac_init_band(struct mt7996_dev *dev, u8 band)
* MT_AGG_ACR_PPDU_TXS2H (PPDU format) even though ACR bit is set.
*/
mt76_set(dev, MT_AGG_ACR4(band), MT_AGG_ACR_PPDU_TXS2H);
+
+ if (!is_mt7996(&dev->mt76))
+ mt7996_mcu_set_bssid_mapping_addr(&dev->mt76, band);
}
static void mt7996_mac_init_basic_rates(struct mt7996_dev *dev)
@@ -1799,6 +1805,8 @@ void mt7996_unregister_device(struct mt7996_dev *dev)
{
cancel_work_sync(&dev->dump_work);
cancel_work_sync(&dev->wed_rro.work);
+ cancel_work_sync(&dev->reset_work);
+ cancel_work_sync(&dev->rc_work);
mt7996_unregister_phy(mt7996_phy3(dev));
mt7996_unregister_phy(mt7996_phy2(dev));
mt7996_unregister_thermal(&dev->phy);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
index 0eebc8182ca9aa..9583870628b45c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mac.c
@@ -294,6 +294,10 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
dcm = FIELD_GET(MT_PRXV_DCM, v2);
bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2);
+ /* the hardware reports NSTS; report the data NSS for STBC frames */
+ if (stbc && nss > 1)
+ nss >>= 1;
+
switch (*mode) {
case MT_PHY_TYPE_CCK:
cck = true;
@@ -349,7 +353,7 @@ mt7996_mac_fill_rx_rate(struct mt7996_dev *dev,
case IEEE80211_STA_RX_BW_20:
break;
case IEEE80211_STA_RX_BW_40:
- if (*mode & MT_PHY_TYPE_HE_EXT_SU &&
+ if (*mode == MT_PHY_TYPE_HE_EXT_SU &&
(idx & MT_PRXV_TX_ER_SU_106T)) {
status->bw = RATE_INFO_BW_HE_RU;
status->he_ru =
@@ -2383,6 +2387,7 @@ mt7996_mac_reset_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
rcu_assign_pointer(mvif->link[i], NULL);
kfree_rcu(mlink, rcu_head);
}
+ mvif->valid_links = 0;
rcu_read_unlock();
}
@@ -2416,12 +2421,14 @@ mt7996_mac_full_reset(struct mt7996_dev *dev)
mt7996_for_each_phy(dev, phy)
phy->omac_mask = 0;
+ dev->mld_idx_mask = 0;
+ dev->mld_remap_idx_mask = 0;
ieee80211_iterate_stations_atomic(hw, mt7996_mac_reset_sta_iter, dev);
+ mt76_reset_device(&dev->mt76);
ieee80211_iterate_active_interfaces_atomic(hw,
IEEE80211_IFACE_SKIP_SDATA_NOT_IN_DRIVER,
mt7996_mac_reset_vif_iter, dev);
- mt76_reset_device(&dev->mt76);
INIT_LIST_HEAD(&dev->sta_rc_list);
INIT_LIST_HEAD(&dev->twt_list);
@@ -2445,6 +2452,8 @@ mt7996_mac_full_reset(struct mt7996_dev *dev)
mutex_unlock(&dev->mt76.mutex);
+ ieee80211_wake_queues(mt76_hw(dev));
+
ieee80211_restart_hw(mt76_hw(dev));
}
@@ -2500,8 +2509,8 @@ void mt7996_mac_reset_work(struct work_struct *work)
set_bit(MT76_RESET, &dev->mphy.state);
set_bit(MT76_MCU_RESET, &dev->mphy.state);
- mt76_abort_scan(&dev->mt76);
wake_up(&dev->mt76.mcu.wait);
+ mt76_abort_scan(&dev->mt76);
cancel_work_sync(&dev->wed_rro.work);
mt7996_for_each_phy(dev, phy) {
@@ -2510,6 +2519,8 @@ void mt7996_mac_reset_work(struct work_struct *work)
cancel_delayed_work_sync(&phy->mt76->mac_work);
}
+ mutex_lock(&dev->mt76.mutex);
+
mt76_worker_disable(&dev->mt76.tx_worker);
mt76_for_each_q_rx(&dev->mt76, i) {
if (mtk_wed_device_active(&dev->mt76.mmio.wed) &&
@@ -2527,8 +2538,6 @@ void mt7996_mac_reset_work(struct work_struct *work)
}
napi_disable(&dev->mt76.tx_napi);
- mutex_lock(&dev->mt76.mutex);
-
mt76_wr(dev, MT_MCU_INT_EVENT, MT_MCU_INT_EVENT_DMA_STOPPED);
if (mt7996_wait_reset_state(dev, MT_MCU_CMD_RESET_DONE)) {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/main.c b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
index afbcc8c7b18b2f..bd624c2eaf857b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/main.c
@@ -372,7 +372,8 @@ int mt7996_vif_link_add(struct mt76_phy *mphy, struct ieee80211_vif *vif,
CONN_STATE_PORT_SECURE, true);
rcu_assign_pointer(dev->mt76.wcid[idx], &msta_link->wcid);
- ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, &it);
+ if (!mlink->wcid->offchannel)
+ ieee80211_iter_keys(mphy->hw, vif, mt7996_key_iter, &it);
if (!mlink->wcid->offchannel) {
if (vif->txq &&
@@ -605,6 +606,8 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
unsigned int link_id;
int i;
+ mutex_lock(&dev->mt76.mutex);
+
/* Remove all active links */
for_each_set_bit(link_id, &rem_links, IEEE80211_MLD_MAX_NUM_LINKS) {
struct mt7996_vif_link *link;
@@ -621,6 +624,8 @@ static void mt7996_remove_interface(struct ieee80211_hw *hw,
mt7996_vif_link_destroy(phy, link, vif, NULL);
}
+ mutex_unlock(&dev->mt76.mutex);
+
ieee80211_iterate_active_interfaces_mtx(hw, 0, mt7996_remove_iter,
&rdata);
mt76_vif_cleanup(&dev->mt76, vif);
@@ -2069,6 +2074,14 @@ static void mt7996_sta_set_decap_offload(struct ieee80211_hw *hw,
continue;
mt7996_mcu_wtbl_update_hdr_trans(dev, vif, link, msta_link);
+
+ /* HW cannot derive the BSSID from 4-address non-AMSDU frames,
+ * so PS exit is missed on links other than the setup link.
+ * Let the firmware wake those links instead.
+ */
+ if (enabled && msta->deflink_id != link_id &&
+ is_mt7996(&dev->mt76))
+ mt7996_mcu_ps_leave(dev, link, msta_link);
}
mutex_unlock(&dev->mt76.mutex);
@@ -2436,6 +2449,23 @@ mt7996_net_fill_forward_path(struct ieee80211_hw *hw,
return 0;
}
+#if defined(CONFIG_NET_MEDIATEK_SOC_WED) || defined(CONFIG_MT7996_NPU)
+static int
+mt7996_net_setup_tc(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
+ struct net_device *netdev, enum tc_setup_type type,
+ void *type_data)
+{
+#ifdef CONFIG_NET_MEDIATEK_SOC_WED
+ struct mt7996_dev *dev = mt7996_hw_dev(hw);
+
+ if (mtk_wed_device_active(&dev->mt76.mmio.wed))
+ return mt76_wed_net_setup_tc(hw, vif, netdev, type,
+ type_data);
+#endif
+ return mt76_npu_net_setup_tc(hw, vif, netdev, type, type_data);
+}
+#endif
+
static int
mt7996_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
u16 old_links, u16 new_links,
@@ -2460,6 +2490,7 @@ mt7996_change_vif_links(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
idx = get_free_idx(dev->mld_remap_idx_mask, 0, 15) - 1;
if (idx < 0) {
+ dev->mld_idx_mask &= ~BIT_ULL(mvif->mld_group_idx);
ret = -ENOSPC;
goto out;
}
@@ -2562,10 +2593,8 @@ const struct ieee80211_ops mt7996_ops = {
#endif
.set_radar_background = mt7996_set_radar_background,
.net_fill_forward_path = mt7996_net_fill_forward_path,
-#ifdef CONFIG_NET_MEDIATEK_SOC_WED
- .net_setup_tc = mt76_wed_net_setup_tc,
-#elif defined(CONFIG_MT7996_NPU)
- .net_setup_tc = mt76_npu_net_setup_tc,
+#if defined(CONFIG_NET_MEDIATEK_SOC_WED) || defined(CONFIG_MT7996_NPU)
+ .net_setup_tc = mt7996_net_setup_tc,
#endif
.change_vif_links = mt7996_change_vif_links,
.change_sta_links = mt7996_mac_sta_change_links,
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
index f119f023bcd579..7abe3aba85db15 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c
@@ -2476,7 +2476,7 @@ mt7996_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7996_dev *dev,
cap |= STA_CAP_VHT_SGI_160;
if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_TXSTBC)
cap |= STA_CAP_VHT_TX_STBC;
- if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_1)
+ if (link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXSTBC_MASK)
cap |= STA_CAP_VHT_RX_STBC;
if ((vif->type != NL80211_IFTYPE_AP || link_conf->vht_ldpc) &&
(link_sta->vht_cap.cap & IEEE80211_VHT_CAP_RXLDPC))
@@ -4016,6 +4016,9 @@ int mt7996_mcu_rdd_background_enable(struct mt7996_phy *phy,
struct mt7996_dev *dev = phy->dev;
int err, region, rdd_idx = mt7996_get_rdd_idx(phy, true);
+ if (rdd_idx < 0)
+ return -EINVAL;
+
if (!chandef) { /* disable offchain */
err = mt7996_mcu_rdd_cmd(dev, RDD_STOP, rdd_idx, 0);
if (err)
@@ -4431,21 +4434,31 @@ int mt7996_mcu_get_chip_config(struct mt7996_dev *dev, u32 *cap)
return ret;
/* fixed field */
+ if (skb->len < 4) {
+ dev_kfree_skb(skb);
+ return -EINVAL;
+ }
skb_pull(skb, 4);
buf = skb->data;
- while (buf - skb->data < skb->len) {
+ while (buf - skb->data + sizeof(struct tlv) <= skb->len) {
struct tlv *tlv = (struct tlv *)buf;
+ u16 tlv_len = le16_to_cpu(tlv->len);
+
+ if (tlv_len < sizeof(*tlv) ||
+ tlv_len > skb->len - (buf - skb->data))
+ break;
switch (le16_to_cpu(tlv->tag)) {
case UNI_EVENT_CHIP_CONFIG_EFUSE_VERSION:
- *cap = le32_to_cpu(*(__le32 *)(buf + sizeof(*tlv)));
+ if (tlv_len >= sizeof(*tlv) + sizeof(__le32))
+ *cap = le32_to_cpu(*(__le32 *)(buf + sizeof(*tlv)));
break;
default:
break;
}
- buf += le16_to_cpu(tlv->len);
+ buf += tlv_len;
}
dev_kfree_skb(skb);
@@ -5022,6 +5035,32 @@ int mt7996_mcu_twt_agrt_update(struct mt7996_dev *dev,
&req, sizeof(req), true);
}
+int mt7996_mcu_set_bssid_mapping_addr(struct mt76_dev *dev, u8 band_idx)
+{
+ enum {
+ BSSID_MAPPING_ADDR1,
+ BSSID_MAPPING_ADDR2,
+ BSSID_MAPPING_ADDR3,
+ };
+ struct {
+ u8 band_idx;
+ u8 _rsv1[3];
+
+ __le16 tag;
+ __le16 len;
+ u8 addr;
+ u8 _rsv2[3];
+ } __packed req = {
+ .band_idx = band_idx,
+ .tag = cpu_to_le16(UNI_BAND_CONFIG_BSSID_MAPPING_ADDR),
+ .len = cpu_to_le16(sizeof(req) - 4),
+ .addr = BSSID_MAPPING_ADDR1,
+ };
+
+ return mt76_mcu_send_msg(dev, MCU_WM_UNI_CMD(BAND_CONFIG),
+ &req, sizeof(req), true);
+}
+
int mt7996_mcu_set_rts_thresh(struct mt7996_phy *phy, u32 val)
{
struct {
@@ -5138,6 +5177,24 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
}
+int mt7996_mcu_ps_leave(struct mt7996_dev *dev, struct mt7996_vif_link *link,
+ struct mt7996_sta_link *msta_link)
+{
+ struct sk_buff *skb;
+
+ skb = __mt76_connac_mcu_alloc_sta_req(&dev->mt76, &link->mt76,
+ &msta_link->wcid,
+ MT7996_STA_UPDATE_MAX_SIZE);
+ if (IS_ERR(skb))
+ return PTR_ERR(skb);
+
+ mt76_connac_mcu_add_tlv(skb, STA_REC_PS_LEAVE,
+ sizeof(struct sta_rec_ps_leave));
+
+ return mt76_mcu_skb_send_msg(&dev->mt76, skb,
+ MCU_WMWA_UNI_CMD(STA_REC_UPDATE), true);
+}
+
int mt7996_mcu_set_fixed_rate_table(struct mt7996_phy *phy, u8 table_idx,
u16 rate_idx, bool beacon)
{
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
index 8902e16508b75e..1487d33a8dbb05 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.h
@@ -680,6 +680,12 @@ struct sta_rec_hdr_trans {
u8 mesh;
} __packed;
+struct sta_rec_ps_leave {
+ __le16 tag;
+ __le16 len;
+ u8 __rsv[4];
+} __packed;
+
struct sta_rec_mld_setup {
__le16 tag;
__le16 len;
@@ -917,7 +923,7 @@ enum {
#define MT7996_BEACON_UPDATE_SIZE (sizeof(struct bss_req_hdr) + \
sizeof(struct bss_bcn_content_tlv) + \
4 + MT_TXD_SIZE + \
- sizeof(struct bss_bcn_cntdwn_tlv) + \
+ sizeof(struct bss_bcn_cntdwn_tlv) * 2 + \
sizeof(struct bss_bcn_mbss_tlv))
#define MT7996_MAX_BSS_OFFLOAD_SIZE 2048
#define MT7996_MAX_BEACON_SIZE (MT7996_MAX_BSS_OFFLOAD_SIZE - \
@@ -927,6 +933,7 @@ enum {
UNI_BAND_CONFIG_RADIO_ENABLE,
UNI_BAND_CONFIG_RTS_THRESHOLD = 0x08,
UNI_BAND_CONFIG_MAC_ENABLE_CTRL = 0x0c,
+ UNI_BAND_CONFIG_BSSID_MAPPING_ADDR = 0x12,
};
enum {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
index 0d6488522ba711..cab7bd59e380a0 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h
@@ -771,6 +771,7 @@ int mt7996_mcu_set_protection(struct mt7996_phy *phy, struct mt7996_vif_link *li
u8 ht_mode, bool use_cts_prot);
int mt7996_mcu_set_timing(struct mt7996_phy *phy, struct ieee80211_vif *vif,
struct ieee80211_bss_conf *link_conf);
+int mt7996_mcu_set_bssid_mapping_addr(struct mt76_dev *dev, u8 band_idx);
int mt7996_mcu_get_chan_mib_info(struct mt7996_phy *phy, bool chan_switch);
int mt7996_mcu_get_temperature(struct mt7996_phy *phy);
int mt7996_mcu_set_thermal_throttling(struct mt7996_phy *phy, u8 state);
@@ -925,6 +926,8 @@ int mt7996_mcu_wtbl_update_hdr_trans(struct mt7996_dev *dev,
struct ieee80211_vif *vif,
struct mt7996_vif_link *link,
struct mt7996_sta_link *msta_link);
+int mt7996_mcu_ps_leave(struct mt7996_dev *dev, struct mt7996_vif_link *link,
+ struct mt7996_sta_link *msta_link);
int mt7996_mcu_cp_support(struct mt7996_dev *dev, u8 mode);
int mt7996_mcu_set_emlsr_mode(struct mt7996_dev *dev,
struct ieee80211_vif *vif,
diff --git a/drivers/net/wireless/mediatek/mt76/scan.c b/drivers/net/wireless/mediatek/mt76/scan.c
index 7fe1b1fbb699b7..d95614b808d731 100644
--- a/drivers/net/wireless/mediatek/mt76/scan.c
+++ b/drivers/net/wireless/mediatek/mt76/scan.c
@@ -11,15 +11,24 @@ static void mt76_scan_complete(struct mt76_dev *dev, bool abort)
.aborted = abort,
};
+ lockdep_assert_held(&dev->mutex);
+
if (!phy)
return;
clear_bit(MT76_SCANNING, &phy->state);
- if (dev->scan.chan && phy->main_chandef.chan && phy->offchannel &&
+ /* Re-program the operating channel even when the scan never left it:
+ * any channel set during the scan ran with MT76_SCANNING held, which
+ * left DFS radar detection disabled
+ */
+ if (phy->main_chandef.chan &&
!test_bit(MT76_MCU_RESET, &dev->phy.state)) {
- mt76_set_channel(phy, &phy->main_chandef, false);
- mt76_offchannel_notify(phy, false);
+ bool offchannel = phy->offchannel;
+
+ __mt76_set_channel(phy, &phy->main_chandef, false);
+ if (offchannel)
+ mt76_offchannel_notify(phy, false);
}
mt76_put_vif_phy_link(phy, dev->scan.vif, dev->scan.mlink);
memset(&dev->scan, 0, sizeof(dev->scan));
@@ -34,7 +43,10 @@ void mt76_abort_scan(struct mt76_dev *dev)
spin_unlock_bh(&dev->scan_lock);
cancel_delayed_work_sync(&dev->scan_work);
+
+ mutex_lock(&dev->mutex);
mt76_scan_complete(dev, true);
+ mutex_unlock(&dev->mutex);
}
EXPORT_SYMBOL_GPL(mt76_abort_scan);
@@ -127,7 +139,9 @@ void mt76_scan_work(struct work_struct *work)
goto probe;
if (dev->scan.chan_idx >= req->n_channels) {
+ mutex_lock(&dev->mutex);
mt76_scan_complete(dev, false);
+ mutex_unlock(&dev->mutex);
return;
}
@@ -206,6 +220,7 @@ int mt76_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
dev->scan.vif = vif;
dev->scan.phy = phy;
dev->scan.mlink = mlink;
+ set_bit(MT76_SCANNING, &phy->state);
ieee80211_queue_delayed_work(dev->phy.hw, &dev->scan_work, 0);
out:
|
| 3/2 | 2026/07/25 19:05 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 17556 output: 37 thoughts: 1031 Thoughts: **WorthFuzzing Assessment of the mt76 Patch** Okay, so we have a patch touching multiple files within the `drivers/net/wireless/mediatek/mt76/` directory. The commit message indicates it's related to syz-cluster, so it's likely a fuzzing-related patch. It modifies a broad range of files, including `dma.c`, `mmio.c`, and several files within `mt7615`, `mt76_connac`, `mt7915`, and `mt7996`, along with `scan.c`. Given the scope and the specific locations within the driver, it's pretty clear we're dealing with a MediaTek wireless driver based on the mac80211 framework. The immediate question that comes to mind is: can we fuzz this in a virtualized environment like QEMU, since the prompt specifies this as a key factor in determining if it's worth fuzzing? While mac80211 itself can be fuzzed using `mac80211_hwsim`, this patch targets the `mt76` hardware driver. Now, the caveat is that MediaTek's `mt76` is a *hardware-specific* driver. Generally, vendor-specific PCIe/USB drivers present a challenge for standard QEMU. Unless it's a USB device emulable via USB gadget/dummy_hcd, or virtio/vhost, it's unlikely standard QEMU can handle it. However, a critical point here is that `mt76` *does* have USB-specific components, like `mt7615/usb_sdio.c`. This is a significant clue. If we can fuzz the USB side, it's worth considering. The patch modifies `mt7615/usb_sdio.c`, implying it may be an entry point. Syzkaller has USB fuzzing capabilities via a dummy_hcd. It supports USB device emulation via crafted USB descriptors. So, even though it's vendor-specific, the USB interface *might* be reachable for fuzzing. This means the question now is, is the USB path of the `mt76` driver usable? The patch *also* modifies `mt7615/pci_mac.c` and other PCI-related files like `mt7915` and `mt7996`, but that's a different story. If the USB driver for `mt7615` is a valid entry point, it means that the `mt76` core components, `dma.c`, `mmio.c`, etc., might be reachable through the USB path. We should check if `mt76` has USB support, and it does, for `mt76x02`, `mt7615`, etc. This looks promising. I would need to investigate Syzkaller's USB support (though I don't have direct access), and what USB descriptors are configured, but generally speaking any USB driver can be probed and fuzzed via the dummy_hcd emulation. The modification to `mt7615/usb_sdio.c` is the key. Given that USB fuzzing with Syzkaller is a possibility here, this patch looks like it *is* worth pursuing. |
| 4/2 | 2026/07/25 19:05 | tool | grepper |
0mArgs:{
"Expression": "module_usb_driver",
"PathPrefix": "drivers/net/wireless/mediatek/mt76"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7615/usb.c=265=static struct usb_driver mt7663u_driver = {\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/usb.c-277-};\ndrivers/net/wireless/mediatek/mt76/mt7615/usb.c:278:module_usb_driver(mt7663u_driver);\ndrivers/net/wireless/mediatek/mt76/mt7615/usb.c-279-\n--\ndrivers/net/wireless/mediatek/mt76/mt76x0/usb.c=345=static struct usb_driver mt76x0_driver = {\n--\ndrivers/net/wireless/mediatek/mt76/mt76x0/usb.c-355-};\ndrivers/net/wireless/mediatek/mt76/mt76x0/usb.c:356:module_usb_driver(mt76x0_driver);\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/usb.c=137=static struct usb_driver mt76x2u_driver = {\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/usb.c-149-};\ndrivers/net/wireless/mediatek/mt76/mt76x2/usb.c:150:module_usb_driver(mt76x2u_driver);\ndrivers/net/wireless/mediatek/mt76/mt76x2/usb.c-151-\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/usb.c=338=static struct usb_driver mt7921u_driver = {\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/usb.c-350-};\ndrivers/net/wireless/mediatek/mt76/mt7921/usb.c:351:module_usb_driver(mt7921u_driver);\ndrivers/net/wireless/mediatek/mt76/mt7921/usb.c-352-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/usb.c=347=static struct usb_driver mt7925u_driver = {\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/usb.c-359-};\ndrivers/net/wireless/mediatek/mt76/mt7925/usb.c:360:module_usb_driver(mt7925u_driver);\ndrivers/net/wireless/mediatek/mt76/mt7925/usb.c-361-\n"
} |
| 5/2 | 2026/07/25 19:05 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 20064 output: 86 thoughts: 69 Thoughts: **USB Driver Investigations within mt76** Okay, so I'm thinking about the `mt76` project and its USB driver implementations. I already know there are multiple USB drivers present in this codebase. My focus is on the potential for USB fuzzing within this module. I know for sure that I can reach the `mt76` core and the `mt7615` driver through USB fuzzing. That's a good starting point. But I need to expand my scope. Now, I'm wondering about the other drivers in the family – specifically, `mt7915` and `mt7996`. The question is: do they also have USB driver implementations? It's essential to check and see what options are available to get to these drivers to conduct further tests. Time to investigate further and get the answers! |
| 6/2 | 2026/07/25 19:05 | tool | grepper |
0mError:no matches Args: {
"Expression": "module_usb_driver",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7915"
}Results: {
"error": "no matches"
} |
| 7/2 | 2026/07/25 19:06 | tool | grepper |
0mError:no matches Args: {
"Expression": "module_usb_driver",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7996"
}Results: {
"error": "no matches"
} |
| 8/2 | 2026/07/25 19:06 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 20424 output: 88 thoughts: 41 Thoughts: **My Assessment of the MT79xx Series** Okay, so the `mt7915` and `mt7996` – right, those are definitely not USB devices. They are either PCIe, SDIO, or platform devices. Given my experience, the initial instinct is to lean towards PCIe for those. Let's dig deeper and verify if they are indeed PCIe-based. I need to confirm the interface as a first step to determine the proper driver architecture. |
| 9/2 | 2026/07/25 19:06 | tool | grepper |
0mError:no matches Args: {
"Expression": "module_pci_driver",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7915"
}Results: {
"error": "no matches"
} |
| 10/2 | 2026/07/25 19:06 | tool | grepper |
0mError:no matches Args: {
"Expression": "module_pci_driver",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7996"
}Results: {
"error": "no matches"
} |
| 11/2 | 2026/07/25 19:06 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 20680 output: 86 thoughts: 7 Thoughts: Okay, here's my attempt at summarizing the thought process, tailored for an expert audience: **The Registration Conundrum** Alright, hold on a second. This whole process hinges on how they're *registered*. I mean, we're talking about a system, a database, a mechanism for tracking these... *entities*. Are we talking about a simple listing, a more sophisticated relational model, or something far more complex? What's the granularity of the registration? Are we looking at individual components, assemblies, or perhaps even higher-level abstractions? The devil is in the details, and the registration process *is* the detail. Without understanding the fundamental mechanism of this, any further analysis is shooting in the dark. We need to define the method of registration to proceed. |
| 12/2 | 2026/07/25 19:06 | tool | grepper |
0mError:no matches Args: {
"Expression": "module_.*_driver",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7915"
}Results: {
"error": "no matches"
} |
| 13/2 | 2026/07/25 19:06 | tool | grepper |
0mError:no matches Args: {
"Expression": "module_.*_driver",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7996"
}Results: {
"error": "no matches"
} |
| 14/2 | 2026/07/25 19:06 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 20961 output: 72 thoughts: 32 Thoughts: Okay, let's dive into this. Here's how I'd approach this, as if it's my own thought process: **Diving into the MT7915 PCI Driver** Alright, I need to get to the core of this. Based on the likely area of the problem, my first thought is to zero in on the PCI driver code for the MT7915 wireless chipset. Specifically, I'm thinking I should start digging through `drivers/net/wireless/mediatek/mt76/mt7915/pci.c`, or something very similar, depending on how Mediatek organizes its code. That file is probably where the PCI-specific initialization, resource allocation, and interrupt handling for that specific device are defined. This is the place to start looking for a possible cause of the described issue. |
| 15/2 | 2026/07/25 19:06 | tool | codesearch-dir-index |
0mArgs:{
"Dir": "drivers/net/wireless/mediatek/mt76/mt7915"
}Results: {
"Files": [
"coredump.c",
"coredump.h",
"debugfs.c",
"dma.c",
"eeprom.c",
"eeprom.h",
"init.c",
"mac.c",
"mac.h",
"main.c",
"mcu.c",
"mcu.h",
"mmio.c",
"mt7915.h",
"pci.c",
"regs.h",
"soc.c",
"testmode.c",
"testmode.h"
],
"Subdirs": null
} |
| 16/2 | 2026/07/25 19:06 | tool | codesearch-dir-index |
0mArgs:{
"Dir": "drivers/net/wireless/mediatek/mt76/mt7996"
}Results: {
"Files": [
"coredump.c",
"coredump.h",
"debugfs.c",
"dma.c",
"eeprom.c",
"eeprom.h",
"init.c",
"mac.c",
"mac.h",
"main.c",
"mcu.c",
"mcu.h",
"mmio.c",
"mt7996.h",
"npu.c",
"pci.c",
"regs.h"
],
"Subdirs": null
} |
| 17/2 | 2026/07/25 19:06 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 21515 output: 82 thoughts: 18 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience and written in the first person: **Diving into PCI Registration** Okay, so `pci.c` is here, good. Let's get right down to brass tacks: how is this thing registering itself within the system? I need to understand its initialization sequence – specifically, what driver model is it adhering to, and what hooks are being used? I'm anticipating the standard calls to things like `pci_register_driver` or similar functions that handle the device probe and removal routines. I'll need to trace the control flow through the registration process to confirm that assumptions around the driver model are valid, and understand the ordering of initialization and resource allocation. No time to waste; let's dig in and find those registration entry points. |
| 18/2 | 2026/07/25 19:06 | tool | grepper |
0mArgs:{
"Expression": "module_init",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7915"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7915/mmio.c=992=static void __exit mt7915_exit(void)\n--\ndrivers/net/wireless/mediatek/mt76/mt7915/mmio.c-1000-\ndrivers/net/wireless/mediatek/mt76/mt7915/mmio.c:1001:module_init(mt7915_init);\ndrivers/net/wireless/mediatek/mt76/mt7915/mmio.c-1002-module_exit(mt7915_exit);\n"
} |
| 19/2 | 2026/07/25 19:06 | tool | grepper |
0mArgs:{
"Expression": "module_init",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7996"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7996/mmio.c=883=static void __exit mt7996_exit(void)\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/mmio.c-888-\ndrivers/net/wireless/mediatek/mt76/mt7996/mmio.c:889:module_init(mt7996_init);\ndrivers/net/wireless/mediatek/mt76/mt7996/mmio.c-890-module_exit(mt7996_exit);\n"
} |
| 20/2 | 2026/07/25 19:06 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 22126 output: 44 thoughts: 549 Thoughts: **Analyzing the Mediatek Driver Patch** Okay, so I'm looking at this patch and immediately, `mt7915` and `mt7996` catch my eye. They're platform drivers, which means they're likely PCI-based. That's a red flag for QEMU fuzzing unless they're emulated. But hold on, the patch modifies `mt7615/usb_sdio.c`. Ah, that's a USB driver! That's much more promising for fuzzing within a QEMU environment. Let me take a closer look at the diff for `mt7615/usb_sdio.c`. Okay, here we are: ```c --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c @@ -187,10 +187,11 @@ int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr, struct sk_buff *skb = tx_info->skb; struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_key_conf *key = info->control.hw_key; - struct mt7615_sta *msta; + struct mt7615_sta *msta = NULL; int pad, err, pktid; - msta = wcid ? container_of(wcid, struct mt7615_sta, wcid) : NULL; + if (wcid && wcid->sta) + msta = container_of(wcid, struct mt7615_sta, wcid); if (!wcid) wcid = &dev->mt76.global_wcid; ``` Ah, the code now includes a null check on `wcid->sta` before dereferencing it. This is definitely reachable via USB fuzzing! That's the target I need to focus on. But wait, this isn't just a simple fix to the `usb_sdio.c` file! I see modifications to `mt76` core files like `dma.c`, `mmio.c`, `scan.c`, `mt76_connac_mac.c`, and `mt76_connac_mcu.c` are also included. Now, are `mt76_connac_mac.c` and `mt76_connac_mcu.c` actually used by `mt7615`? Time to investigate that connection... |
| 21/2 | 2026/07/25 19:06 | tool | grepper |
0mArgs:{
"Expression": "mt76_connac",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7615"
}Results: {
"Output": "\nFull output is too long, showing 500 out of 772 lines.\nUse more precise expression if possible.\n\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c=51=static int mt7615_config(void *data, u64 val)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-56-\tmt7615_mutex_acquire(dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c:57:\tret = mt76_connac_mcu_chip_config(\u0026dev-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-58-\tmt7615_mutex_release(dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c=96=mt7615_pm_set(void *data, u64 val)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-98-\tstruct mt7615_dev *dev = data;\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c:99:\tstruct mt76_connac_pm *pm = \u0026dev-\u003epm;\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-100-\tint ret = 0;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-125-\tpm-\u003eenable = false;\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c:126:\tmt76_connac_pm_wake(\u0026dev-\u003emphy, pm);\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-127-\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-128-\tpm-\u003eenable = val;\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c:129:\tmt76_connac_power_save_sched(\u0026dev-\u003emphy, pm);\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-130-out:\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c=149=mt7615_pm_stats(struct seq_file *s, void *data)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-151-\tstruct mt7615_dev *dev = dev_get_drvdata(s-\u003eprivate);\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c:152:\tstruct mt76_connac_pm *pm = \u0026dev-\u003epm;\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-153-\tunsigned long awake_time = pm-\u003estats.awake_time;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c=45=mt7615_init_tx_queues(struct mt7615_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-56-\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c:57:\tret = mt76_connac_init_tx_queues(\u0026dev-\u003emphy, 0, MT7615_TX_RING_SIZE,\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-58-\t\t\t\t\t MT_TX_RING_BASE, NULL, 0);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c=66=static int mt7615_poll_tx(struct napi_struct *napi, int budget)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-70-\tdev = mt76_priv(napi-\u003edev);\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c:71:\tif (!mt76_connac_pm_ref(\u0026dev-\u003emphy, \u0026dev-\u003epm)) {\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-72-\t\tnapi_complete(napi);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-78-\tif (napi_complete(napi))\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c:79:\t\tmt76_connac_irq_enable(\u0026dev-\u003emt76,\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-80-\t\t\t\t mt7615_tx_mcu_int_mask(dev));\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-81-\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c:82:\tmt76_connac_pm_unref(\u0026dev-\u003emphy, \u0026dev-\u003epm);\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-83-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c=87=static int mt7615_poll_rx(struct napi_struct *napi, int budget)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-93-\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c:94:\tif (!mt76_connac_pm_ref(\u0026dev-\u003emphy, \u0026dev-\u003epm)) {\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-95-\t\tnapi_complete(napi);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-99-\tdone = mt76_dma_rx_poll(napi, budget);\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c:100:\tmt76_connac_pm_unref(\u0026dev-\u003emphy, \u0026dev-\u003epm);\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-101-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c=220=int mt7615_dma_init(struct mt7615_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-300-\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c:301:\tmt76_connac_irq_enable(\u0026dev-\u003emt76, mask);\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-302-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c=136=mt7615_mac_init(struct mt7615_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c-151-\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c:152:\tmt76_connac_mcu_set_rts_thresh(\u0026dev-\u003emt76, 0x92b, 0);\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c-153-\tmt7615_mac_set_scs(\u0026dev-\u003ephy, true);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c=319=void mt7615_init_work(struct mt7615_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c-323-\tmt7615_phy_init(dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c:324:\tmt76_connac_mcu_del_wtbl_all(\u0026dev-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c-325-\tmt7615_check_offload_capability(dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c=330=mt7615_regd_notifier(struct wiphy *wiphy,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c-350-\tif (mt7615_firmware_offload(phy-\u003edev)) {\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c:351:\t\tmt76_connac_mcu_set_channel_domain(mphy);\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c:352:\t\tmt76_connac_mcu_set_rate_txpower(mphy);\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c-353-\t}\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c=466=mt7615_led_set_config(struct led_classdev *led_cdev,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c-476-\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c:477:\tif (!mt76_connac_pm_ref(mphy, \u0026dev-\u003epm))\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c-478-\t\treturn;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c-498-\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c:499:\tmt76_connac_pm_unref(mphy, \u0026dev-\u003epm);\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c-500-}\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c=1517=mt7615_txwi_free(struct mt7615_dev *dev, struct mt76_txwi_cache *txwi)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-1523-\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c:1524:\tmt76_connac_txp_skb_unmap(mdev, txwi);\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-1525-\tif (!txwi-\u003eskb)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c=1552=static void mt7615_mac_tx_free(struct mt7615_dev *dev, void *data, int len)\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-1553-{\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c:1554:\tstruct mt76_connac_tx_free *free = data;\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-1555-\tvoid *tx_token = data + sizeof(*free);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c=1945=void mt7615_update_channel(struct mt76_phy *mphy)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-1948-\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c:1949:\tif (mt76_connac_pm_wake(\u0026dev-\u003emphy, \u0026dev-\u003epm))\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-1950-\t\treturn;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-1952-\tmt7615_update_survey(dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c:1953:\tmt76_connac_power_save_sched(\u0026dev-\u003emphy, \u0026dev-\u003epm);\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-1954-}\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c=1994=void mt7615_pm_wake_work(struct work_struct *work)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2007-\t\tif (mt76_is_sdio(mdev)) {\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c:2008:\t\t\tmt76_connac_pm_dequeue_skbs(mphy, \u0026dev-\u003epm);\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2009-\t\t\tmt76_worker_schedule(\u0026mdev-\u003esdio.txrx_worker);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2014-\t\t\tlocal_bh_enable();\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c:2015:\t\t\tmt76_connac_pm_dequeue_skbs(mphy, \u0026dev-\u003epm);\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2016-\t\t\tmt76_queue_tx_cleanup(dev, mdev-\u003eq_mcu[MT_MCUQ_WM],\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c=2106=static void mt7615_dfs_stop_radar_detector(struct mt7615_phy *phy)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2110-\tif (phy-\u003erdd_state \u0026 BIT(0))\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c:2111:\t\tmt76_connac_mcu_rdd_cmd(\u0026dev-\u003emt76, RDD_STOP, 0,\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2112-\t\t\t\t\tMT_RX_SEL0, 0);\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2113-\tif (phy-\u003erdd_state \u0026 BIT(1))\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c:2114:\t\tmt76_connac_mcu_rdd_cmd(\u0026dev-\u003emt76, RDD_STOP, 1,\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2115-\t\t\t\t\tMT_RX_SEL0, 0);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c=2118=static int mt7615_dfs_start_rdd(struct mt7615_dev *dev, int chain)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2121-\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c:2122:\terr = mt76_connac_mcu_rdd_cmd(\u0026dev-\u003emt76, RDD_START, chain,\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2123-\t\t\t\t MT_RX_SEL0, 0);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2126-\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c:2127:\treturn mt76_connac_mcu_rdd_cmd(\u0026dev-\u003emt76, RDD_DET_MODE, chain,\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2128-\t\t\t\t MT_RX_SEL0, 1);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c=2131=static int mt7615_dfs_start_radar_detector(struct mt7615_phy *phy)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2138-\t/* start CAC */\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c:2139:\terr = mt76_connac_mcu_rdd_cmd(\u0026dev-\u003emt76, RDD_CAC_START, ext_phy,\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2140-\t\t\t\t MT_RX_SEL0, 0);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c=2199=int mt7615_dfs_init_radar_detector(struct mt7615_phy *phy)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2236-\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c:2237:\terr = mt76_connac_mcu_rdd_cmd(\u0026dev-\u003emt76, RDD_CAC_END,\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2238-\t\t\t\t ext_phy, MT_RX_SEL0, 0);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2247-stop:\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c:2248:\terr = mt76_connac_mcu_rdd_cmd(\u0026dev-\u003emt76, RDD_NORMAL_START, ext_phy,\ndrivers/net/wireless/mediatek/mt76/mt7615/mac.c-2249-\t\t\t\t MT_RX_SEL0, 0);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=27=static int mt7615_start(struct ieee80211_hw *hw)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-46-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:47:\t\tret = mt76_connac_mcu_set_mac_enable(\u0026dev-\u003emt76, 0, true, false);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-48-\t\tif (ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-58-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:59:\t\tret = mt76_connac_mcu_set_mac_enable(\u0026dev-\u003emt76, 1, true, false);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-60-\t\tif (ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-66-\tif (mt7615_firmware_offload(dev)) {\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:67:\t\tret = mt76_connac_mcu_set_channel_domain(phy-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-68-\t\tif (ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-70-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:71:\t\tret = mt76_connac_mcu_set_rate_txpower(phy-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-72-\t\tif (ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=94=static void mt7615_stop(struct ieee80211_hw *hw, bool suspend)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-105-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:106:\tmt76_connac_free_pending_tx_skbs(\u0026dev-\u003epm, NULL);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-107-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-116-\t\tmt7615_mcu_set_pm(dev, 1, 1);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:117:\t\tmt76_connac_mcu_set_mac_enable(\u0026dev-\u003emt76, 1, false, false);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-118-\t}\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-121-\t\tmt7615_mcu_set_pm(dev, 0, 1);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:122:\t\tmt76_connac_mcu_set_mac_enable(\u0026dev-\u003emt76, 0, false, false);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-123-\t}\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=246=static void mt7615_remove_interface(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-263-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:264:\tmt76_connac_free_pending_tx_skbs(\u0026dev-\u003epm, \u0026msta-\u003ewcid);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-265-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=284=int mt7615_set_channel(struct mt76_phy *mphy)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-290-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:291:\tmt76_connac_pm_wake(mphy, \u0026dev-\u003epm);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-292-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-321-out:\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:322:\tmt76_connac_power_save_sched(mphy, \u0026dev-\u003epm);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-323-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=335=static int mt7615_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-379-\tif (cmd == SET_KEY \u0026\u0026 !sta \u0026\u0026 !mvif-\u003emt76.cipher) {\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:380:\t\tmvif-\u003emt76.cipher = mt76_connac_mcu_get_cipher(key-\u003ecipher);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-381-\t\tmt7615_mcu_add_bss_info(phy, vif, NULL, true);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=404=static int mt7615_set_sar_specs(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-417-\tif (mt7615_firmware_offload(phy-\u003edev))\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:418:\t\treturn mt76_connac_mcu_set_rate_txpower(phy-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-419-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=567=static void mt7615_bss_info_changed(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-590-\t\tif (mt7615_firmware_offload(dev) \u0026\u0026 vif-\u003ep2p)\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:591:\t\t\tmt76_connac_mcu_set_p2p_oppps(hw, vif);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-592-\t}\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-602-\tif (changed \u0026 BSS_CHANGED_PS)\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:603:\t\tmt76_connac_mcu_set_vif_ps(\u0026dev-\u003emt76, vif);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-604-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-608-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:609:\t\tmt76_connac_mcu_update_arp_filter(\u0026dev-\u003emt76, \u0026mvif-\u003emt76,\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-610-\t\t\t\t\t\t info);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=634=int mt7615_mac_sta_add(struct mt76_dev *mdev, struct ieee80211_vif *vif,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-653-\tphy = mvif-\u003emt76.band_idx ? mt7615_ext_phy(dev) : \u0026dev-\u003ephy;\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:654:\terr = mt76_connac_pm_wake(phy-\u003emt76, \u0026dev-\u003epm);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-655-\tif (err)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-669-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:670:\tmt76_connac_power_save_sched(phy-\u003emt76, \u0026dev-\u003epm);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-671-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=676=void mt7615_mac_sta_remove(struct mt76_dev *mdev, struct ieee80211_vif *vif,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-683-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:684:\tmt76_connac_free_pending_tx_skbs(\u0026dev-\u003epm, \u0026msta-\u003ewcid);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-685-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-686-\tphy = mvif-\u003emt76.band_idx ? mt7615_ext_phy(dev) : \u0026dev-\u003ephy;\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:687:\tmt76_connac_pm_wake(phy-\u003emt76, \u0026dev-\u003epm);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-688-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-699-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:700:\tmt76_connac_power_save_sched(phy-\u003emt76, \u0026dev-\u003epm);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-701-}\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=704=static void mt7615_sta_rate_tbl_update(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-726-\tmsta-\u003en_rates = i;\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:727:\tif (mt76_connac_pm_ref(phy-\u003emt76, \u0026dev-\u003epm)) {\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-728-\t\tmt7615_mac_set_rates(phy, msta, NULL, msta-\u003erates);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:729:\t\tmt76_connac_pm_unref(phy-\u003emt76, \u0026dev-\u003epm);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-730-\t}\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=734=void mt7615_tx_worker(struct mt76_worker *w)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-738-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:739:\tif (!mt76_connac_pm_ref(\u0026dev-\u003emphy, \u0026dev-\u003epm)) {\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-740-\t\tqueue_work(dev-\u003emt76.wq, \u0026dev-\u003epm.wake_work);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-744-\tmt76_tx_worker_run(\u0026dev-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:745:\tmt76_connac_pm_unref(\u0026dev-\u003emphy, \u0026dev-\u003epm);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-746-}\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=748=static void mt7615_tx(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-772-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:773:\tif (mt76_connac_pm_ref(mphy, \u0026dev-\u003epm)) {\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-774-\t\tmt76_tx(mphy, control-\u003esta, wcid, skb);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:775:\t\tmt76_connac_pm_unref(mphy, \u0026dev-\u003epm);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-776-\t\treturn;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-784-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:785:\tmt76_connac_pm_queue_skb(hw, \u0026dev-\u003epm, wcid, skb);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-786-}\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=788=static int mt7615_set_rts_threshold(struct ieee80211_hw *hw, int radio_idx,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-795-\tmt7615_mutex_acquire(dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:796:\terr = mt76_connac_mcu_set_rts_thresh(\u0026dev-\u003emt76, val, band);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-797-\tmt7615_mutex_release(dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=1089=mt7615_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1100-\tmt7615_mutex_acquire(dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:1101:\terr = mt76_connac_mcu_hw_scan(mphy, vif, req);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1102-\tmt7615_mutex_release(dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=1108=mt7615_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1113-\tmt7615_mutex_acquire(dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:1114:\tmt76_connac_mcu_cancel_hw_scan(mphy, vif);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1115-\tmt7615_mutex_release(dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=1119=mt7615_start_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1131-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:1132:\terr = mt76_connac_mcu_sched_scan_req(mphy, vif, req);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1133-\tif (err \u003c 0)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1135-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:1136:\terr = mt76_connac_mcu_sched_scan_enable(mphy, vif, true);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1137-out:\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=1144=mt7615_stop_sched_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1153-\tmt7615_mutex_acquire(dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:1154:\terr = mt76_connac_mcu_sched_scan_enable(mphy, vif, false);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1155-\tmt7615_mutex_release(dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=1232=static int mt7615_suspend(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1239-\tcancel_delayed_work_sync(\u0026dev-\u003epm.ps_work);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:1240:\tmt76_connac_free_pending_tx_skbs(\u0026dev-\u003epm, NULL);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1241-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1250-\t\t\t\t\t IEEE80211_IFACE_ITER_RESUME_ALL,\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:1251:\t\t\t\t\t mt76_connac_mcu_set_suspend_iter,\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1252-\t\t\t\t\t phy-\u003emt76);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1254-\tif (!mt7615_dev_running(dev))\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:1255:\t\terr = mt76_connac_mcu_set_hif_suspend(\u0026dev-\u003emt76, true, true);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1256-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=1262=static int mt7615_resume(struct ieee80211_hw *hw)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1276-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:1277:\t\terr = mt76_connac_mcu_set_hif_suspend(\u0026dev-\u003emt76, false, true);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1278-\t\tif (err \u003c 0) {\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1286-\t\t\t\t\t IEEE80211_IFACE_ITER_RESUME_ALL,\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:1287:\t\t\t\t\t mt76_connac_mcu_set_suspend_iter,\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1288-\t\t\t\t\t phy-\u003emt76);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c=1306=static void mt7615_set_rekey_data(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1312-\tmt7615_mutex_acquire(dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:1313:\tmt76_connac_mcu_update_gtk_rekey(hw, vif, data);\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-1314-\tmt7615_mutex_release(dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c=135=int mt7615_mcu_parse_response(struct mt76_dev *mdev, int cmd,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-165-\t\t cmd == MCU_UNI_CMD(SUSPEND)) {\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:166:\t\tstruct mt76_connac_mcu_uni_event *event;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-167-\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-168-\t\tskb_pull(skb, sizeof(*rxd));\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:169:\t\tevent = (struct mt76_connac_mcu_uni_event *)skb-\u003edata;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-170-\t\tret = le32_to_cpu(event-\u003estatus);\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-171-\t} else if (cmd == MCU_CE_QUERY(REG_READ)) {\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:172:\t\tstruct mt76_connac_mcu_reg_event *event;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-173-\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-174-\t\tskb_pull(skb, sizeof(*rxd));\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:175:\t\tevent = (struct mt76_connac_mcu_reg_event *)skb-\u003edata;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-176-\t\tret = (int)le32_to_cpu(event-\u003eval);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c=241=static int mt7615_mcu_drv_pmctrl(struct mt7615_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-243-\tstruct mt76_phy *mphy = \u0026dev-\u003emt76.phy;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:244:\tstruct mt76_connac_pm *pm = \u0026dev-\u003epm;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-245-\tstruct mt76_dev *mdev = \u0026dev-\u003emt76;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c=281=static int mt7615_mcu_lp_drv_pmctrl(struct mt7615_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-283-\tstruct mt76_phy *mphy = \u0026dev-\u003emt76.phy;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:284:\tstruct mt76_connac_pm *pm = \u0026dev-\u003epm;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-285-\tint i, err = 0;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c=315=static int mt7615_mcu_fw_pmctrl(struct mt7615_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-317-\tstruct mt76_phy *mphy = \u0026dev-\u003emt76.phy;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:318:\tstruct mt76_connac_pm *pm = \u0026dev-\u003epm;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-319-\tint err = 0;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-323-\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:324:\tif (mt76_connac_skip_fw_pmctrl(mphy, pm))\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-325-\t\tgoto out;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c=494=mt7615_mcu_beacon_loss_event(struct mt7615_dev *dev, struct sk_buff *skb)\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-495-{\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:496:\tstruct mt76_connac_beacon_loss_event *event;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-497-\tstruct mt76_phy *mphy;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-500-\tskb_pull(skb, sizeof(struct mt7615_mcu_rxd));\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:501:\tevent = (struct mt76_connac_beacon_loss_event *)skb-\u003edata;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-502-\tif (band_idx \u0026\u0026 dev-\u003emt76.phys[MT_BAND1])\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-508-\t\t\t\t\tIEEE80211_IFACE_ITER_RESUME_ALL,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:509:\t\t\t\t\tmt76_connac_mcu_beacon_loss_iter,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-510-\t\t\t\t\tevent);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c=514=mt7615_mcu_bss_event(struct mt7615_dev *dev, struct sk_buff *skb)\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-515-{\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:516:\tstruct mt76_connac_mcu_bss_event *event;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-517-\tstruct mt76_phy *mphy;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-520-\tskb_pull(skb, sizeof(struct mt7615_mcu_rxd));\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:521:\tevent = (struct mt76_connac_mcu_bss_event *)skb-\u003edata;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-522-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c=535=mt7615_mcu_rx_unsolicited_event(struct mt7615_dev *dev, struct sk_buff *skb)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-556-\tcase MCU_EVENT_COREDUMP:\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:557:\t\tmt76_connac_mcu_coredump_event(\u0026dev-\u003emt76, skb,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-558-\t\t\t\t\t \u0026dev-\u003ecoredump);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c=734=mt7615_mcu_ctrl_pm_state(struct mt7615_dev *dev, int band, int state)\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-735-{\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:736:\treturn mt76_connac_mcu_set_pm(\u0026dev-\u003emt76, band, state);\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-737-}\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c=740=mt7615_mcu_add_bss(struct mt7615_phy *phy, struct ieee80211_vif *vif,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-749-\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:750:\tskb = mt76_connac_mcu_alloc_sta_req(\u0026dev-\u003emt76, \u0026mvif-\u003emt76, NULL);\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-751-\tif (IS_ERR(skb))\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-754-\tif (enable)\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:755:\t\tmt76_connac_mcu_bss_omac_tlv(skb, vif);\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-756-\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:757:\tmt76_connac_mcu_bss_basic_tlv(skb, vif, sta, phy-\u003emt76,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-758-\t\t\t\t mvif-\u003esta.wcid.idx, enable);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-761-\t mvif-\u003emt76.omac_idx \u003c REPEATER_BSSID_START)\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:762:\t\tmt76_connac_mcu_bss_ext_tlv(skb, \u0026mvif-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-763-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c=769=mt7615_mcu_wtbl_tx_ba(struct mt7615_dev *dev,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-778-\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:779:\twtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(\u0026dev-\u003emt76, \u0026msta-\u003ewcid,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-780-\t\t\t\t\t\t WTBL_SET, NULL, \u0026skb);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-783-\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:784:\tmt76_connac_mcu_wtbl_ba_tlv(\u0026dev-\u003emt76, skb, params, enable, true,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-785-\t\t\t\t NULL, wtbl_hdr);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-791-\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:792:\tskb = mt76_connac_mcu_alloc_sta_req(\u0026dev-\u003emt76, \u0026mvif-\u003emt76,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-793-\t\t\t\t\t \u0026msta-\u003ewcid);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-796-\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:797:\tmt76_connac_mcu_sta_ba_tlv(skb, params, enable, true);\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-798-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c=804=mt7615_mcu_wtbl_rx_ba(struct mt7615_dev *dev,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-813-\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:814:\tskb = mt76_connac_mcu_alloc_sta_req(\u0026dev-\u003emt76, \u0026mvif-\u003emt76,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-815-\t\t\t\t\t \u0026msta-\u003ewcid);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-818-\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:819:\tmt76_connac_mcu_sta_ba_tlv(skb, params, enable, false);\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-820-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-826-\tskb = NULL;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:827:\twtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(\u0026dev-\u003emt76, \u0026msta-\u003ewcid,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-828-\t\t\t\t\t\t WTBL_SET, NULL, \u0026skb);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-831-\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:832:\tmt76_connac_mcu_wtbl_ba_tlv(\u0026dev-\u003emt76, skb, params, enable, false,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-833-\t\t\t\t NULL, wtbl_hdr);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c=840=mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-855-\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:856:\tsskb = mt76_connac_mcu_alloc_sta_req(\u0026dev-\u003emt76, \u0026mvif-\u003emt76,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-857-\t\t\t\t\t \u0026msta-\u003ewcid);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-867-\tconn_state = enable ? CONN_STATE_PORT_SECURE : CONN_STATE_DISCONNECT;\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:868:\tmt76_connac_mcu_sta_basic_tlv(\u0026dev-\u003emt76, sskb, \u0026vif-\u003ebss_conf,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-869-\t\t\t\t link_sta, conn_state, new_entry);\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-870-\tif (enable \u0026\u0026 sta)\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:871:\t\tmt76_connac_mcu_sta_tlv(phy-\u003emt76, sskb, sta, vif, 0,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-872-\t\t\t\t\tMT76_STA_INFO_STATE_ASSOC);\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-873-\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:874:\twtbl_hdr = mt76_connac_mcu_alloc_wtbl_req(\u0026dev-\u003emt76, \u0026msta-\u003ewcid,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-875-\t\t\t\t\t\t WTBL_RESET_AND_SET, NULL,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-882-\tif (enable) {\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:883:\t\tmt76_connac_mcu_wtbl_generic_tlv(\u0026dev-\u003emt76, wskb, vif, sta,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-884-\t\t\t\t\t\t NULL, wtbl_hdr);\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-885-\t\tif (sta)\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:886:\t\t\tmt76_connac_mcu_wtbl_ht_tlv(\u0026dev-\u003emt76, wskb, sta,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-887-\t\t\t\t\t\t NULL, wtbl_hdr, true, true);\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:888:\t\tmt76_connac_mcu_wtbl_hdr_trans_tlv(wskb, vif, \u0026msta-\u003ewcid,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-889-\t\t\t\t\t\t NULL, wtbl_hdr);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c=910=mt7615_mcu_wtbl_update_hdr_trans(struct mt7615_dev *dev,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-913-{\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:914:\treturn mt76_connac_mcu_wtbl_update_hdr_trans(\u0026dev-\u003emt76, vif, sta);\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-915-}\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c=931=mt7615_mcu_sta_ba(struct mt7615_dev *dev,\n\n"
} |
| 22/2 | 2026/07/25 19:06 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 39907 output: 47 thoughts: 2416 Thoughts: **Fuzzing Feasibility and Patch Analysis for MT7615 USB Driver** Okay, so I've confirmed that the `mt7615` driver utilizes `mt76_connac_mac.c` and `mt76_connac_mcu.c`. Plus, there's a USB driver available for `mt7615`! That's a key observation. This means that the code changes in `mt7615/usb_sdio.c`, `mt76_connac_mac.c`, and `mt76_connac_mcu.c` are all potentially reachable through USB fuzzing. We can use a dummy HCD for this. Let's dive into these patches to understand the potential attack surface. The first patch addresses a possible null pointer dereference in `mt7615/usb_sdio.c`. It's a conditional check now, ensuring `wcid->sta` exists before dereferencing it. The comment clarifies `wcid` might not be for a station wcid. This is a functional fix. Next, `mt76_connac_mac.c` has a functional change to improve how the hardware reports the NSS for STBC frames. `mt76_connac_mcu.c` includes another functional change related to HE capabilities; it looks like a typo fix, assigning the maximum RU capability. `mt76/dma.c` has a functional change with an added condition for the `MT_DMA_CTL_WO_DROP` on a specific WED version. Finally, `mt76/scan.c` introduces locking and more nuanced channel setting logic during scans. Given all these functional changes and the existence of a USB driver for the `mt7615`, I think it's worth it! Yes, the `mt7615` USB driver is, in fact, `mt7663u`. Now, I should investigate `mt7615/usb.c` to see if this is enabled by a configuration option. |
| 23/2 | 2026/07/25 19:06 | tool | grepper |
0mArgs:{
"Expression": "config MT7615",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7615/Kconfig"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7615/Kconfig-2-\ndrivers/net/wireless/mediatek/mt76/mt7615/Kconfig:3:config MT7615_COMMON\ndrivers/net/wireless/mediatek/mt76/mt7615/Kconfig-4-\ttristate\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/Kconfig-7-\ndrivers/net/wireless/mediatek/mt76/mt7615/Kconfig:8:config MT7615E\ndrivers/net/wireless/mediatek/mt76/mt7615/Kconfig-9-\ttristate \"MediaTek MT7615E and MT7663E (PCIe) support\"\n"
} |
| 24/2 | 2026/07/25 19:06 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 43033 output: 48 thoughts: 14 Thoughts: Okay, let's dive into this. Here's how I'd approach this task, as if these were my internal thoughts: **Analyzing the mt7663u Configuration** Alright, time to get to work. First things first, I need to take a look at this `mt7663u` configuration. I need to understand its setup, its parameters, and how it's interacting within the broader system. I'll be looking for anything that stands out, any potential bottlenecks, or anything that seems out of the ordinary. My initial scan will be for key settings related to its function, particularly any wireless or USB aspects, since it looks like a Mediatek part and a USB connection is referenced in the name. I'll mentally map out the relevant sections and compare them to my prior experience with similar hardware configurations. I'm expecting to see things like driver versions, power settings, maybe some MAC address configurations, and of course, interface settings. Let's get started. |
| 25/2 | 2026/07/25 19:06 | tool | grepper |
0mArgs:{
"Expression": "config MT7663U",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7615/Kconfig"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7615/Kconfig=32=config MT7663_USB_SDIO_COMMON\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/Kconfig-35-\ndrivers/net/wireless/mediatek/mt76/mt7615/Kconfig:36:config MT7663U\ndrivers/net/wireless/mediatek/mt76/mt7615/Kconfig-37-\ttristate \"MediaTek MT7663U (USB) support\"\n"
} |
| 26/2 | 2026/07/25 19:06 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 43461 output: 48 thoughts: 14 Thoughts: Here's my take on those thoughts: **Analyzing the Dependency Landscape for MT7663U** Okay, so I need to get a handle on the `MT7663U` situation. My first step is clear: I need to really dig into its dependencies. I'm thinking, this isn't just a simple module, and experience tells me there's likely a whole web of related components and drivers that it relies on. I want to build a quick mental map of *everything* that feeds into this thing, and *everything* it might affect. I need to understand all the potential weak points. Any downstream impacts? Any legacy code lurking that I need to be aware of? Best to get all of that figured out now before moving forward. Let's see what's what. |
| 27/2 | 2026/07/25 19:06 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/mediatek/mt76/mt7615/Kconfig",
"FirstLine": 36,
"LineCount": 10
}Results: {
"Contents": " 36:\tconfig MT7663U\n 37:\t\ttristate \"MediaTek MT7663U (USB) support\"\n 38:\t\tselect MT76_USB\n 39:\t\tselect MT7663_USB_SDIO_COMMON\n 40:\t\tdepends on MAC80211\n 41:\t\tdepends on USB\n 42:\t\thelp\n 43:\t\t This adds support for MT7663U 802.11ac 2x2:2 wireless devices.\n 44:\t\n 45:\t\t To compile this driver as a module, choose M here.\n"
} |
| 28/2 | 2026/07/25 19:06 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 43862 output: 48 thoughts: 29 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **USB Driver Configuration - A Quick Check** Right, so I'm looking at the driver configuration files, and `MT7663U` jumps out as the USB driver for a specific hardware revision. Standard naming convention, makes perfect sense. But my mind immediately jumps to the next likely candidate. Now, I need to make sure I'm not missing anything. What about `MT7921U`? Is that the successor or perhaps a variation for a different platform? Gotta keep my mental map current. Need to quickly recall if there are any known compatibility issues or architecture changes to consider. Always be thorough when configuring the network stack, as unexpected issues will otherwise surface in the field. |
| 29/2 | 2026/07/25 19:06 | tool | grepper |
0mArgs:{
"Expression": "config MT7921U",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7921/Kconfig"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7921/Kconfig=17=config MT7921S\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/Kconfig-27-\ndrivers/net/wireless/mediatek/mt76/mt7921/Kconfig:28:config MT7921U\ndrivers/net/wireless/mediatek/mt76/mt7921/Kconfig-29-\ttristate \"MediaTek MT7921U (USB) support\"\n"
} |
| 30/2 | 2026/07/25 19:06 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 44255 output: 46 thoughts: 378 Thoughts: **Analyzing the Fuzzing Potential of This Patch** Okay, so this patch hits `mt7915` and `mt7996`. My initial thought is to ask about USB drivers, but wait, we already know those are PCIe only. Right, PCIe drivers... can we even fuzz those? Hmm, let's see, the criteria state: "Return WorthFuzzing=false if the patch only contains code in vendor-specific PCIe... drivers that require physical PCIe hardware cards not emulated in standard QEMU". That sounds like it applies here – `mt7915` and `mt7996` are definitely vendor-specific PCIe wireless drivers, and they are *not* emulated in standard QEMU. So far, the changes *there* are a dead end for fuzzing. But hold on, the patch *also* modifies `mt7615/usb_sdio.c` and some core `mt76` files (`dma.c`, `scan.c`, etc.). Aha! `mt7615` *does* have a USB driver – `mt7663u`, if memory serves. Bingo! That means changes to `mt7615/usb_sdio.c` *are* reachable via USB fuzzing! This changes everything. Now, just to be absolutely sure, it's worth double-checking that `mt7615/usb_sdio.c` is actually compiled for `MT7663U`. Need to confirm this is relevant before continuing to assess this for fuzzing purposes. |
| 31/2 | 2026/07/25 19:07 | tool | grepper |
0mArgs:{
"Expression": "usb_sdio.o",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7615/Makefile"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7615/Makefile=16=mt7615e-$(CONFIG_MT7622_WMAC) += soc.o\ndrivers/net/wireless/mediatek/mt76/mt7615/Makefile-17-\ndrivers/net/wireless/mediatek/mt76/mt7615/Makefile:18:mt7663-usb-sdio-common-y := usb_sdio.o\ndrivers/net/wireless/mediatek/mt76/mt7615/Makefile-19-mt7663u-y := usb.o usb_mcu.o\n"
} |
| 32/2 | 2026/07/25 19:07 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 45203 output: 44 thoughts: 115 Thoughts: Okay, let me think this through. **Analyzing the MT7663U Compilation Path** Alright, so `mt7663-usb-sdio-common-y := usb_sdio.o` definitely ties the `usb_sdio.o` object file to the `mt7663-usb-sdio-common` configuration. Good. And, confirmation: `MT7663U` is set to select `MT7663_USB_SDIO_COMMON`. That confirms that the driver source for `mt7615/usb_sdio.c` is going to be built when the `MT7663U` configuration is enabled, and is accessible via USB. So far, so good, this seems logical. Now, let me shift gears slightly. What about the connection-specific MAC and MCU code, like `mt76_connac_mac.c` and `mt76_connac_mcu.c`? Are those, in fact, compiled and included in the build process for the `MT7663U` configuration? That's the next logical piece to figure out. I'll need to trace the dependencies to be sure. |
| 33/2 | 2026/07/25 19:07 | tool | grepper |
0mArgs:{
"Expression": "mt76_connac_mac.o",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/Makefile"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/Makefile=32=mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o\ndrivers/net/wireless/mediatek/mt76/Makefile-33-\ndrivers/net/wireless/mediatek/mt76/Makefile:34:mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o mt76_connac3_mac.o\ndrivers/net/wireless/mediatek/mt76/Makefile-35-\n"
} |
| 34/2 | 2026/07/25 19:07 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 45796 output: 42 thoughts: 16 Thoughts: Okay, let's dive into this. Here's my thought process on dissecting the `mt76-connac-lib` selection: **Investigating the `mt76-connac-lib` Selection** Alright, the first question I'm asking myself is *why* is `mt76-connac-lib` being selected. It's a key component, so understanding its dependencies and triggers is crucial. Is it being pulled in directly by something, or is it a transitive dependency? If it's the latter, what's *its* dependency chain? I need to trace this back. I'll probably start by grepping the build system files – Makefiles, Kconfig files, configuration scripts – to pinpoint the exact locations where this selection occurs. I'm looking for keywords like `select`, `depends on`, or `CONFIG_`. Understanding the context is key. What configuration options trigger its inclusion? Is it tied to a specific board, wireless chipset, or kernel version? Then, I'll need to think about the functionality it provides. What are the key features and modules associated with `mt76-connac-lib`? Does it handle WiFi, Bluetooth, or some other interface? Understanding its role will help interpret *why* it's being selected and how it interacts with other components in the system. Essentially, I'm aiming for a complete understanding of its role, direct dependencies, and any indirect dependencies to fully understand its inclusion in the system build. Once I understand the *why*, I can then determine if this is the correct behavior or if further investigation is needed. |
| 35/2 | 2026/07/25 19:07 | tool | grepper |
0mArgs:{
"Expression": "mt76-connac-lib",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/Makefile"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/Makefile=6=obj-$(CONFIG_MT76x02_USB) += mt76x02-usb.o\ndrivers/net/wireless/mediatek/mt76/Makefile:7:obj-$(CONFIG_MT76_CONNAC_LIB) += mt76-connac-lib.o\ndrivers/net/wireless/mediatek/mt76/Makefile-8-obj-$(CONFIG_MT792x_LIB) += mt792x-lib.o\n--\ndrivers/net/wireless/mediatek/mt76/Makefile=32=mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o\ndrivers/net/wireless/mediatek/mt76/Makefile-33-\ndrivers/net/wireless/mediatek/mt76/Makefile:34:mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o mt76_connac3_mac.o\ndrivers/net/wireless/mediatek/mt76/Makefile-35-\n"
} |
| 36/2 | 2026/07/25 19:07 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 46492 output: 44 thoughts: 20 Thoughts: Okay, here's my interpretation of that thought process, from an expert's perspective: **Diving into the Kernel Configuration for MT76's CONNAC Library** Right, let's get down to brass tacks. I need to understand the configuration status of `CONFIG_MT76_CONNAC_LIB`. This is a critical building block within the MT76 wireless stack, and its state dictates a whole lot about how the ConNAC (concurrent network access) features are handled. I'm going to quickly check the `Kconfig` files, probably starting with the core MT76 Kconfig, to see if it's enabled, disabled, or if it has any dependencies. I’m thinking I’ll see what’s defined, what its default settings are, and if any other configurations might indirectly affect this module. It’s imperative to have this information, because it will impact any further analysis or development I’m doing with the MT76 stack. I have to see how it’s currently configured in order to move forward intelligently. This is a foundational step. |
| 37/2 | 2026/07/25 19:07 | tool | grepper |
0mArgs:{
"Expression": "config MT76_CONNAC_LIB",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/Kconfig"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/Kconfig=24=config MT76x02_USB\n--\ndrivers/net/wireless/mediatek/mt76/Kconfig-27-\ndrivers/net/wireless/mediatek/mt76/Kconfig:28:config MT76_CONNAC_LIB\ndrivers/net/wireless/mediatek/mt76/Kconfig-29-\ttristate\n"
} |
| 38/2 | 2026/07/25 19:07 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 46902 output: 42 thoughts: 16 Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and presented as if it were my own internal monologue: **Investigating the `MT76_CONNAC_LIB` Dependency** Alright, time to get to the bottom of this. My initial thought process is geared towards understanding the context around this specific library, `MT76_CONNAC_LIB`. I need to figure out *what* exactly is selecting it. I'm assuming it's part of a larger configuration puzzle, likely related to networking or wireless functionality within the `MT76` driver suite. The 'selecting' aspect indicates a dependency relationship, so I need to trace this back. Is it a direct dependency defined in a `Kconfig` file, or is it triggered indirectly through another option? Are there any obvious candidates within the relevant `MT76` configuration files that I should check first? I'll probably start with a grep across the kernel source, or maybe utilize my build system's dependency tracing tools if they're available. The goal is to quickly pinpoint the origin and justification for this particular selection. Ultimately, understanding *why* it's selected is crucial for any potential modifications or optimizations I might want to consider. |
| 39/2 | 2026/07/25 19:07 | tool | grepper |
0mArgs:{
"Expression": "select MT76_CONNAC_LIB",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/Kconfig=32=config MT792x_LIB\ndrivers/net/wireless/mediatek/mt76/Kconfig-33-\ttristate\ndrivers/net/wireless/mediatek/mt76/Kconfig:34:\tselect MT76_CONNAC_LIB\ndrivers/net/wireless/mediatek/mt76/Kconfig-35-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/Kconfig=3=config MT7615_COMMON\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/Kconfig-5-\tselect WANT_DEV_COREDUMP\ndrivers/net/wireless/mediatek/mt76/mt7615/Kconfig:6:\tselect MT76_CONNAC_LIB\ndrivers/net/wireless/mediatek/mt76/mt7615/Kconfig-7-\n--\ndrivers/net/wireless/mediatek/mt76/mt7915/Kconfig=2=config MT7915E\ndrivers/net/wireless/mediatek/mt76/mt7915/Kconfig-3-\ttristate \"MediaTek MT7915E (PCIe) support\"\ndrivers/net/wireless/mediatek/mt76/mt7915/Kconfig:4:\tselect MT76_CONNAC_LIB\ndrivers/net/wireless/mediatek/mt76/mt7915/Kconfig-5-\tselect WANT_DEV_COREDUMP\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/Kconfig=2=config MT7996E\ndrivers/net/wireless/mediatek/mt76/mt7996/Kconfig-3-\ttristate \"MediaTek MT7996 (PCIe) support\"\ndrivers/net/wireless/mediatek/mt76/mt7996/Kconfig:4:\tselect MT76_CONNAC_LIB\ndrivers/net/wireless/mediatek/mt76/mt7996/Kconfig-5-\tselect WANT_DEV_COREDUMP\n"
} |
| 40/2 | 2026/07/25 19:07 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 47757 output: 48 thoughts: 57 Thoughts: Okay, let's break this down. **Decoding the Dependency Tree** Alright, let me see if I've got this straight. The `MT7615_COMMON` configuration option, right, that's pulling in the `MT76_CONNAC_LIB` library. Makes sense, that's a common dependency for those chipsets. Hmm, but then I'm wondering about the link between `MT7663U` and `MT7615_COMMON`. Doesn't feel quite right somehow. Let me just re-run the dependency checks for that `MT7663U` configuration again, just to be absolutely certain I haven't missed anything. I want to make sure the build process is pulling in exactly what it needs, and nothing more. Gotta stay on top of these things. |
| 41/2 | 2026/07/25 19:07 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/mediatek/mt76/mt7615/Kconfig",
"FirstLine": 30,
"LineCount": 20
}Results: {
"Contents": " 30:\t\t 2.4 GHz only.\n 31:\t\n 32:\tconfig MT7663_USB_SDIO_COMMON\n 33:\t\ttristate\n 34:\t\tselect MT7615_COMMON\n 35:\t\n 36:\tconfig MT7663U\n 37:\t\ttristate \"MediaTek MT7663U (USB) support\"\n 38:\t\tselect MT76_USB\n 39:\t\tselect MT7663_USB_SDIO_COMMON\n 40:\t\tdepends on MAC80211\n 41:\t\tdepends on USB\n 42:\t\thelp\n 43:\t\t This adds support for MT7663U 802.11ac 2x2:2 wireless devices.\n 44:\t\n 45:\t\t To compile this driver as a module, choose M here.\n 46:\t\n 47:\tconfig MT7663S\n 48:\t\ttristate \"MediaTek MT7663S (SDIO) support\"\n 49:\t\tselect MT76_SDIO\n"
} |
| 42/2 | 2026/07/25 19:07 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 48332 output: 48 thoughts: 623 Thoughts: **Reaching Conclusions on USB Fuzzing Targets** Okay, let's break this down. First, the `MT7663U` driver, based on the kernel configuration, links down to `MT7615_COMMON` which, in turn, selects `MT76_CONNAC_LIB`. This means both `mt76_connac_mac.c` and `mt76_connac_mcu.c` are definitely compiled and accessible when using a USB connection. Good. Next, I'm checking `mt7921u`, and it mirrors the pattern. `MT7921U` uses `MT792x_LIB` which *also* pulls in `MT76_CONNAC_LIB`. So, another USB driver employing those critical `mt76_connac_mac.c` and `mt76_connac_mcu.c` files. And the same applies to `mt7925u`, another USB driver in the mix. Given this, the changes in those two, as well as `mt76/dma.c`, `mt76/scan.c`, and `mt7615/usb_sdio.c` are definitely relevant targets for USB fuzzing. The fact that the changes in `mt7915` and `mt7996` are *not* directly reachable via USB, but are part of the same patch, is a point to note. But since some of the code is reachable and functional, we should flag this as `WorthFuzzing=true`. Now, the real work begins: identifying the specific functions within those files that are worth focusing the fuzzing efforts on. Let's see... from `mt7615/usb_sdio.c`, `mt7663_usb_sdio_tx_prepare_skb` stands out. From `mt76_connac_mac.c`, `mt76_connac2_mac_fill_rx_rate` is a key function to explore. In `mt76_connac_mcu.c`, `mt76_connac_mcu_sta_he_tlv` looks interesting. Moving on, `mt76/dma.c` gives us `mt76_dma_get_buf`, and finally, in `mt76/scan.c`, we've got a handful of options: `mt76_scan_complete` (even though it's static, there might be indirect paths through `mt76_abort_scan`, `mt76_scan_work`, or `mt76_hw_scan`), plus those latter functions themselves: `mt76_abort_scan`, `mt76_scan_work`, and `mt76_hw_scan`. One last thing: Before I get too deep, let's make sure that `mt76_connac2_mac_fill_rx_rate` is, in fact, relevant in a `MT7663U` context. It's for CONNAC2 chips. I need to double-check the `mt7615` driver specifically to verify if this is a supported hardware target. |
| 43/2 | 2026/07/25 19:07 | tool | grepper |
0mArgs:{
"Expression": "mt76_connac2_mac_fill_rx_rate",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt76_connac.h=470=int mt76_connac2_reverse_frag0_hdr_trans(struct ieee80211_vif *vif,\ndrivers/net/wireless/mediatek/mt76/mt76_connac.h-471-\t\t\t\t\t struct sk_buff *skb, u16 hdr_offset);\ndrivers/net/wireless/mediatek/mt76/mt76_connac.h:472:int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,\ndrivers/net/wireless/mediatek/mt76/mt76_connac.h-473-\t\t\t\t struct mt76_rx_status *status,\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mac.c=1037=EXPORT_SYMBOL_GPL(mt76_connac2_reverse_frag0_hdr_trans);\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mac.c-1038-\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mac.c:1039:int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mac.c-1040-\t\t\t\t struct mt76_rx_status *status,\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mac.c-1145-}\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mac.c:1146:EXPORT_SYMBOL_GPL(mt76_connac2_mac_fill_rx_rate);\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mac.c-1147-\n--\ndrivers/net/wireless/mediatek/mt76/mt7915/mac.c=263=mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb,\n--\ndrivers/net/wireless/mediatek/mt76/mt7915/mac.c-453-\t\tif (!is_mt7915(\u0026dev-\u003emt76) || (rxd1 \u0026 MT_RXD1_NORMAL_GROUP_5)) {\ndrivers/net/wireless/mediatek/mt76/mt7915/mac.c:454:\t\t\tret = mt76_connac2_mac_fill_rx_rate(\u0026dev-\u003emt76, status,\ndrivers/net/wireless/mediatek/mt76/mt7915/mac.c-455-\t\t\t\t\t\t\t sband, rxv, \u0026mode);\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/mac.c=169=mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb)\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/mac.c-344-\ndrivers/net/wireless/mediatek/mt76/mt7921/mac.c:345:\t\tret = mt76_connac2_mac_fill_rx_rate(\u0026dev-\u003emt76, status, sband,\ndrivers/net/wireless/mediatek/mt76/mt7921/mac.c-346-\t\t\t\t\t\t rxv, \u0026mode);\n"
} |
| 44/2 | 2026/07/25 19:07 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 50623 output: 49 thoughts: 105 Thoughts: **Reaching Potential Vulnerabilities** Okay, so I'm looking at `mt76_connac2_mac_fill_rx_rate`. That's interesting, as it's used by both `mt7915` and `mt7921`. Now, I recall that `mt7921` has a USB driver, `MT7921U`. This is potentially huge! That means `mt76_connac2_mac_fill_rx_rate` is directly accessible through a USB interface, opening up a pathway for fuzzing. I can definitely see some interesting angles there. Now, what about `mt76_connac_mcu_sta_he_tlv`? Let's take a look and see how that fits into the picture. |
| 45/2 | 2026/07/25 19:07 | tool | grepper |
0mArgs:{
"Expression": "mt76_connac_mcu_sta_he_tlv",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c=629=static void\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c:630:mt76_connac_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c-631-{\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c=762=void\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c:763:mt76_connac_mcu_sta_he_tlv_v2(struct sk_buff *skb, struct ieee80211_sta *sta)\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c-764-{\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c-793-}\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c:794:EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_he_tlv_v2);\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c-795-\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c=853=void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c-901-\tif (sta-\u003edeflink.he_cap.has_he) {\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c:902:\t\tmt76_connac_mcu_sta_he_tlv(skb, sta);\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c:903:\t\tmt76_connac_mcu_sta_he_tlv_v2(skb, sta);\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c-904-\t\tif (band == NL80211_BAND_6GHZ \u0026\u0026\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h=1972=int mt76_connac_mcu_sta_update_hdr_trans(struct mt76_dev *dev,\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h-1974-\t\t\t\t\t struct mt76_wcid *wcid, int cmd);\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h:1975:void mt76_connac_mcu_sta_he_tlv_v2(struct sk_buff *skb, struct ieee80211_sta *sta);\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h-1976-u8 mt76_connac_get_phy_mode_v2(struct mt76_phy *mphy, struct ieee80211_vif *vif,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/mcu.c=1694=mt7925_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_link_sta *link_sta)\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/mcu.c-1698-\ndrivers/net/wireless/mediatek/mt76/mt7925/mcu.c:1699:\tmt76_connac_mcu_sta_he_tlv_v2(skb, link_sta-\u003esta);\ndrivers/net/wireless/mediatek/mt76/mt7925/mcu.c-1700-}\n"
} |
| 46/2 | 2026/07/25 19:07 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 52069 output: 47 thoughts: 80 Thoughts: **Analyzing the MT76 Connection Manager's TLV Structures** Okay, hold on a second. I'm looking at this `mt76_connac_mcu.c` file and something's bugging me. I noticed that `mt76_connac_mcu_sta_he_tlv` is declared as `static` within the code. That means it's scoped locally and, as I understand it, not directly accessible from outside this specific file. But, then I see that `mt76_connac_mcu_sta_tlv` is exported, meaning it *is* reachable and available for other parts of the system to utilize. This discrepancy needs further investigation. Since I know `mt76_connac_mcu_sta_he_tlv` is static and possibly related to `mt76_connac_mcu_sta_tlv` and it's exported counterpart, I need to check `mt76_connac_mcu_sta_tlv` very carefully. Let's dig in and figure out the exact relationship here. There's definitely something interesting going on with how these TLVs are structured and handled. |
| 47/2 | 2026/07/25 19:07 | tool | grepper |
0mArgs:{
"Expression": "mt76_connac_mcu_sta_tlv",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7615/mcu.c=840=mt7615_mcu_wtbl_sta_add(struct mt7615_phy *phy, struct ieee80211_vif *vif,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-870-\tif (enable \u0026\u0026 sta)\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:871:\t\tmt76_connac_mcu_sta_tlv(phy-\u003emt76, sskb, sta, vif, 0,\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-872-\t\t\t\t\tMT76_STA_INFO_STATE_ASSOC);\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c=851=EXPORT_SYMBOL_GPL(mt76_connac_get_phy_mode_v2);\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c-852-\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c:853:void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c-854-\t\t\t struct ieee80211_sta *sta,\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c-952-}\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c:953:EXPORT_SYMBOL_GPL(mt76_connac_mcu_sta_tlv);\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c-954-\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c=1047=int mt76_connac_mcu_sta_cmd(struct mt76_phy *phy,\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c-1072-\tif (info-\u003esta \u0026\u0026 info-\u003eenable)\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c:1073:\t\tmt76_connac_mcu_sta_tlv(phy, skb, info-\u003esta,\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c-1074-\t\t\t\t\tinfo-\u003evif, info-\u003ercpi,\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h=1979=int mt76_connac_mcu_wtbl_update_hdr_trans(struct mt76_dev *dev,\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h-1981-\t\t\t\t\t struct ieee80211_sta *sta);\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h:1982:void mt76_connac_mcu_sta_tlv(struct mt76_phy *mphy, struct sk_buff *skb,\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h-1983-\t\t\t struct ieee80211_sta *sta,\n"
} |
| 48/2 | 2026/07/25 19:07 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 53406 output: 43 thoughts: 55 Thoughts: Okay, here's my summary, considering my expertise: **Checking Connectivity and DMA Buffer Allocation** Alright, it looks like `mt76_connac_mcu_sta_tlv` is indeed accessible and exported, which is good. That's the starting point. Now, I need to understand how the DMA buffers are managed within this context. I'm going to quickly check `mt76_dma_get_buf` in `mt76/dma.c`. I'm going to look and make sure it is reachable too. That call should give me a good understanding of the data flow and any potential contention points, especially given my knowledge of similar chipsets. |
| 49/2 | 2026/07/25 19:07 | tool | grepper |
0mArgs:{
"Expression": "mt76_dma_get_buf",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/dma.c=493=static void *\ndrivers/net/wireless/mediatek/mt76/dma.c:494:mt76_dma_get_buf(struct mt76_dev *dev, struct mt76_queue *q, int idx,\ndrivers/net/wireless/mediatek/mt76/dma.c-495-\t\t int *len, u32 *info, bool *more, bool *drop, bool flush)\n--\ndrivers/net/wireless/mediatek/mt76/dma.c=556=mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,\n--\ndrivers/net/wireless/mediatek/mt76/dma.c-607-\ndrivers/net/wireless/mediatek/mt76/dma.c:608:\treturn mt76_dma_get_buf(dev, q, idx, len, info, more, drop, flush);\ndrivers/net/wireless/mediatek/mt76/dma.c-609-}\n"
} |
| 50/2 | 2026/07/25 19:07 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 53945 output: 41 thoughts: 45 Thoughts: Okay, here's my interpretation of that thought process, assuming I'm an expert in this area and thinking through this code: **Diving into the DMA Buffer Management** Right, let's see, `mt76_dma_get_buf` is declared as `static`. Okay, that's important; it means it's only visible within this specific compilation unit. And I know it's called by `mt76_dma_dequeue`. So, the next logical step is to understand what `mt76_dma_dequeue` is doing and, crucially, how it interacts with that static function. I need to trace the flow. Let's dig into `mt76_dma_dequeue` and see what's going on. |
| 51/2 | 2026/07/25 19:07 | tool | grepper |
0mArgs:{
"Expression": "mt76_dma_dequeue",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/dma.c=555=static void *\ndrivers/net/wireless/mediatek/mt76/dma.c:556:mt76_dma_dequeue(struct mt76_dev *dev, struct mt76_queue *q, bool flush,\ndrivers/net/wireless/mediatek/mt76/dma.c-557-\t\t int *len, u32 *info, bool *more, bool *drop)\n--\ndrivers/net/wireless/mediatek/mt76/dma.c=866=mt76_dma_rx_cleanup(struct mt76_dev *dev, struct mt76_queue *q)\n--\ndrivers/net/wireless/mediatek/mt76/dma.c-880-\t\tspin_lock_bh(\u0026q-\u003elock);\ndrivers/net/wireless/mediatek/mt76/dma.c:881:\t\tbuf = mt76_dma_dequeue(dev, q, true, NULL, NULL, \u0026more, NULL);\ndrivers/net/wireless/mediatek/mt76/dma.c-882-\t\tspin_unlock_bh(\u0026q-\u003elock);\n--\ndrivers/net/wireless/mediatek/mt76/dma.c=979=mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)\n--\ndrivers/net/wireless/mediatek/mt76/dma.c-1006-\ndrivers/net/wireless/mediatek/mt76/dma.c:1007:\t\tdata = mt76_dma_dequeue(dev, q, false, \u0026len, \u0026info, \u0026more,\ndrivers/net/wireless/mediatek/mt76/dma.c-1008-\t\t\t\t\t\u0026drop);\n"
} |
| 52/2 | 2026/07/25 19:07 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 54666 output: 43 thoughts: 15 Thoughts: Okay, here's my interpretation of that: **My Perspective on `mt76_dma_rx_process`** Right, so `mt76_dma_rx_process` is exposed, meaning it's accessible and usable from outside of its immediate defining module. Hmm, that's a key piece of information. Since I'm working with networking and driver internals, I immediately start thinking about what that implies. This probably means it's a critical function related to receiving data via DMA, likely in the context of an MT76 wireless chipset. It's handling the incoming packets, likely in a low-level way, and processing them. The fact that it's exported suggests a few things. First, other parts of the driver, potentially higher-level network stack components, or even possibly other modules in a modular system, need to call into it. It could be for functions such as direct firmware interaction, perhaps a specialized diagnostic or monitoring component needs access, or possibly even a separate offload engine that's being supported. Second, this is an important point to note when working with security and robustness, so I'll need to keep that in mind when examining the code. It's going to be essential for me to understand how this function is *designed* to be called, what input parameters it expects, and what guarantees it provides about its behaviour. I'll need to look very closely at the data structures it interacts with. What's the context in which it's invoked? Is it interrupt-driven? Is it called from a tasklet or workqueue? What locking mechanisms are involved? Any potential for race conditions? Are there any potential vulnerabilities related to data validation or buffer management? I'll probably start by grepping the kernel source to identify all the call sites and figure out the exact call sequences involved. Understanding the intended usage will give me a critical overview of its role in the receive path. Also, I'll need to examine how error conditions are handled. It's probably responsible for reporting receive errors, packet drops, and so on. Exported functions are often entry points for complex receive processing. I will need to understand this to have any chance of debugging problems, optimizing performance, or identifying security vulnerabilities. It will be helpful to examine the header files and any associated documentation, if it exists, to get a handle on its purpose. |
| 53/2 | 2026/07/25 19:07 | tool | grepper |
0mArgs:{
"Expression": "mt76_dma_rx_process",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/dma.c=978=static int\ndrivers/net/wireless/mediatek/mt76/dma.c:979:mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)\ndrivers/net/wireless/mediatek/mt76/dma.c-980-{\n--\ndrivers/net/wireless/mediatek/mt76/dma.c=1078=int mt76_dma_rx_poll(struct napi_struct *napi, int budget)\n--\ndrivers/net/wireless/mediatek/mt76/dma.c-1088-\tdo {\ndrivers/net/wireless/mediatek/mt76/dma.c:1089:\t\tcur = mt76_dma_rx_process(dev, \u0026dev-\u003eq_rx[qid], budget - done);\ndrivers/net/wireless/mediatek/mt76/dma.c-1090-\t\tmt76_rx_poll_complete(dev, qid, napi);\n"
} |
| 54/2 | 2026/07/25 19:07 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 55509 output: 50 thoughts: 239 Thoughts: **Analyzing the Exposed Functions** Okay, so `mt76_dma_rx_poll` is definitely exported; that's good to know. Now, let's see... what about `mt76_scan_complete`? Ah, right, that's static. But, wait, it's called by both `mt76_abort_scan` and `mt76_scan_work`. Hmm, `mt76_abort_scan` is *exported*, and `mt76_scan_work` is also *exported*. Excellent. This narrows down the scope of what I need to look at. So, the key functions to focus on for this particular analysis are: * `mt7663_usb_sdio_tx_prepare_skb` * `mt76_connac2_mac_fill_rx_rate` * `mt76_connac_mcu_sta_tlv` * `mt76_dma_rx_poll` * `mt76_abort_scan` * `mt76_scan_work` Hold on a second... `mt7663_usb_sdio_tx_prepare_skb`, that's in `mt7615/usb_sdio.c`, isn't it? Okay, I need to verify whether that's actually exported or if it's used as a callback somewhere. Gotta be thorough. |
| 55/2 | 2026/07/25 19:08 | tool | grepper |
0mArgs:{
"Expression": "mt7663_usb_sdio_tx_prepare_skb",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h=540=void mt7622_trigger_hif_int(struct mt7615_dev *dev, bool en);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h-542-/* usb */\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h:543:int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h-544-\t\t\t\t enum mt76_txq_id qid, struct mt76_wcid *wcid,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/sdio.c=76=static int mt7663s_probe(struct sdio_func *func,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/sdio.c-81-\t\t.drv_flags = MT_DRV_RX_DMA_HDR,\ndrivers/net/wireless/mediatek/mt76/mt7615/sdio.c:82:\t\t.tx_prepare_skb = mt7663_usb_sdio_tx_prepare_skb,\ndrivers/net/wireless/mediatek/mt76/mt7615/sdio.c-83-\t\t.tx_complete_skb = mt7663_usb_sdio_tx_complete_skb,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/usb.c=112=static int mt7663u_probe(struct usb_interface *usb_intf,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/usb.c-117-\t\t.drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ,\ndrivers/net/wireless/mediatek/mt76/mt7615/usb.c:118:\t\t.tx_prepare_skb = mt7663_usb_sdio_tx_prepare_skb,\ndrivers/net/wireless/mediatek/mt76/mt7615/usb.c-119-\t\t.tx_complete_skb = mt7663_usb_sdio_tx_complete_skb,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c=179=EXPORT_SYMBOL_GPL(mt7663_usb_sdio_tx_complete_skb);\ndrivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c-180-\ndrivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c:181:int mt7663_usb_sdio_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,\ndrivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c-182-\t\t\t\t enum mt76_txq_id qid, struct mt76_wcid *wcid,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c-224-}\ndrivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c:225:EXPORT_SYMBOL_GPL(mt7663_usb_sdio_tx_prepare_skb);\ndrivers/net/wireless/mediatek/mt76/mt7615/usb_sdio.c-226-\n"
} |
| 56/2 | 2026/07/25 19:08 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 57116 output: 45 thoughts: 45 Thoughts: Okay, here's my interpretation of those thoughts, framed as my own: **Analyzing Callback Utilization in the MT7615 Driver** Alright, so the clue here is that the function is being "exported and used as a callback". That's a key piece of information. I need to figure out *how* it's being used as a callback, and where. Let's dive right into it. The immediate place to look is `mt7615_tx_prepare_skb` within `mt7615/pci_mac.c`. That should be the critical function to examine. I'll need to trace its usage within the driver to understand its interaction with the broader transmission process and where this callback is actually being invoked. From there I'll be able to piece together the entire picture. |
| 57/2 | 2026/07/25 19:08 | tool | grepper |
0mArgs:{
"Expression": "mt7615_tx_prepare_skb",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7615/mmio.c=166=int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mmio.c-176-\t\t.token_size = MT7615_TOKEN_SIZE,\ndrivers/net/wireless/mediatek/mt76/mt7615/mmio.c:177:\t\t.tx_prepare_skb = mt7615_tx_prepare_skb,\ndrivers/net/wireless/mediatek/mt76/mt7615/mmio.c-178-\t\t.tx_complete_skb = mt76_connac_tx_complete_skb,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h=494=void mt7615_mcu_fill_msg(struct mt7615_dev *dev, struct sk_buff *skb,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h-496-\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h:497:int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h-498-\t\t\t enum mt76_txq_id qid, struct mt76_wcid *wcid,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c=18=mt7615_write_fw_txp(struct mt7615_dev *dev, struct mt76_tx_info *tx_info,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c-59-\ndrivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c:60:int mt7615_tx_prepare_skb(struct mt76_dev *mdev, void *txwi_ptr,\ndrivers/net/wireless/mediatek/mt76/mt7615/pci_mac.c-61-\t\t\t enum mt76_txq_id qid, struct mt76_wcid *wcid,\n"
} |
| 58/2 | 2026/07/25 19:08 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 58040 output: 43 thoughts: 598 Thoughts: **Reaching Functions Through USB** Okay, so I'm trying to figure out which of these symbols are actually reachable through a USB connection, specifically in a QEMU environment. I started by looking at `mt7615_mmio_probe`, but that's PCIe/platform-specific, so anything related to it, like `mt7615_tx_prepare_skb`, is out. Similarly, `mt7915_mac_full_reset` and `mt7996_mac_full_reset` are PCIe-only, so those aren't relevant either. That leaves me with a smaller, focused set: `mt7663_usb_sdio_tx_prepare_skb`, `mt76_connac2_mac_fill_rx_rate`, `mt76_connac_mcu_sta_tlv`, `mt76_dma_rx_poll`, `mt76_abort_scan`, and `mt76_scan_work`. Now, let's start with `mt76_connac2_mac_fill_rx_rate`. I see that it's used by `mt7921_mac_fill_rx`, and `mt7921` has a USB driver, `MT7921U`. Excellent, that one's reachable. Next, `mt76_connac_mcu_sta_tlv`. This is used by `mt7615_mcu_wtbl_sta_add` and `mt76_connac_mcu_sta_cmd`. `mt7615_mcu_wtbl_sta_add` itself is used by `mt7615_mac_sta_add`, which is used by `mt7615_ops.sta_add`. And `mt7615` has a USB driver, `MT7663U`. So, that one is reachable as well. Okay, let's look at `mt76_dma_rx_poll`. Wait a minute... this is for NAPI polling, isn't it? The question is, does the USB driver use NAPI for receive (RX) polling? I should probably check `mt7615/usb.c` to be sure. |
| 59/2 | 2026/07/25 19:08 | tool | grepper |
0mArgs:{
"Expression": "mt76_dma_rx_poll",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/dma.c=979=mt76_dma_rx_process(struct mt76_dev *dev, struct mt76_queue *q, int budget)\n--\ndrivers/net/wireless/mediatek/mt76/dma.c-1077-\ndrivers/net/wireless/mediatek/mt76/dma.c:1078:int mt76_dma_rx_poll(struct napi_struct *napi, int budget)\ndrivers/net/wireless/mediatek/mt76/dma.c-1079-{\n--\ndrivers/net/wireless/mediatek/mt76/dma.c-1100-}\ndrivers/net/wireless/mediatek/mt76/dma.c:1101:EXPORT_SYMBOL_GPL(mt76_dma_rx_poll);\ndrivers/net/wireless/mediatek/mt76/dma.c-1102-\n--\ndrivers/net/wireless/mediatek/mt76/dma.h=164=enum mt76_dma_wed_ind_reason {\n--\ndrivers/net/wireless/mediatek/mt76/dma.h-169-\ndrivers/net/wireless/mediatek/mt76/dma.h:170:int mt76_dma_rx_poll(struct napi_struct *napi, int budget);\ndrivers/net/wireless/mediatek/mt76/dma.h-171-void mt76_dma_attach(struct mt76_dev *dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7603/dma.c=176=int mt7603_dma_init(struct mt7603_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7603/dma.c-240-\tmt76_wr(dev, MT_DELAY_INT_CFG, 0);\ndrivers/net/wireless/mediatek/mt76/mt7603/dma.c:241:\tret = mt76_init_queues(dev, mt76_dma_rx_poll);\ndrivers/net/wireless/mediatek/mt76/mt7603/dma.c-242-\tif (ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c=87=static int mt7615_poll_rx(struct napi_struct *napi, int budget)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-98-\t}\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c:99:\tdone = mt76_dma_rx_poll(napi, budget);\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-100-\tmt76_connac_pm_unref(\u0026dev-\u003emphy, \u0026dev-\u003epm);\n--\ndrivers/net/wireless/mediatek/mt76/mt76x02_mmio.c=175=int mt76x02_dma_init(struct mt76x02_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x02_mmio.c-236-\ndrivers/net/wireless/mediatek/mt76/mt76x02_mmio.c:237:\tret = mt76_init_queues(dev, mt76_dma_rx_poll);\ndrivers/net/wireless/mediatek/mt76/mt76x02_mmio.c-238-\tif (ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt7915/dma.c=408=int mt7915_dma_init(struct mt7915_dev *dev, struct mt7915_phy *phy2)\n--\ndrivers/net/wireless/mediatek/mt76/mt7915/dma.c-576-\ndrivers/net/wireless/mediatek/mt76/mt7915/dma.c:577:\tret = mt76_init_queues(dev, mt76_dma_rx_poll);\ndrivers/net/wireless/mediatek/mt76/mt7915/dma.c-578-\tif (ret \u003c 0)\n--\ndrivers/net/wireless/mediatek/mt76/mt792x_dma.c=459=int mt792x_poll_rx(struct napi_struct *napi, int budget)\n--\ndrivers/net/wireless/mediatek/mt76/mt792x_dma.c-470-\t}\ndrivers/net/wireless/mediatek/mt76/mt792x_dma.c:471:\tdone = mt76_dma_rx_poll(napi, budget);\ndrivers/net/wireless/mediatek/mt76/mt792x_dma.c-472-\tmt76_connac_pm_unref(\u0026dev-\u003emphy, \u0026dev-\u003epm);\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c=622=void mt7996_dma_rro_start(struct mt7996_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-638-\t\tmt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND1,\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c:639:\t\t\t\t mt76_dma_rx_poll);\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-640-\t\tmt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND2,\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c:641:\t\t\t\t mt76_dma_rx_poll);\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-642-\t\tmt76_queue_rx_init(dev, MT_RXQ_RRO_BAND2,\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c:643:\t\t\t\t mt76_dma_rx_poll);\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-644-\t} else {\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-645-\t\tmt76_queue_rx_init(dev, MT_RXQ_RRO_BAND1,\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c:646:\t\t\t\t mt76_dma_rx_poll);\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-647-\t}\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-648-\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c:649:\tmt76_queue_rx_init(dev, MT_RXQ_RRO_BAND0, mt76_dma_rx_poll);\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-650-\tif (dev-\u003emt76.hwrro_mode == MT76_HWRRO_V3_1) {\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-651-\t\tmt76_queue_rx_init(dev, MT_RXQ_RRO_RXDMAD_C,\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c:652:\t\t\t\t mt76_dma_rx_poll);\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-653-\t} else {\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-654-\t\tmt76_queue_rx_init(dev, MT_RXQ_RRO_IND,\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c:655:\t\t\t\t mt76_dma_rx_poll);\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-656-\t\tmt76_queue_rx_init(dev, MT_RXQ_MSDU_PAGE_BAND0,\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c:657:\t\t\t\t mt76_dma_rx_poll);\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-658-\t}\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c=664=int mt7996_dma_init(struct mt7996_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-942-\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c:943:\tret = mt76_init_queues(dev, mt76_dma_rx_poll);\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-944-\tif (ret \u003c 0)\n"
} |
| 60/2 | 2026/07/25 19:08 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 61718 output: 42 thoughts: 118 Thoughts: **Investigating the Data Flow in the MT792x Driver** Okay, so I'm looking at the `mt76_dma_rx_poll` function; it's being called by `mt792x_poll_rx`. Makes sense. I know `mt792x` has USB drivers, like `mt7921u` and `mt7925u`. That's important context. Hang on... `mt792x_poll_rx` is actually defined within `mt792x_dma.c`. Now, that's interesting. I need to make sure I understand the data path properly here. Is `mt792x_dma.c` actually being compiled when the USB driver is built? I need to verify that and see how the DMA interacts with USB specifically. I'll need to go through the code and quickly confirm the usage of `mt792x_dma.c` and figure out how it is used for USB. This is where I'll probably find my answer. |
| 61/2 | 2026/07/25 19:08 | tool | grepper |
0mArgs:{
"Expression": "mt792x_poll_rx",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7921/pci.c=171=static int mt7921_dma_init(struct mt792x_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/pci.c-247-\ndrivers/net/wireless/mediatek/mt76/mt7921/pci.c:248:\tret = mt76_init_queues(dev, mt792x_poll_rx);\ndrivers/net/wireless/mediatek/mt76/mt7921/pci.c-249-\tif (ret \u003c 0)\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c=255=static int mt7927_dma_init(struct mt792x_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-270-\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c:271:\tret = mt76_init_queues(dev, mt792x_poll_rx);\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-272-\tif (ret \u003c 0)\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c=282=static int mt7925_dma_init(struct mt792x_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-289-\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c:290:\tret = mt76_init_queues(dev, mt792x_poll_rx);\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-291-\tif (ret \u003c 0)\n--\ndrivers/net/wireless/mediatek/mt76/mt792x.h=453=int mt792x_poll_tx(struct napi_struct *napi, int budget);\ndrivers/net/wireless/mediatek/mt76/mt792x.h:454:int mt792x_poll_rx(struct napi_struct *napi, int budget);\ndrivers/net/wireless/mediatek/mt76/mt792x.h-455-void mt792x_irq_tasklet(unsigned long data);\n--\ndrivers/net/wireless/mediatek/mt76/mt792x_dma.c=457=EXPORT_SYMBOL_GPL(mt792x_poll_tx);\ndrivers/net/wireless/mediatek/mt76/mt792x_dma.c-458-\ndrivers/net/wireless/mediatek/mt76/mt792x_dma.c:459:int mt792x_poll_rx(struct napi_struct *napi, int budget)\ndrivers/net/wireless/mediatek/mt76/mt792x_dma.c-460-{\n--\ndrivers/net/wireless/mediatek/mt76/mt792x_dma.c-475-}\ndrivers/net/wireless/mediatek/mt76/mt792x_dma.c:476:EXPORT_SYMBOL_GPL(mt792x_poll_rx);\ndrivers/net/wireless/mediatek/mt76/mt792x_dma.c-477-\n"
} |
| 62/2 | 2026/07/25 19:08 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 63053 output: 44 thoughts: 69 Thoughts: **Investigating Receiver Polling Functions** Okay, so I'm looking at this `mt792x_poll_rx` function – that's being used within `pci.c`, interesting. My mind immediately jumps to the related landscape. Now, where does `mt7615_poll_rx` fit into the picture? Ah, it's defined in `mt7615/dma.c`. But here's the key question, and this is where I need to clarify things: is that `mt7615/dma.c` module even compiled and included when the system is configured for USB? Because if it's not, we might be missing something important in the USB context. Need to double-check that dependency to see if there's potential for unexpected behavior or performance differences between PCI and USB implementations. |
| 63/2 | 2026/07/25 19:08 | tool | grepper |
0mArgs:{
"Expression": "dma.o",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7615/Makefile"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7615/Makefile=13=mt7615-common-$(CONFIG_NL80211_TESTMODE) += testmode.o\ndrivers/net/wireless/mediatek/mt76/mt7615/Makefile-14-\ndrivers/net/wireless/mediatek/mt76/mt7615/Makefile:15:mt7615e-y := pci.o pci_init.o dma.o pci_mac.o mmio.o\ndrivers/net/wireless/mediatek/mt76/mt7615/Makefile-16-mt7615e-$(CONFIG_MT7622_WMAC) += soc.o\n"
} |
| 64/2 | 2026/07/25 19:08 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 63543 output: 38 thoughts: 207 Thoughts: **Analyzing DMA Paths in MT76 Drivers** Okay, let me think this through. The initial concern was about how changes in `mt76/dma.c` might affect the `mt7615` driver, particularly if they are USB-related, but I think I've got it figured out. No, wait, `dma.o` is definitely part of `mt7615e-y`, which is PCIe. So, the `mt76_dma_rx_poll` function isn't even accessible through USB for the `mt7615` driver. Now, let's rethink this. What about `mt76x02_mmio.c`? It relies on mmio, not USB. And what about `mt7603`? It is also mmio-based. So, `mt76_dma_rx_poll` is only ever utilized by drivers that are utilizing PCIe or MMIO access. USB drivers would naturally use something like `mt76_usb_rx_complete`, or a similar function designed for USB communication, rather than the DMA-specific calls. Consequently, any changes in `mt76/dma.c` won't be reachable via USB at all. Wait a second, the `mt76/dma.c` file is compiled for `MT76_CONNAC_LIB`? No, it looks like it is in `mt76-y`. That confirms my thinking, the path is clear. |
| 65/2 | 2026/07/25 19:08 | tool | grepper |
0mArgs:{
"Expression": "dma.o",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/Makefile"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/Makefile=11=mt76-y := \\\ndrivers/net/wireless/mediatek/mt76/Makefile:12:\tmmio.o util.o trace.o dma.o mac80211.o debugfs.o eeprom.o \\\ndrivers/net/wireless/mediatek/mt76/Makefile-13-\ttx.o agg-rx.o mcu.o wed.o scan.o channel.o\n--\ndrivers/net/wireless/mediatek/mt76/Makefile=36=mt792x-lib-y := mt792x_core.o mt792x_mac.o mt792x_trace.o \\\ndrivers/net/wireless/mediatek/mt76/Makefile:37:\t\tmt792x_debugfs.o mt792x_dma.o\ndrivers/net/wireless/mediatek/mt76/Makefile-38-mt792x-lib-$(CONFIG_ACPI) += mt792x_acpi_sar.o\n"
} |
| 66/2 | 2026/07/25 19:08 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 64391 output: 41 thoughts: 172 Thoughts: **Investigating the Reachability of `mt76_dma_rx_poll` from USB Drivers** Okay, so `dma.o` seems to reside within the `mt76-y` module. My immediate concern is whether `mt76_dma_rx_poll` is actually reachable via the USB interface, or if it's strictly confined to other parts of the system. I need to determine if the USB drivers even *use* it. If they don't, then I can probably safely consider it outside the scope of my current investigation. To ascertain this, I need to trace the call paths. I'll start by checking if `mt76_dma_get_buf` – a likely critical function in this DMA chain – is invoked by any USB-related code. Looks like it's called by `mt76_dma_dequeue`. Now, `mt76_dma_dequeue` itself is called by `mt76_dma_rx_cleanup` and `mt76_dma_rx_process`. The `mt76_dma_rx_cleanup` function is called by `mt76_dma_cleanup`. So, now the question is: is `mt76_dma_cleanup` called by any of the USB drivers? That is the question I now need to answer. I suspect if I find a call to `mt76_dma_cleanup` from USB, I will then know that `mt76_dma_rx_poll` is reachable from USB. |
| 67/2 | 2026/07/25 19:08 | tool | grepper |
0mArgs:{
"Expression": "mt76_dma_cleanup",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/dma.c=1170=EXPORT_SYMBOL_GPL(mt76_dma_attach);\ndrivers/net/wireless/mediatek/mt76/dma.c-1171-\ndrivers/net/wireless/mediatek/mt76/dma.c:1172:void mt76_dma_cleanup(struct mt76_dev *dev)\ndrivers/net/wireless/mediatek/mt76/dma.c-1173-{\n--\ndrivers/net/wireless/mediatek/mt76/dma.c-1213-}\ndrivers/net/wireless/mediatek/mt76/dma.c:1214:EXPORT_SYMBOL_GPL(mt76_dma_cleanup);\n--\ndrivers/net/wireless/mediatek/mt76/dma.h=171=void mt76_dma_attach(struct mt76_dev *dev);\ndrivers/net/wireless/mediatek/mt76/dma.h:172:void mt76_dma_cleanup(struct mt76_dev *dev);\ndrivers/net/wireless/mediatek/mt76/dma.h-173-int mt76_dma_rx_fill(struct mt76_dev *dev, struct mt76_queue *q,\n--\ndrivers/net/wireless/mediatek/mt76/mt7603/dma.c=252=void mt7603_dma_cleanup(struct mt7603_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7603/dma.c-258-\ndrivers/net/wireless/mediatek/mt76/mt7603/dma.c:259:\tmt76_dma_cleanup(\u0026dev-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt7603/dma.c-260-}\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c=308=void mt7615_dma_cleanup(struct mt7615_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-314-\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c:315:\tmt76_dma_cleanup(\u0026dev-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt7615/dma.c-316-}\n--\ndrivers/net/wireless/mediatek/mt76/mt76x0/pci.c=224=static void mt76x0e_cleanup(struct mt76x02_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x0/pci.c-229-\tmt76x0e_stop_hw(dev);\ndrivers/net/wireless/mediatek/mt76/mt76x0/pci.c:230:\tmt76_dma_cleanup(\u0026dev-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt76x0/pci.c-231-\tmt76x02_mcu_cleanup(dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c=281=void mt76x2_cleanup(struct mt76x02_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c-285-\tmt76x2_stop_hardware(dev);\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c:286:\tmt76_dma_cleanup(\u0026dev-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c-287-\tmt76x02_mcu_cleanup(dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7915/dma.c=650=void mt7915_dma_cleanup(struct mt7915_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7915/dma.c-653-\ndrivers/net/wireless/mediatek/mt76/mt7915/dma.c:654:\tmt76_dma_cleanup(\u0026dev-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt7915/dma.c-655-}\n--\ndrivers/net/wireless/mediatek/mt76/mt792x_dma.c=409=void mt792x_dma_cleanup(struct mt792x_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt792x_dma.c-432-\ndrivers/net/wireless/mediatek/mt76/mt792x_dma.c:433:\tmt76_dma_cleanup(\u0026dev-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt792x_dma.c-434-}\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c=1052=void mt7996_dma_cleanup(struct mt7996_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-1055-\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c:1056:\tmt76_dma_cleanup(\u0026dev-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt7996/dma.c-1057-}\n"
} |
| 68/2 | 2026/07/25 19:08 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 66469 output: 40 thoughts: 316 Thoughts: **Analyzing DMA and Scan Operations in mt76 Drivers** Okay, let's break this down systematically. I'm looking at DMA cleanup and scan operations within the mt76 wireless driver framework. I've noted that `mt7615_dma_cleanup` is specifically linked to the PCIe implementation, residing in `mt7615/dma.c`. But what about `mt792x_dma_cleanup` in `mt792x_dma.c`? My initial thought is to determine its scope, and whether it's utilized by USB-based devices. A quick cross-reference reveals the presence of `mt792x_dma.o` within `mt792x-lib-y`. And given that `mt7921u` leverages `mt792x-lib`, it's confirmed: `mt792x_dma_cleanup` *is* accessible via the USB path. Expanding the dependency graph, `mt792x_dma_cleanup` calls `mt76_dma_cleanup`, which then calls `mt76_dma_rx_cleanup`, eventually reaching `mt76_dma_dequeue` and finally `mt76_dma_get_buf`. This clearly establishes that `mt76_dma_get_buf` is reachable through the USB interface as well, which is an important point. Now, shifting gears to scan operations. I'm also examining the reachability of `mt76_abort_scan` and `mt76_scan_work`, which reside within `mt76/scan.c`. The question becomes whether these are used by the USB drivers. The `scan.o` object is included in `mt76-y` so the answer is yes. Now I'll need to double check that `mt76_abort_scan` is called by a function like `mt7615_stop_sched_scan` or a similar function in the driver code. |
| 69/2 | 2026/07/25 19:08 | tool | grepper |
0mArgs:{
"Expression": "mt76_abort_scan",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/channel.c=32=int mt76_add_chanctx(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/mediatek/mt76/channel.c-44-\tif (dev-\u003escan.phy == phy)\ndrivers/net/wireless/mediatek/mt76/channel.c:45:\t\tmt76_abort_scan(dev);\ndrivers/net/wireless/mediatek/mt76/channel.c-46-\n--\ndrivers/net/wireless/mediatek/mt76/channel.c=58=void mt76_remove_chanctx(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/mediatek/mt76/channel.c-69-\tif (dev-\u003escan.phy == phy)\ndrivers/net/wireless/mediatek/mt76/channel.c:70:\t\tmt76_abort_scan(dev);\ndrivers/net/wireless/mediatek/mt76/channel.c-71-\n--\ndrivers/net/wireless/mediatek/mt76/channel.c=103=int mt76_assign_vif_chanctx(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/mediatek/mt76/channel.c-117-\tif (dev-\u003escan.vif == vif)\ndrivers/net/wireless/mediatek/mt76/channel.c:118:\t\tmt76_abort_scan(dev);\ndrivers/net/wireless/mediatek/mt76/channel.c-119-\n--\ndrivers/net/wireless/mediatek/mt76/channel.c=154=void mt76_unassign_vif_chanctx(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/mediatek/mt76/channel.c-164-\tif (dev-\u003escan.vif == vif)\ndrivers/net/wireless/mediatek/mt76/channel.c:165:\t\tmt76_abort_scan(dev);\ndrivers/net/wireless/mediatek/mt76/channel.c-166-\n--\ndrivers/net/wireless/mediatek/mt76/channel.c=184=int mt76_switch_vif_chanctx(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/mediatek/mt76/channel.c-208-\t\tif (dev-\u003escan.phy == phy)\ndrivers/net/wireless/mediatek/mt76/channel.c:209:\t\t\tmt76_abort_scan(dev);\ndrivers/net/wireless/mediatek/mt76/channel.c-210-\n--\ndrivers/net/wireless/mediatek/mt76/mac80211.c=2087=void mt76_vif_cleanup(struct mt76_dev *dev, struct ieee80211_vif *vif)\n--\ndrivers/net/wireless/mediatek/mt76/mac80211.c-2092-\trcu_assign_pointer(mvif-\u003elink[0], NULL);\ndrivers/net/wireless/mediatek/mt76/mac80211.c:2093:\tmt76_abort_scan(dev);\ndrivers/net/wireless/mediatek/mt76/mac80211.c-2094-\tif (mvif-\u003eroc_phy)\n--\ndrivers/net/wireless/mediatek/mt76/mt76.h=1817=void mt76_scan_work(struct work_struct *work);\ndrivers/net/wireless/mediatek/mt76/mt76.h:1818:void mt76_abort_scan(struct mt76_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt76.h-1819-void mt76_roc_complete_work(struct work_struct *work);\n--\ndrivers/net/wireless/mediatek/mt76/mt7915/mac.c=1420=mt7915_mac_full_reset(struct mt7915_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7915/mac.c-1440-\ndrivers/net/wireless/mediatek/mt76/mt7915/mac.c:1441:\tmt76_abort_scan(\u0026dev-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt7915/mac.c-1442-\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/mac.c=2395=mt7996_mac_full_reset(struct mt7996_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/mac.c-2410-\ndrivers/net/wireless/mediatek/mt76/mt7996/mac.c:2411:\tmt76_abort_scan(\u0026dev-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt7996/mac.c-2412-\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/mac.c=2460=void mt7996_mac_reset_work(struct work_struct *work)\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/mac.c-2512-\twake_up(\u0026dev-\u003emt76.mcu.wait);\ndrivers/net/wireless/mediatek/mt76/mt7996/mac.c:2513:\tmt76_abort_scan(\u0026dev-\u003emt76);\ndrivers/net/wireless/mediatek/mt76/mt7996/mac.c-2514-\n--\ndrivers/net/wireless/mediatek/mt76/scan.c=7=static void mt76_scan_complete(struct mt76_dev *dev, bool abort)\n--\ndrivers/net/wireless/mediatek/mt76/scan.c-38-\ndrivers/net/wireless/mediatek/mt76/scan.c:39:void mt76_abort_scan(struct mt76_dev *dev)\ndrivers/net/wireless/mediatek/mt76/scan.c-40-{\n--\ndrivers/net/wireless/mediatek/mt76/scan.c-50-}\ndrivers/net/wireless/mediatek/mt76/scan.c:51:EXPORT_SYMBOL_GPL(mt76_abort_scan);\ndrivers/net/wireless/mediatek/mt76/scan.c-52-\n--\ndrivers/net/wireless/mediatek/mt76/scan.c=233=void mt76_cancel_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif)\n--\ndrivers/net/wireless/mediatek/mt76/scan.c-236-\ndrivers/net/wireless/mediatek/mt76/scan.c:237:\tmt76_abort_scan(phy-\u003edev);\ndrivers/net/wireless/mediatek/mt76/scan.c-238-}\n"
} |
| 70/2 | 2026/07/25 19:08 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 69122 output: 48 thoughts: 351 Thoughts: **My Assessment of the MT76 Driver Reachability** Okay, let's break this down. It seems `mt76_abort_scan` gets called from multiple places: `mt76_vif_cleanup`, `mt76_cancel_hw_scan`, and so on. And, as I expected, `mt76_cancel_hw_scan` is exposed and utilized by mac80211. That confirms it *is* accessible via USB, which is important for this line of investigation. Now, focusing on the key symbols of interest, the following are clearly on the radar: `mt7663_usb_sdio_tx_prepare_skb`, `mt76_connac2_mac_fill_rx_rate`, and `mt76_connac_mcu_sta_tlv`. Those are all candidates. Wait, here is an interesting point... `mt76_dma_rx_poll`. I had to pause there because it's *not* reachable via USB for the `mt7615` implementation, but it *is* accessible via USB for the `mt7921u` and `mt7925u` variants because of how they call `mt792x_poll_rx` which then calls `mt76_dma_rx_poll`. Adding to that the list is `mt76_abort_scan` and `mt76_scan_work`, too. So, the next step is to nail down the configuration. I need to figure out if `mt7921u` and `mt7925u` are enabled by default, or what specific configurations are needed to build these. I know they're `MT7921U` and `MT7925U`. The plan is to check these in the Kconfig and then add `MT7663U`, `MT7921U`, and `MT7925U` to the `EnableConfigs` list. |
| 71/2 | 2026/07/25 19:08 | tool | grepper |
0mArgs:{
"Expression": "config MT7921U",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7921/Kconfig"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7921/Kconfig=17=config MT7921S\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/Kconfig-27-\ndrivers/net/wireless/mediatek/mt76/mt7921/Kconfig:28:config MT7921U\ndrivers/net/wireless/mediatek/mt76/mt7921/Kconfig-29-\ttristate \"MediaTek MT7921U (USB) support\"\n"
} |
| 72/2 | 2026/07/25 19:08 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 70116 output: 48 thoughts: 9 Thoughts: Okay, here's my summary, presented as a first-person account reflecting on the "Thoughts" provided. I'll tailor it as if I were speaking to a fellow expert. **MT7925U Deep Dive** Alright, let's break this down. When I see "MT7925U", my mind immediately goes into overdrive, connecting the dots. I start by recalling its place within the overall Wi-Fi ecosystem. This isn't just a random chip; it's a MediaTek product, likely targeted at a specific segment of the market. I need to figure out what it's trying to *do*. What's its architecture? Is it a dual-band, tri-band, or something more specialized? The "U" suffix is potentially a clue, often indicating the target application – USB, perhaps? Or is it a designation of the feature set? I need to look at the data sheet to find out. I also wonder about the underlying design considerations. What process node are we talking about? This will inform everything from power consumption to performance capabilities, and the density of integrations. Any mention of standards would be important too. Is it 802.11ax (Wi-Fi 6) or Wi-Fi 6E? Or is it looking further ahead? What are the supported channels, bandwidths, and modulation schemes? Ultimately, my assessment will depend on the intended application. Is this aimed at an embedded system, a laptop, a router, or something else entirely? The feature set – security protocols, power management options, offload capabilities – will provide essential context. Understanding the competitive landscape is key. I'll need to compare it to offerings from Qualcomm, Intel, Broadcom, and others. What are its strengths? Where does it fall short? Is it designed to be competitive on price, performance, or a specific feature set? Finally, I'm thinking about the implications for system integration. What kind of drivers and software support will it have? Will it play nicely with existing operating systems, and will there be good documentation and development resources? The software ecosystem is crucial to the chip's adoption and usability. Overall, the full picture emerges from cross-referencing all these factors. |
| 73/2 | 2026/07/25 19:08 | tool | grepper |
0mArgs:{
"Expression": "config MT7925U",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7925/Kconfig"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7925/Kconfig=7=config MT7925E\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig-18-\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig:19:config MT7925U\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig-20-\ttristate \"MediaTek MT7925U (USB) support\"\n"
} |
| 74/2 | 2026/07/25 19:08 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 70791 output: 310 thoughts: 1289 Thoughts: **Reasoning for Fuzzing the MediaTek mt76 Wireless Driver via USB** Okay, let's break this down. We have a patch touching the MediaTek mt76 wireless driver, and we need to figure out the right way to fuzz it. First, let's identify the relevant configurations. We know we're dealing with USB, and based on the initial assessment, the configs that look promising are `MT7663U`, `MT7921U`, and `MT7925U`. `MAC80211` and `USB` are almost always enabled, so we don't have to specifically include them. I'll make a note to include `MT7663U`, `MT7921U`, and `MT7925U` in `EnableConfigs`. Now, the patch touches `mt76_dma_get_buf`, which is called by `mt76_dma_dequeue`. The key question is whether `mt76_dma_dequeue` can be reached via USB. Let's trace it through. For `mt7921u`, it uses `mt792x_poll_rx`, which in turn calls `mt76_dma_rx_poll`. `mt76_dma_rx_poll` calls `mt76_dma_rx_process`, which finally calls `mt76_dma_dequeue`. And `mt76_dma_dequeue` calls `mt76_dma_get_buf`. Aha! So, `mt76_dma_get_buf` is indeed reachable via USB for `mt7921u`. Since `mt76_dma_get_buf` is static, we can narrow down our focus on `mt76_dma_rx_poll`. Let's identify the key functions or symbols that require focused attention. I'll need a list of functions affected by the patch. Considering the changes, the initial list I've come up with is: * `mt7663_usb_sdio_tx_prepare_skb` * `mt76_connac2_mac_fill_rx_rate` * `mt76_connac_mcu_sta_tlv` * `mt76_dma_rx_poll` * `mt76_abort_scan` * `mt76_scan_work` Let's double-check if there are others. I'll go through the relevant source files (`mt76_connac_mcu.c`, `mt76_connac_mac.c`, `mt7615/usb_sdio.c`, `mt76/scan.c`). In `mt76_connac_mcu.c`, `mt76_connac_mcu_sta_he_tlv` is static and called by `mt76_connac_mcu_sta_tlv`. So, `mt76_connac_mcu_sta_tlv` is good to include. In `mt76_connac_mac.c`, `mt76_connac2_mac_fill_rx_rate` is exported, so it's on the list. In `mt7615/usb_sdio.c`, `mt7663_usb_sdio_tx_prepare_skb` is exported, so it's included as well. In `mt76/scan.c`, `mt76_abort_scan` and `mt76_scan_work` are both exported, and so they are good. So, that list of six functions looks comprehensive. What about other functions in the driver? Let's check `mt7615_tx_prepare_skb`, which is in `mt7615/pci_mac.c`, and `mt7915_mac_full_reset` and `mt7996_mac_full_reset`, which are in `mt7915/mac.c` and `mt7996/mac.c` respectively. These are PCIe-only, so since we're using QEMU with a USB interface, we can exclude them. Now, let's confirm the configuration dependencies. Does `MT7663U` actually build `mt7615/usb_sdio.c`? Yes, `MT7663U` selects `MT7663_USB_SDIO_COMMON`, which compiles `usb_sd |
| 75/2 | 2026/07/25 19:09 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"MT7663U",
"MT7921U",
"MT7925U"
],
"FocusSymbols": [
"mt7663_usb_sdio_tx_prepare_skb",
"mt76_connac2_mac_fill_rx_rate",
"mt76_connac_mcu_sta_tlv",
"mt76_dma_rx_poll",
"mt76_abort_scan",
"mt76_scan_work"
],
"Reasoning": "The patch modifies the MediaTek mt76 wireless driver, including core DMA, MAC, MCU, and scanning logic, as well as specific drivers like mt7615, mt7915, and mt7996. While mt7915 and mt7996 are PCIe-only and not reachable in standard QEMU, the mt76 core and mt7615 driver have USB support (e.g., MT7663U, MT7921U, MT7925U) which can be fuzzed via USB emulation (dummy_hcd). The changes include functional modifications to RX rate reporting, STA HE TLV parsing, DMA buffer handling, and scan channel locking, all of which are reachable via the USB driver paths.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"MT7663U",
"MT7921U",
"MT7925U"
],
"FocusSymbols": [
"mt7663_usb_sdio_tx_prepare_skb",
"mt76_connac2_mac_fill_rx_rate",
"mt76_connac_mcu_sta_tlv",
"mt76_dma_rx_poll",
"mt76_abort_scan",
"mt76_scan_work"
],
"Reasoning": "The patch modifies the MediaTek mt76 wireless driver, including core DMA, MAC, MCU, and scanning logic, as well as specific drivers like mt7615, mt7915, and mt7996. While mt7915 and mt7996 are PCIe-only and not reachable in standard QEMU, the mt76 core and mt7615 driver have USB support (e.g., MT7663U, MT7921U, MT7925U) which can be fuzzed via USB emulation (dummy_hcd). The changes include functional modifications to RX rate reporting, STA HE TLV parsing, DMA buffer handling, and scan channel locking, all of which are reachable via the USB driver paths.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|