| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/10 06:12 | flow | patch-triage |
2mArgs:null Results: {
"EnableConfigs": [
"MT7925E",
"MAC80211",
"WLAN",
"WLAN_VENDOR_MEDIATEK"
],
"FocusSymbols": [
"mt7925e_axidma_cal_cache_init",
"mt7925_axidma_alloc",
"mt7925_axidma_free",
"mt7925_mcu_send_axidma_info",
"mt7925_mcu_send_fact_cal_mapping_tbl",
"mt7925_mcu_fact_cal_set_bypass"
],
"KMSANReasoning": "The patch introduces a new factory calibration caching mechanism for the MT7925 wireless driver using AXI DMA. All structures sent to the MCU (e.g., `mt7925_axidma_info_req`, `mt7925_fact_cal_req`, `mt7925_fact_cal_mapping_tbl`, and the bypass request) are fully zero-initialized using `kzalloc`, `memset`, or C struct initializers. The DMA buffer itself is allocated with `dma_alloc_coherent`, which guarantees zero-initialization. There is no risk of uninitialized memory being leaked to the MCU or user space, nor is there any control flow dependent on uninitialized variables. Any potential memory corruption, out-of-bounds access, or use-after-free bugs in this code would be effectively caught by standard KASAN. Therefore, a dedicated KMSAN fuzzing session is not required.",
"NeedsKMSAN": false,
"Reasoning": "The patch introduces a new AXI DMA factory calibration cache feature for the MediaTek MT7925 PCIe Wi-Fi driver. It adds DMA memory allocation, MCU messaging, and state management to bypass full calibration by reusing cached data. These are functional changes to the driver's initialization and reset paths, reachable via PCI device probing and MMIO/DMA interactions, which can be fuzzed by syzkaller's PCI fuzzer.",
"WorthFuzzing": true
} |
| 1/1 | 2026/08/10 06:12 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 211b10cacfc32c164f8edcef15e7517d1020bc42\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Mon Aug 10 06:12:37 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h\nindex 0ededa569e9a5..e46cb4ae37a98 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h\n+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h\n@@ -1357,9 +1357,11 @@ enum {\n \tMCU_UNI_CMD_ALL_STA_INFO = 0x6e,\n \tMCU_UNI_CMD_ASSERT_DUMP = 0x6f,\n \tMCU_UNI_CMD_EXT_EEPROM_CTRL = 0x74,\n+\tMCU_UNI_CMD_FACT_CAL = 0x7c,\n \tMCU_UNI_CMD_RADIO_STATUS = 0x80,\n \tMCU_UNI_CMD_MLD = 0x82,\n \tMCU_UNI_CMD_SDO = 0x88,\n+\tMCU_UNI_CMD_AXIDMA = 0xa2,\n };\n \n enum {\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7925/Makefile b/drivers/net/wireless/mediatek/mt76/mt7925/Makefile\nindex f9dcc0bba393c..33539121a15cd 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7925/Makefile\n+++ b/drivers/net/wireless/mediatek/mt76/mt7925/Makefile\n@@ -6,5 +6,5 @@ obj-$(CONFIG_MT7925U) += mt7925u.o\n \n mt7925-common-y := mac.o mcu.o regd.o main.o init.o debugfs.o nan.o\n mt7925-common-$(CONFIG_NL80211_TESTMODE) += testmode.o\n-mt7925e-y := pci.o pci_mac.o pci_mcu.o\n+mt7925e-y := pci.o pci_mac.o pci_mcu.o cached_cal.o\n mt7925u-y := usb.o\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c b/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c\nnew file mode 100644\nindex 0000000000000..03bd682f1224b\n--- /dev/null\n+++ b/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c\n@@ -0,0 +1,304 @@\n+// SPDX-License-Identifier: BSD-3-Clause-Clear\n+/* Copyright (C) 2026 MediaTek Inc. */\n+\n+#include \u003clinux/dma-mapping.h\u003e\n+#include \"../mt792x.h\"\n+#include \"cached_cal.h\"\n+\n+static void mt7925_cal_cache_calc_layout(struct mt7925_cal_cache_layout *l)\n+{\n+\tu32 hdr = sizeof(struct mt7925_fact_cal_buf_info);\n+\n+\tl-\u003ecommon_stride = hdr + MT7925_FACT_CAL_LEN_COM;\n+\tl-\u003egroup_stride = hdr + MT7925_FACT_CAL_LEN_GRP;\n+\tl-\u003echannel_stride = hdr + MT7925_FACT_CAL_LEN_CH;\n+\n+\tl-\u003ecommon_off = 0;\n+\tl-\u003egroup_off = l-\u003ecommon_off +\n+\t\tl-\u003ecommon_stride * MT7925_FACT_CAL_COMMON_BAND_NUM;\n+\tl-\u003echannel_off = l-\u003egroup_off +\n+\t\tl-\u003egroup_stride * MT7925_FACT_CAL_GROUP_NUM;\n+\tl-\u003emapping_off = l-\u003echannel_off +\n+\t\tl-\u003echannel_stride * MT7925_FACT_CAL_CH_NUM_ALL;\n+\tl-\u003etotal = l-\u003emapping_off +\n+\t\tsizeof(struct mt7925_fact_cal_mapping_tbl);\n+}\n+\n+static u32 mt7925_cal_cache_region_size(void)\n+{\n+\tstruct mt7925_cal_cache_layout l;\n+\n+\tmt7925_cal_cache_calc_layout(\u0026l);\n+\n+\treturn l.total;\n+}\n+\n+int mt7925_axidma_alloc(struct mt792x_dev *dev)\n+{\n+\tu32 total_size;\n+\tdma_addr_t dma_addr;\n+\tvoid *va;\n+\n+\tif (dev-\u003ecached_cal.va)\n+\t\treturn 0;\n+\n+\ttotal_size = mt7925_cal_cache_region_size();\n+\n+\tva = dma_alloc_coherent(dev-\u003emt76.dev, total_size, \u0026dma_addr,\n+\t\t\t\tGFP_KERNEL);\n+\tif (!va)\n+\t\treturn -ENOMEM;\n+\n+\tdev-\u003ecached_cal.va = va;\n+\tdev-\u003ecached_cal.dma_addr = dma_addr;\n+\tdev-\u003ecached_cal.size = total_size;\n+\n+\treturn 0;\n+}\n+\n+void mt7925_axidma_free(struct mt792x_dev *dev)\n+{\n+\tif (!dev-\u003ecached_cal.va)\n+\t\treturn;\n+\n+\tdma_free_coherent(dev-\u003emt76.dev, dev-\u003ecached_cal.size,\n+\t\t\t dev-\u003ecached_cal.va, dev-\u003ecached_cal.dma_addr);\n+\n+\tmemset(\u0026dev-\u003ecached_cal, 0, sizeof(dev-\u003ecached_cal));\n+}\n+\n+int mt7925_mcu_send_axidma_info(struct mt792x_dev *dev)\n+{\n+\tstruct mt7925_axidma_info_req *req;\n+\tu32 remap_base, pa_offset;\n+\tint ret;\n+\n+\tif (!dev-\u003ecached_cal.va)\n+\t\treturn -EINVAL;\n+\n+\treq = kzalloc(sizeof(*req), GFP_KERNEL);\n+\tif (!req)\n+\t\treturn -ENOMEM;\n+\n+\tremap_base = (u32)(dev-\u003ecached_cal.dma_addr \u003e\u003e 16);\n+\tpa_offset = (u32)(dev-\u003ecached_cal.dma_addr \u0026 0xFFFF);\n+\n+\treq-\u003eremap.tag = cpu_to_le16(MT7925_AXIDMA_TAG_REMAP);\n+\treq-\u003eremap.len = cpu_to_le16(sizeof(req-\u003eremap));\n+\treq-\u003eremap.remap_addr = cpu_to_le32(remap_base);\n+\n+\treq-\u003efact_cal.tag = cpu_to_le16(MT7925_AXIDMA_TAG_FACT_CAL);\n+\treq-\u003efact_cal.len = cpu_to_le16(sizeof(req-\u003efact_cal));\n+\treq-\u003efact_cal.host_addr_offset = cpu_to_le32(pa_offset);\n+\treq-\u003efact_cal.size = cpu_to_le32(dev-\u003ecached_cal.size);\n+\treq-\u003efact_cal.bound = cpu_to_le32(pa_offset + dev-\u003ecached_cal.size - 1);\n+\n+\tret = mt76_mcu_send_msg(\u0026dev-\u003emt76, MCU_UNI_CMD(AXIDMA),\n+\t\t\t\treq, sizeof(*req), true);\n+\n+\tkfree(req);\n+\n+\tif (ret)\n+\t\tdev_err(dev-\u003emt76.dev,\n+\t\t\t\"failed to send AXI DMA info: %d\\n\", ret);\n+\n+\treturn ret;\n+}\n+\n+static bool mt7925_cal_cache_read_slot(struct mt792x_dev *dev, u32 region_off,\n+\t\t\t\t u32 stride, u32 idx,\n+\t\t\t\t u32 *cal_param, u32 *total_buf_num)\n+{\n+\tconst struct mt7925_fact_cal_buf_info *bi;\n+\tu32 off = region_off + stride * idx;\n+\n+\tif (!dev-\u003ecached_cal.va || off + sizeof(*bi) \u003e dev-\u003ecached_cal.size)\n+\t\treturn false;\n+\n+\tbi = (const struct mt7925_fact_cal_buf_info *)\n+\t\t((const u8 *)dev-\u003ecached_cal.va + off);\n+\tif (cal_param)\n+\t\t*cal_param = le32_to_cpu(bi-\u003ecal_param);\n+\tif (total_buf_num)\n+\t\t*total_buf_num = le32_to_cpu(bi-\u003etotal_buf_num);\n+\treturn true;\n+}\n+\n+static void mt7925_fact_cal_build_mapping_tbl(struct mt792x_dev *dev,\n+\t\t\t\t\t struct mt7925_fact_cal_mapping_tbl *tbl)\n+{\n+\tdma_addr_t common_pa, group_pa, channel_pa, mapping_pa;\n+\tu32 hdr = sizeof(struct mt7925_fact_cal_buf_info);\n+\tdma_addr_t base = dev-\u003ecached_cal.dma_addr;\n+\tstruct mt7925_cal_cache_layout l;\n+\n+\tmt7925_cal_cache_calc_layout(\u0026l);\n+\n+\tcommon_pa = base + l.common_off;\n+\tgroup_pa = base + l.group_off;\n+\tchannel_pa = base + l.channel_off;\n+\tmapping_pa = base + l.mapping_off;\n+\n+\tmemset(tbl, 0, sizeof(*tbl));\n+\n+\ttbl-\u003ecommon.phy_addr_h = cpu_to_le32(upper_32_bits(common_pa));\n+\ttbl-\u003ecommon.phy_addr_l = cpu_to_le32(lower_32_bits(common_pa));\n+\ttbl-\u003ecommon.offset = cpu_to_le32(l.common_stride);\n+\n+\ttbl-\u003egroup.phy_addr_h = cpu_to_le32(upper_32_bits(group_pa));\n+\ttbl-\u003egroup.phy_addr_l = cpu_to_le32(lower_32_bits(group_pa));\n+\ttbl-\u003egroup.offset = cpu_to_le32(l.group_stride);\n+\n+\ttbl-\u003echannel.phy_addr_h = cpu_to_le32(upper_32_bits(channel_pa));\n+\ttbl-\u003echannel.phy_addr_l = cpu_to_le32(lower_32_bits(channel_pa));\n+\ttbl-\u003echannel.offset = cpu_to_le32(l.channel_stride);\n+\n+\tif (dev-\u003ecached_cal.reused) {\n+\t\tu32 i, cal_param, total_buf_num;\n+\n+\t\tfor (i = 0; i \u003c MT7925_FACT_CAL_COMMON_BAND_NUM; i++)\n+\t\t\tif (mt7925_cal_cache_read_slot(dev, l.common_off,\n+\t\t\t\t\t\t l.common_stride, i,\n+\t\t\t\t\t\t \u0026cal_param, NULL))\n+\t\t\t\ttbl-\u003ecommon.band[i] = cal_param \u0026 0xff;\n+\n+\t\tfor (i = 0; i \u003c MT7925_FACT_CAL_GROUP_NUM; i++)\n+\t\t\tif (mt7925_cal_cache_read_slot(dev, l.group_off,\n+\t\t\t\t\t\t l.group_stride, i,\n+\t\t\t\t\t\t \u0026cal_param, NULL))\n+\t\t\t\ttbl-\u003egroup.group[i] = cal_param \u0026 0xff;\n+\n+\t\tfor (i = 0; i \u003c MT7925_FACT_CAL_CH_NUM_ALL; i++)\n+\t\t\tif (mt7925_cal_cache_read_slot(dev, l.channel_off,\n+\t\t\t\t\t\t l.channel_stride, i,\n+\t\t\t\t\t\t \u0026cal_param,\n+\t\t\t\t\t\t \u0026total_buf_num)) {\n+\t\t\t\ttbl-\u003echannel.cal_param[i] =\n+\t\t\t\t\tcpu_to_le32(cal_param);\n+\t\t\t\ttbl-\u003echannel.total_buf_num[i] =\n+\t\t\t\t\ttotal_buf_num \u0026 0xff;\n+\t\t\t}\n+\t}\n+\n+\ttbl-\u003ebuf_info_size = cpu_to_le32(hdr);\n+\ttbl-\u003ephy_addr_h = cpu_to_le32(upper_32_bits(mapping_pa));\n+\ttbl-\u003ephy_addr_l = cpu_to_le32(lower_32_bits(mapping_pa));\n+}\n+\n+static int mt7925_mcu_fact_cal_rapid_set(struct mt792x_dev *dev, u8 cal_type,\n+\t\t\t\t\t u32 seq_num, bool done,\n+\t\t\t\t\t const void *data, u32 data_len)\n+{\n+\tstruct mt7925_fact_cal_req *req;\n+\tint ret;\n+\n+\tif (data_len \u003e MT7925_FACT_CAL_DATA_BUF_LEN)\n+\t\treturn -EINVAL;\n+\n+\treq = kzalloc(sizeof(*req), GFP_KERNEL);\n+\tif (!req)\n+\t\treturn -ENOMEM;\n+\n+\treq-\u003eset.tag = cpu_to_le16(MT7925_FACT_CAL_TAG_RAPID_SET);\n+\treq-\u003eset.len = cpu_to_le16(sizeof(req-\u003eset));\n+\treq-\u003eset.seq_num = cpu_to_le32(seq_num);\n+\treq-\u003eset.buf_data_len = cpu_to_le32(data_len);\n+\treq-\u003eset.cal_type = cal_type;\n+\treq-\u003eset.done = done;\n+\tif (data \u0026\u0026 data_len)\n+\t\tmemcpy(req-\u003eset.buf_data, data, data_len);\n+\n+\t/* Wait for the ACK on the final chunk only: the FW applies the whole\n+\t * table there (DMAs the cached common / power-on group cal data in and\n+\t * programs the PHY), so its ACK is the completion point. Waiting also\n+\t * drains the ACKs the earlier chunks left in the MCU response queue,\n+\t * since UNI commands always request one.\n+\t */\n+\tret = mt76_mcu_send_msg(\u0026dev-\u003emt76, MCU_UNI_CMD(FACT_CAL),\n+\t\t\t\treq, sizeof(*req), done);\n+\tkfree(req);\n+\n+\treturn ret;\n+}\n+\n+int mt7925_mcu_send_fact_cal_mapping_tbl(struct mt792x_dev *dev)\n+{\n+\tstruct mt7925_fact_cal_mapping_tbl *tbl;\n+\t__le32 cfg[MT7925_FACT_CAL_BUF_CFG_LEN / sizeof(__le32)] = {0};\n+\tu32 seq = 0, off = 0, left;\n+\tint ret;\n+\n+\tif (!dev-\u003ecached_cal.va)\n+\t\treturn -EINVAL;\n+\n+\ttbl = kzalloc(sizeof(*tbl), GFP_KERNEL);\n+\tif (!tbl)\n+\t\treturn -ENOMEM;\n+\n+\tmt7925_fact_cal_build_mapping_tbl(dev, tbl);\n+\n+\tcfg[1] = cpu_to_le32(sizeof(*tbl));\n+\tcfg[2] = cpu_to_le32(MT7925_FACT_CAL_DATA_BUF_NUM_MAX);\n+\tret = mt7925_mcu_fact_cal_rapid_set(dev, MT7925_FACT_CAL_TYPE_MAPPING_TBL,\n+\t\t\t\t\t seq, false, cfg, sizeof(cfg));\n+\tif (ret) {\n+\t\tdev_err(dev-\u003emt76.dev,\n+\t\t\t\"fact-cal mapping tbl header send failed (seq=%u): %d\\n\",\n+\t\t\tseq, ret);\n+\t\tgoto out;\n+\t}\n+\n+\tleft = sizeof(*tbl);\n+\twhile (left) {\n+\t\tu32 chunk = min_t(u32, left, MT7925_FACT_CAL_DATA_BUF_LEN);\n+\n+\t\tret = mt7925_mcu_fact_cal_rapid_set(dev,\n+\t\t\t\t\t\t MT7925_FACT_CAL_TYPE_MAPPING_TBL,\n+\t\t\t\t\t\t ++seq, false,\n+\t\t\t\t\t\t (u8 *)tbl + off, chunk);\n+\t\tif (ret) {\n+\t\t\tdev_err(dev-\u003emt76.dev,\n+\t\t\t\t\"fact-cal mapping tbl data send failed (seq=%u, off=%u, chunk=%u): %d\\n\",\n+\t\t\t\tseq, off, chunk, ret);\n+\t\t\tgoto out;\n+\t\t}\n+\n+\t\toff += chunk;\n+\t\tleft -= chunk;\n+\t}\n+\n+\tret = mt7925_mcu_fact_cal_rapid_set(dev, MT7925_FACT_CAL_TYPE_MAPPING_TBL,\n+\t\t\t\t\t ++seq, true, NULL, 0);\n+\tif (ret) {\n+\t\tdev_err(dev-\u003emt76.dev,\n+\t\t\t\"fact-cal mapping tbl done send failed (seq=%u): %d\\n\",\n+\t\t\tseq, ret);\n+\t\tgoto out;\n+\t}\n+out:\n+\tkfree(tbl);\n+\n+\treturn ret;\n+}\n+\n+int mt7925_mcu_fact_cal_set_bypass(struct mt792x_dev *dev, bool enable)\n+{\n+\tstruct {\n+\t\tu8 _rsv[4];\n+\n+\t\tstruct {\n+\t\t\t__le16 tag;\n+\t\t\t__le16 len;\n+\t\t\t__le32 data;\n+\t\t} __packed update_flag;\n+\t} req = {\n+\t\t.update_flag = {\n+\t\t\t.tag = cpu_to_le16(MT7925_FACT_CAL_TAG_UPDATE_FLAG),\n+\t\t\t.len = cpu_to_le16(sizeof(req.update_flag)),\n+\t\t\t.data = cpu_to_le32(enable ? 1 : 0),\n+\t\t},\n+\t};\n+\n+\treturn mt76_mcu_send_msg(\u0026dev-\u003emt76, MCU_UNI_CMD(FACT_CAL),\n+\t\t\t\t \u0026req, sizeof(req), false);\n+}\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h b/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h\nnew file mode 100644\nindex 0000000000000..6572513b76466\n--- /dev/null\n+++ b/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h\n@@ -0,0 +1,151 @@\n+/* SPDX-License-Identifier: BSD-3-Clause-Clear */\n+/* Copyright (C) 2026 MediaTek Inc. */\n+\n+#ifndef __CACHED_CAL_H\n+#define __CACHED_CAL_H\n+\n+enum mt7925_axidma_info_tag {\n+\tMT7925_AXIDMA_TAG_REMAP = 0,\n+\tMT7925_AXIDMA_TAG_FACT_CAL = 1,\n+\tMT7925_AXIDMA_TAG_NUM\n+};\n+\n+enum mt7925_fact_cal_tag {\n+\tMT7925_FACT_CAL_TAG_TRIGGER\t= 2,\n+\tMT7925_FACT_CAL_TAG_UPDATE_FLAG\t= 3,\n+\tMT7925_FACT_CAL_TAG_RAPID_GET\t= 4,\n+\tMT7925_FACT_CAL_TAG_RAPID_SET\t= 5,\n+};\n+\n+enum mt7925_fact_cal_type {\n+\tMT7925_FACT_CAL_TYPE_COMMON\t\t= 0,\n+\tMT7925_FACT_CAL_TYPE_GROUP\t\t= 1,\n+\tMT7925_FACT_CAL_TYPE_CHANNEL\t\t= 2,\n+\tMT7925_FACT_CAL_TYPE_MAPPING_TBL\t= 4,\n+};\n+\n+#define MT7925_FACT_CAL_DATA_BUF_LEN\t\t1400\n+#define MT7925_FACT_CAL_BUF_CFG_LEN\t\t\t16\n+#define MT7925_FACT_CAL_DATA_BUF_NUM_MAX\t4\n+#define MT7925_FACT_CAL_BUF_CFG_U32_LEN\t\t4\n+#define MT7925_FACT_CAL_DATA_MAX_BUF_LEN \\\n+\t(MT7925_FACT_CAL_DATA_BUF_NUM_MAX * MT7925_FACT_CAL_BUF_CFG_U32_LEN)\n+\n+#define MT7925_FACT_CAL_COMMON_BAND_NUM\t\t2\n+#define MT7925_FACT_CAL_GROUP_NUM\t\t35\n+#define MT7925_FACT_CAL_CH_NUM_2G\t\t14\n+#define MT7925_FACT_CAL_CH_NUM_5G\t\t68\n+#define MT7925_FACT_CAL_CH_NUM_6G\t\t109\n+#define MT7925_FACT_CAL_CH_NUM_ALL \\\n+\t(MT7925_FACT_CAL_CH_NUM_2G + MT7925_FACT_CAL_CH_NUM_5G + \\\n+\t MT7925_FACT_CAL_CH_NUM_6G)\n+\n+#define MT7925_FACT_CAL_LEN_COM\t\t\t600\n+#define MT7925_FACT_CAL_LEN_GRP\t\t\t4500\n+#define MT7925_FACT_CAL_LEN_CH\t\t\t2800\n+\n+struct mt7925_fact_cal_buf_info {\n+\t__le32 cal_type;\n+\t__le32 cal_param;\n+\t__le32 buf_seq_num;\n+\t__le32 total_buf_num;\n+\t__le32 buf_data_len;\n+\tu8 valid;\n+\tu8 done;\n+\tu8 rsv[2];\n+\t__le32 buf_cfg_info[MT7925_FACT_CAL_DATA_MAX_BUF_LEN];\n+} __packed;\n+\n+static_assert(sizeof(struct mt7925_fact_cal_buf_info) == 88,\n+\t \"buf_info must match the MT7928 FW (88 bytes) or it rejects the mapping table\");\n+\n+struct mt7925_fact_cal_common_map {\n+\t__le32 phy_addr_h;\n+\t__le32 phy_addr_l;\n+\t__le32 offset;\n+\tu8 band[MT7925_FACT_CAL_COMMON_BAND_NUM];\n+\tu8 rsv[2];\n+} __packed;\n+\n+struct mt7925_fact_cal_group_map {\n+\t__le32 phy_addr_h;\n+\t__le32 phy_addr_l;\n+\t__le32 offset;\n+\tu8 group[MT7925_FACT_CAL_GROUP_NUM];\n+\tu8 rsv;\n+} __packed;\n+\n+struct mt7925_fact_cal_channel_map {\n+\t__le32 phy_addr_h;\n+\t__le32 phy_addr_l;\n+\t__le32 offset;\n+\t__le32 cal_param[MT7925_FACT_CAL_CH_NUM_ALL];\n+\tu8 total_buf_num[MT7925_FACT_CAL_CH_NUM_ALL];\n+\tu8 rsv;\n+} __packed;\n+\n+struct mt7925_fact_cal_mapping_tbl {\n+\tstruct mt7925_fact_cal_common_map common;\n+\tstruct mt7925_fact_cal_group_map group;\n+\tstruct mt7925_fact_cal_channel_map channel;\n+\t__le32 buf_info_size;\n+\t__le32 phy_addr_h;\n+\t__le32 phy_addr_l;\n+} __packed;\n+\n+static_assert(sizeof(struct mt7925_fact_cal_mapping_tbl) == 1044,\n+\t \"mapping table must match the MT7928 FW (1044 bytes) or the FW parse corrupts\");\n+\n+struct mt7925_cal_cache_layout {\n+\tu32 common_off, group_off, channel_off, mapping_off;\n+\tu32 common_stride, group_stride, channel_stride;\n+\tu32 total;\n+};\n+\n+struct mt7925_axidma_info_req {\n+\tu8 _rsv[4];\n+\n+\tstruct {\n+\t\t__le16 tag;\n+\t\t__le16 len;\n+\t\t__le32 remap_addr;\n+\t\t__le32 reserved;\n+\t} __packed remap;\n+\n+\tstruct {\n+\t\t__le16 tag;\n+\t\t__le16 len;\n+\t\t__le32 host_addr_offset;\n+\t\t__le32 size;\n+\t\t__le32 bound;\n+\t\t__le32 reserved;\n+\t} __packed fact_cal;\n+} __packed;\n+\n+struct mt7925_fact_cal_req {\n+\tu8 _rsv[4];\n+\n+\tstruct {\n+\t\t__le16 tag;\n+\t\t__le16 len;\n+\t\t__le32 data;\n+\t\t__le32 seq_num;\n+\t\t__le32 buf_data_len;\n+\t\tu8 cal_type;\n+\t\tu8 done;\n+\t\tu8 rsv[2];\n+\t\tu8 buf_data[MT7925_FACT_CAL_DATA_BUF_LEN];\n+\t} __packed set;\n+} __packed;\n+\n+int mt7925_axidma_alloc(struct mt792x_dev *dev);\n+\n+void mt7925_axidma_free(struct mt792x_dev *dev);\n+\n+int mt7925_mcu_send_axidma_info(struct mt792x_dev *dev);\n+\n+int mt7925_mcu_send_fact_cal_mapping_tbl(struct mt792x_dev *dev);\n+\n+int mt7925_mcu_fact_cal_set_bypass(struct mt792x_dev *dev, bool enable);\n+\n+#endif /* __CACHED_CAL_H */\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h\nindex 321e732347f2f..4d79c1e66e66b 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h\n+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h\n@@ -353,6 +353,7 @@ int mt7925_mcu_parse_response(struct mt76_dev *mdev, int cmd,\n \n int mt7925e_mac_reset(struct mt792x_dev *dev);\n int mt7925e_mcu_init(struct mt792x_dev *dev);\n+void mt7925e_axidma_cal_cache_init(struct mt792x_dev *dev);\n void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data);\n void mt7928_mac_add_txs_msg(struct mt792x_dev *dev, void *evt);\n void mt7925_set_runtime_pm(struct mt792x_dev *dev);\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c\nindex 02ef09dd797da..724abd2be57c5 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c\n+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c\n@@ -9,6 +9,7 @@\n #include \"mac.h\"\n #include \"mcu.h\"\n #include \"regd.h\"\n+#include \"cached_cal.h\"\n #include \"../dma.h\"\n \n static const struct pci_device_id mt7925_pci_device_table[] = {\n@@ -38,6 +39,62 @@ static int mt7925e_init_reset(struct mt792x_dev *dev)\n \treturn mt792x_wpdma_reset(dev, true);\n }\n \n+/* Set up the factory-calibration cache in host memory. PCIe only: the FW\n+ * reaches the buffer through AXI DMA, so it has no meaning on other buses.\n+ * Every failure just leaves the cache off, which is not fatal.\n+ */\n+void mt7925e_axidma_cal_cache_init(struct mt792x_dev *dev)\n+{\n+\tif (!(dev-\u003ephy.chip_cap \u0026 MT792x_CHIP_CAP_AXIDMA_EN))\n+\t\treturn;\n+\n+\tif (dev-\u003ecached_cal.va) {\n+\t\t/* Carried-over buffer still holds FW-written cal data. */\n+\t\tdev-\u003ecached_cal.reused = true;\n+\t} else {\n+\t\tif (mt7925_axidma_alloc(dev)) {\n+\t\t\tdev_warn(dev-\u003emt76.dev,\n+\t\t\t\t \"AXI DMA cal cache disabled: buffer alloc failed\\n\");\n+\t\t\treturn;\n+\t\t}\n+\t\t/* Freshly allocated buffer is zeroed: no cal data yet. */\n+\t\tdev-\u003ecached_cal.reused = false;\n+\t}\n+\n+\tif (mt7925_mcu_send_axidma_info(dev)) {\n+\t\tdev_warn(dev-\u003emt76.dev,\n+\t\t\t \"AXI DMA cal cache disabled: info cmd to FW failed\\n\");\n+\t\treturn;\n+\t}\n+\n+\t/* Enable the bypass-cal flow so the FW reuses cached cal data\n+\t * (common / power-on group) instead of running a full calibration;\n+\t * must be set before the mapping table is sent.\n+\t */\n+\tif (mt7925_mcu_fact_cal_set_bypass(dev, true)) {\n+\t\tdev_warn(dev-\u003emt76.dev,\n+\t\t\t \"AXI DMA cal cache disabled: bypass flag set failed\\n\");\n+\t\treturn;\n+\t}\n+\n+\tif (mt7925_mcu_send_fact_cal_mapping_tbl(dev)) {\n+\t\tdev_warn(dev-\u003emt76.dev,\n+\t\t\t \"AXI DMA cal cache disabled: mapping tbl send failed\\n\");\n+\t\treturn;\n+\t}\n+\n+\tif (mt7925_mcu_fact_cal_set_bypass(dev, false)) {\n+\t\tdev_warn(dev-\u003emt76.dev,\n+\t\t\t \"AXI DMA cal cache disabled: bypass flag set failed\\n\");\n+\t\treturn;\n+\t}\n+\n+\tdev_info(dev-\u003emt76.dev,\n+\t\t \"AXI DMA cal cache enabled (DMA=%pad, size=%u, reused=%d)\\n\",\n+\t\t \u0026dev-\u003ecached_cal.dma_addr, dev-\u003ecached_cal.size,\n+\t\t dev-\u003ecached_cal.reused);\n+}\n+\n static void mt7925e_unregister_device(struct mt792x_dev *dev)\n {\n \tint i;\n@@ -58,6 +115,9 @@ static void mt7925e_unregister_device(struct mt792x_dev *dev)\n \n \tmt7925_tx_token_put(dev);\n \t__mt792x_mcu_drv_pmctrl(dev);\n+\n+\tmt7925_axidma_free(dev);\n+\n \tmt792x_dma_cleanup(dev);\n \tmt792x_wfsys_reset(dev);\n \tskb_queue_purge(\u0026dev-\u003emt76.mcu.res_q);\n@@ -587,7 +647,7 @@ static int mt7925_pci_probe(struct pci_dev *pdev,\n \tis_mt7928_hw = (pdev-\u003edevice == 0x7928 || pdev-\u003edevice == 0x7935);\n \n \tif (is_mt7928_hw)\n-\t\tret = dma_set_mask(\u0026pdev-\u003edev, DMA_BIT_MASK(34));\n+\t\tret = dma_set_mask_and_coherent(\u0026pdev-\u003edev, DMA_BIT_MASK(34));\n \telse\n \t\tret = dma_set_mask(\u0026pdev-\u003edev, DMA_BIT_MASK(32));\n \ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c\nindex 8477d21abc660..c90f129b3a34e 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c\n+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c\n@@ -135,6 +135,8 @@ int mt7925e_mac_reset(struct mt792x_dev *dev)\n \tif (err)\n \t\tgoto out;\n \n+\tmt7925e_axidma_cal_cache_init(dev);\n+\n \terr = mt7925_mcu_set_eeprom(dev);\n \tif (err)\n \t\tgoto out;\ndiff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c\nindex 72707eddc3db6..258f3753db1fb 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c\n+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c\n@@ -46,6 +46,8 @@ int mt7925e_mcu_init(struct mt792x_dev *dev)\n \tmt76_rmw_field(dev, dev-\u003epcie_reg-\u003epm, MT_PCIE_MAC_PM_L0S_DIS, 1);\n \n \terr = mt7925_run_firmware(dev);\n+\tif (!err)\n+\t\tmt7925e_axidma_cal_cache_init(dev);\n \n \tmt76_queue_tx_cleanup(dev, dev-\u003emt76.q_mcu[MT_MCUQ_FWDL], false);\n \ndiff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h\nindex 9efc251cb745f..740d517eb38bb 100644\n--- a/drivers/net/wireless/mediatek/mt76/mt792x.h\n+++ b/drivers/net/wireless/mediatek/mt76/mt792x.h\n@@ -33,6 +33,7 @@\n #define MT792x_CHIP_CAP_REGD_EN BIT(5)\n #define MT792x_CHIP_CAP_MLO_EN BIT(8)\n #define MT792x_CHIP_CAP_MLO_EML_EN BIT(9)\n+#define MT792x_CHIP_CAP_AXIDMA_EN BIT(16)\n \n /* NOTE: used to map mt76_rates. idx may change if firmware expands table */\n #define MT792x_BASIC_RATES_TBL\t14\n@@ -342,6 +343,13 @@ struct mt792x_dev {\n \tstruct ieee80211_vif *nan_vif;\n \tconst struct ieee80211_iface_combination *iface_combinations;\n \tint n_iface_combinations;\n+\n+\tstruct {\n+\t\tvoid *va;\n+\t\tdma_addr_t dma_addr;\n+\t\tu32 size;\n+\t\tbool reused;\n+\t} cached_cal;\n };\n \n static inline struct mt792x_bss_conf *\n"
} |
| 2/1 | 2026/08/10 06:12 | agent | patch-evaluator |
1mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"MT7925E",
"MAC80211",
"WLAN",
"WLAN_VENDOR_MEDIATEK"
],
"FocusSymbols": [
"mt7925e_axidma_cal_cache_init",
"mt7925_axidma_alloc",
"mt7925_axidma_free",
"mt7925_mcu_send_axidma_info",
"mt7925_mcu_send_fact_cal_mapping_tbl",
"mt7925_mcu_fact_cal_set_bypass"
],
"Reasoning": "The patch introduces a new AXI DMA factory calibration cache feature for the MediaTek MT7925 PCIe Wi-Fi driver. It adds DMA memory allocation, MCU messaging, and state management to bypass full calibration by reusing cached data. These are functional changes to the driver's initialization and reset paths, reachable via PCI device probing and MMIO/DMA interactions, which can be fuzzed by syzkaller's PCI fuzzer.",
"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 211b10cacfc32c164f8edcef15e7517d1020bc42
Author: syz-cluster <triage@syzkaller.com>
Date: Mon Aug 10 06:12:37 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
index 0ededa569e9a5..e46cb4ae37a98 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
@@ -1357,9 +1357,11 @@ enum {
MCU_UNI_CMD_ALL_STA_INFO = 0x6e,
MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
MCU_UNI_CMD_EXT_EEPROM_CTRL = 0x74,
+ MCU_UNI_CMD_FACT_CAL = 0x7c,
MCU_UNI_CMD_RADIO_STATUS = 0x80,
MCU_UNI_CMD_MLD = 0x82,
MCU_UNI_CMD_SDO = 0x88,
+ MCU_UNI_CMD_AXIDMA = 0xa2,
};
enum {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/Makefile b/drivers/net/wireless/mediatek/mt76/mt7925/Makefile
index f9dcc0bba393c..33539121a15cd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/Makefile
@@ -6,5 +6,5 @@ obj-$(CONFIG_MT7925U) += mt7925u.o
mt7925-common-y := mac.o mcu.o regd.o main.o init.o debugfs.o nan.o
mt7925-common-$(CONFIG_NL80211_TESTMODE) += testmode.o
-mt7925e-y := pci.o pci_mac.o pci_mcu.o
+mt7925e-y := pci.o pci_mac.o pci_mcu.o cached_cal.o
mt7925u-y := usb.o
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c b/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c
new file mode 100644
index 0000000000000..03bd682f1224b
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/* Copyright (C) 2026 MediaTek Inc. */
+
+#include <linux/dma-mapping.h>
+#include "../mt792x.h"
+#include "cached_cal.h"
+
+static void mt7925_cal_cache_calc_layout(struct mt7925_cal_cache_layout *l)
+{
+ u32 hdr = sizeof(struct mt7925_fact_cal_buf_info);
+
+ l->common_stride = hdr + MT7925_FACT_CAL_LEN_COM;
+ l->group_stride = hdr + MT7925_FACT_CAL_LEN_GRP;
+ l->channel_stride = hdr + MT7925_FACT_CAL_LEN_CH;
+
+ l->common_off = 0;
+ l->group_off = l->common_off +
+ l->common_stride * MT7925_FACT_CAL_COMMON_BAND_NUM;
+ l->channel_off = l->group_off +
+ l->group_stride * MT7925_FACT_CAL_GROUP_NUM;
+ l->mapping_off = l->channel_off +
+ l->channel_stride * MT7925_FACT_CAL_CH_NUM_ALL;
+ l->total = l->mapping_off +
+ sizeof(struct mt7925_fact_cal_mapping_tbl);
+}
+
+static u32 mt7925_cal_cache_region_size(void)
+{
+ struct mt7925_cal_cache_layout l;
+
+ mt7925_cal_cache_calc_layout(&l);
+
+ return l.total;
+}
+
+int mt7925_axidma_alloc(struct mt792x_dev *dev)
+{
+ u32 total_size;
+ dma_addr_t dma_addr;
+ void *va;
+
+ if (dev->cached_cal.va)
+ return 0;
+
+ total_size = mt7925_cal_cache_region_size();
+
+ va = dma_alloc_coherent(dev->mt76.dev, total_size, &dma_addr,
+ GFP_KERNEL);
+ if (!va)
+ return -ENOMEM;
+
+ dev->cached_cal.va = va;
+ dev->cached_cal.dma_addr = dma_addr;
+ dev->cached_cal.size = total_size;
+
+ return 0;
+}
+
+void mt7925_axidma_free(struct mt792x_dev *dev)
+{
+ if (!dev->cached_cal.va)
+ return;
+
+ dma_free_coherent(dev->mt76.dev, dev->cached_cal.size,
+ dev->cached_cal.va, dev->cached_cal.dma_addr);
+
+ memset(&dev->cached_cal, 0, sizeof(dev->cached_cal));
+}
+
+int mt7925_mcu_send_axidma_info(struct mt792x_dev *dev)
+{
+ struct mt7925_axidma_info_req *req;
+ u32 remap_base, pa_offset;
+ int ret;
+
+ if (!dev->cached_cal.va)
+ return -EINVAL;
+
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ remap_base = (u32)(dev->cached_cal.dma_addr >> 16);
+ pa_offset = (u32)(dev->cached_cal.dma_addr & 0xFFFF);
+
+ req->remap.tag = cpu_to_le16(MT7925_AXIDMA_TAG_REMAP);
+ req->remap.len = cpu_to_le16(sizeof(req->remap));
+ req->remap.remap_addr = cpu_to_le32(remap_base);
+
+ req->fact_cal.tag = cpu_to_le16(MT7925_AXIDMA_TAG_FACT_CAL);
+ req->fact_cal.len = cpu_to_le16(sizeof(req->fact_cal));
+ req->fact_cal.host_addr_offset = cpu_to_le32(pa_offset);
+ req->fact_cal.size = cpu_to_le32(dev->cached_cal.size);
+ req->fact_cal.bound = cpu_to_le32(pa_offset + dev->cached_cal.size - 1);
+
+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(AXIDMA),
+ req, sizeof(*req), true);
+
+ kfree(req);
+
+ if (ret)
+ dev_err(dev->mt76.dev,
+ "failed to send AXI DMA info: %d\n", ret);
+
+ return ret;
+}
+
+static bool mt7925_cal_cache_read_slot(struct mt792x_dev *dev, u32 region_off,
+ u32 stride, u32 idx,
+ u32 *cal_param, u32 *total_buf_num)
+{
+ const struct mt7925_fact_cal_buf_info *bi;
+ u32 off = region_off + stride * idx;
+
+ if (!dev->cached_cal.va || off + sizeof(*bi) > dev->cached_cal.size)
+ return false;
+
+ bi = (const struct mt7925_fact_cal_buf_info *)
+ ((const u8 *)dev->cached_cal.va + off);
+ if (cal_param)
+ *cal_param = le32_to_cpu(bi->cal_param);
+ if (total_buf_num)
+ *total_buf_num = le32_to_cpu(bi->total_buf_num);
+ return true;
+}
+
+static void mt7925_fact_cal_build_mapping_tbl(struct mt792x_dev *dev,
+ struct mt7925_fact_cal_mapping_tbl *tbl)
+{
+ dma_addr_t common_pa, group_pa, channel_pa, mapping_pa;
+ u32 hdr = sizeof(struct mt7925_fact_cal_buf_info);
+ dma_addr_t base = dev->cached_cal.dma_addr;
+ struct mt7925_cal_cache_layout l;
+
+ mt7925_cal_cache_calc_layout(&l);
+
+ common_pa = base + l.common_off;
+ group_pa = base + l.group_off;
+ channel_pa = base + l.channel_off;
+ mapping_pa = base + l.mapping_off;
+
+ memset(tbl, 0, sizeof(*tbl));
+
+ tbl->common.phy_addr_h = cpu_to_le32(upper_32_bits(common_pa));
+ tbl->common.phy_addr_l = cpu_to_le32(lower_32_bits(common_pa));
+ tbl->common.offset = cpu_to_le32(l.common_stride);
+
+ tbl->group.phy_addr_h = cpu_to_le32(upper_32_bits(group_pa));
+ tbl->group.phy_addr_l = cpu_to_le32(lower_32_bits(group_pa));
+ tbl->group.offset = cpu_to_le32(l.group_stride);
+
+ tbl->channel.phy_addr_h = cpu_to_le32(upper_32_bits(channel_pa));
+ tbl->channel.phy_addr_l = cpu_to_le32(lower_32_bits(channel_pa));
+ tbl->channel.offset = cpu_to_le32(l.channel_stride);
+
+ if (dev->cached_cal.reused) {
+ u32 i, cal_param, total_buf_num;
+
+ for (i = 0; i < MT7925_FACT_CAL_COMMON_BAND_NUM; i++)
+ if (mt7925_cal_cache_read_slot(dev, l.common_off,
+ l.common_stride, i,
+ &cal_param, NULL))
+ tbl->common.band[i] = cal_param & 0xff;
+
+ for (i = 0; i < MT7925_FACT_CAL_GROUP_NUM; i++)
+ if (mt7925_cal_cache_read_slot(dev, l.group_off,
+ l.group_stride, i,
+ &cal_param, NULL))
+ tbl->group.group[i] = cal_param & 0xff;
+
+ for (i = 0; i < MT7925_FACT_CAL_CH_NUM_ALL; i++)
+ if (mt7925_cal_cache_read_slot(dev, l.channel_off,
+ l.channel_stride, i,
+ &cal_param,
+ &total_buf_num)) {
+ tbl->channel.cal_param[i] =
+ cpu_to_le32(cal_param);
+ tbl->channel.total_buf_num[i] =
+ total_buf_num & 0xff;
+ }
+ }
+
+ tbl->buf_info_size = cpu_to_le32(hdr);
+ tbl->phy_addr_h = cpu_to_le32(upper_32_bits(mapping_pa));
+ tbl->phy_addr_l = cpu_to_le32(lower_32_bits(mapping_pa));
+}
+
+static int mt7925_mcu_fact_cal_rapid_set(struct mt792x_dev *dev, u8 cal_type,
+ u32 seq_num, bool done,
+ const void *data, u32 data_len)
+{
+ struct mt7925_fact_cal_req *req;
+ int ret;
+
+ if (data_len > MT7925_FACT_CAL_DATA_BUF_LEN)
+ return -EINVAL;
+
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ req->set.tag = cpu_to_le16(MT7925_FACT_CAL_TAG_RAPID_SET);
+ req->set.len = cpu_to_le16(sizeof(req->set));
+ req->set.seq_num = cpu_to_le32(seq_num);
+ req->set.buf_data_len = cpu_to_le32(data_len);
+ req->set.cal_type = cal_type;
+ req->set.done = done;
+ if (data && data_len)
+ memcpy(req->set.buf_data, data, data_len);
+
+ /* Wait for the ACK on the final chunk only: the FW applies the whole
+ * table there (DMAs the cached common / power-on group cal data in and
+ * programs the PHY), so its ACK is the completion point. Waiting also
+ * drains the ACKs the earlier chunks left in the MCU response queue,
+ * since UNI commands always request one.
+ */
+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(FACT_CAL),
+ req, sizeof(*req), done);
+ kfree(req);
+
+ return ret;
+}
+
+int mt7925_mcu_send_fact_cal_mapping_tbl(struct mt792x_dev *dev)
+{
+ struct mt7925_fact_cal_mapping_tbl *tbl;
+ __le32 cfg[MT7925_FACT_CAL_BUF_CFG_LEN / sizeof(__le32)] = {0};
+ u32 seq = 0, off = 0, left;
+ int ret;
+
+ if (!dev->cached_cal.va)
+ return -EINVAL;
+
+ tbl = kzalloc(sizeof(*tbl), GFP_KERNEL);
+ if (!tbl)
+ return -ENOMEM;
+
+ mt7925_fact_cal_build_mapping_tbl(dev, tbl);
+
+ cfg[1] = cpu_to_le32(sizeof(*tbl));
+ cfg[2] = cpu_to_le32(MT7925_FACT_CAL_DATA_BUF_NUM_MAX);
+ ret = mt7925_mcu_fact_cal_rapid_set(dev, MT7925_FACT_CAL_TYPE_MAPPING_TBL,
+ seq, false, cfg, sizeof(cfg));
+ if (ret) {
+ dev_err(dev->mt76.dev,
+ "fact-cal mapping tbl header send failed (seq=%u): %d\n",
+ seq, ret);
+ goto out;
+ }
+
+ left = sizeof(*tbl);
+ while (left) {
+ u32 chunk = min_t(u32, left, MT7925_FACT_CAL_DATA_BUF_LEN);
+
+ ret = mt7925_mcu_fact_cal_rapid_set(dev,
+ MT7925_FACT_CAL_TYPE_MAPPING_TBL,
+ ++seq, false,
+ (u8 *)tbl + off, chunk);
+ if (ret) {
+ dev_err(dev->mt76.dev,
+ "fact-cal mapping tbl data send failed (seq=%u, off=%u, chunk=%u): %d\n",
+ seq, off, chunk, ret);
+ goto out;
+ }
+
+ off += chunk;
+ left -= chunk;
+ }
+
+ ret = mt7925_mcu_fact_cal_rapid_set(dev, MT7925_FACT_CAL_TYPE_MAPPING_TBL,
+ ++seq, true, NULL, 0);
+ if (ret) {
+ dev_err(dev->mt76.dev,
+ "fact-cal mapping tbl done send failed (seq=%u): %d\n",
+ seq, ret);
+ goto out;
+ }
+out:
+ kfree(tbl);
+
+ return ret;
+}
+
+int mt7925_mcu_fact_cal_set_bypass(struct mt792x_dev *dev, bool enable)
+{
+ struct {
+ u8 _rsv[4];
+
+ struct {
+ __le16 tag;
+ __le16 len;
+ __le32 data;
+ } __packed update_flag;
+ } req = {
+ .update_flag = {
+ .tag = cpu_to_le16(MT7925_FACT_CAL_TAG_UPDATE_FLAG),
+ .len = cpu_to_le16(sizeof(req.update_flag)),
+ .data = cpu_to_le32(enable ? 1 : 0),
+ },
+ };
+
+ return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(FACT_CAL),
+ &req, sizeof(req), false);
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h b/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h
new file mode 100644
index 0000000000000..6572513b76466
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/* Copyright (C) 2026 MediaTek Inc. */
+
+#ifndef __CACHED_CAL_H
+#define __CACHED_CAL_H
+
+enum mt7925_axidma_info_tag {
+ MT7925_AXIDMA_TAG_REMAP = 0,
+ MT7925_AXIDMA_TAG_FACT_CAL = 1,
+ MT7925_AXIDMA_TAG_NUM
+};
+
+enum mt7925_fact_cal_tag {
+ MT7925_FACT_CAL_TAG_TRIGGER = 2,
+ MT7925_FACT_CAL_TAG_UPDATE_FLAG = 3,
+ MT7925_FACT_CAL_TAG_RAPID_GET = 4,
+ MT7925_FACT_CAL_TAG_RAPID_SET = 5,
+};
+
+enum mt7925_fact_cal_type {
+ MT7925_FACT_CAL_TYPE_COMMON = 0,
+ MT7925_FACT_CAL_TYPE_GROUP = 1,
+ MT7925_FACT_CAL_TYPE_CHANNEL = 2,
+ MT7925_FACT_CAL_TYPE_MAPPING_TBL = 4,
+};
+
+#define MT7925_FACT_CAL_DATA_BUF_LEN 1400
+#define MT7925_FACT_CAL_BUF_CFG_LEN 16
+#define MT7925_FACT_CAL_DATA_BUF_NUM_MAX 4
+#define MT7925_FACT_CAL_BUF_CFG_U32_LEN 4
+#define MT7925_FACT_CAL_DATA_MAX_BUF_LEN \
+ (MT7925_FACT_CAL_DATA_BUF_NUM_MAX * MT7925_FACT_CAL_BUF_CFG_U32_LEN)
+
+#define MT7925_FACT_CAL_COMMON_BAND_NUM 2
+#define MT7925_FACT_CAL_GROUP_NUM 35
+#define MT7925_FACT_CAL_CH_NUM_2G 14
+#define MT7925_FACT_CAL_CH_NUM_5G 68
+#define MT7925_FACT_CAL_CH_NUM_6G 109
+#define MT7925_FACT_CAL_CH_NUM_ALL \
+ (MT7925_FACT_CAL_CH_NUM_2G + MT7925_FACT_CAL_CH_NUM_5G + \
+ MT7925_FACT_CAL_CH_NUM_6G)
+
+#define MT7925_FACT_CAL_LEN_COM 600
+#define MT7925_FACT_CAL_LEN_GRP 4500
+#define MT7925_FACT_CAL_LEN_CH 2800
+
+struct mt7925_fact_cal_buf_info {
+ __le32 cal_type;
+ __le32 cal_param;
+ __le32 buf_seq_num;
+ __le32 total_buf_num;
+ __le32 buf_data_len;
+ u8 valid;
+ u8 done;
+ u8 rsv[2];
+ __le32 buf_cfg_info[MT7925_FACT_CAL_DATA_MAX_BUF_LEN];
+} __packed;
+
+static_assert(sizeof(struct mt7925_fact_cal_buf_info) == 88,
+ "buf_info must match the MT7928 FW (88 bytes) or it rejects the mapping table");
+
+struct mt7925_fact_cal_common_map {
+ __le32 phy_addr_h;
+ __le32 phy_addr_l;
+ __le32 offset;
+ u8 band[MT7925_FACT_CAL_COMMON_BAND_NUM];
+ u8 rsv[2];
+} __packed;
+
+struct mt7925_fact_cal_group_map {
+ __le32 phy_addr_h;
+ __le32 phy_addr_l;
+ __le32 offset;
+ u8 group[MT7925_FACT_CAL_GROUP_NUM];
+ u8 rsv;
+} __packed;
+
+struct mt7925_fact_cal_channel_map {
+ __le32 phy_addr_h;
+ __le32 phy_addr_l;
+ __le32 offset;
+ __le32 cal_param[MT7925_FACT_CAL_CH_NUM_ALL];
+ u8 total_buf_num[MT7925_FACT_CAL_CH_NUM_ALL];
+ u8 rsv;
+} __packed;
+
+struct mt7925_fact_cal_mapping_tbl {
+ struct mt7925_fact_cal_common_map common;
+ struct mt7925_fact_cal_group_map group;
+ struct mt7925_fact_cal_channel_map channel;
+ __le32 buf_info_size;
+ __le32 phy_addr_h;
+ __le32 phy_addr_l;
+} __packed;
+
+static_assert(sizeof(struct mt7925_fact_cal_mapping_tbl) == 1044,
+ "mapping table must match the MT7928 FW (1044 bytes) or the FW parse corrupts");
+
+struct mt7925_cal_cache_layout {
+ u32 common_off, group_off, channel_off, mapping_off;
+ u32 common_stride, group_stride, channel_stride;
+ u32 total;
+};
+
+struct mt7925_axidma_info_req {
+ u8 _rsv[4];
+
+ struct {
+ __le16 tag;
+ __le16 len;
+ __le32 remap_addr;
+ __le32 reserved;
+ } __packed remap;
+
+ struct {
+ __le16 tag;
+ __le16 len;
+ __le32 host_addr_offset;
+ __le32 size;
+ __le32 bound;
+ __le32 reserved;
+ } __packed fact_cal;
+} __packed;
+
+struct mt7925_fact_cal_req {
+ u8 _rsv[4];
+
+ struct {
+ __le16 tag;
+ __le16 len;
+ __le32 data;
+ __le32 seq_num;
+ __le32 buf_data_len;
+ u8 cal_type;
+ u8 done;
+ u8 rsv[2];
+ u8 buf_data[MT7925_FACT_CAL_DATA_BUF_LEN];
+ } __packed set;
+} __packed;
+
+int mt7925_axidma_alloc(struct mt792x_dev *dev);
+
+void mt7925_axidma_free(struct mt792x_dev *dev);
+
+int mt7925_mcu_send_axidma_info(struct mt792x_dev *dev);
+
+int mt7925_mcu_send_fact_cal_mapping_tbl(struct mt792x_dev *dev);
+
+int mt7925_mcu_fact_cal_set_bypass(struct mt792x_dev *dev, bool enable);
+
+#endif /* __CACHED_CAL_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
index 321e732347f2f..4d79c1e66e66b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
@@ -353,6 +353,7 @@ int mt7925_mcu_parse_response(struct mt76_dev *mdev, int cmd,
int mt7925e_mac_reset(struct mt792x_dev *dev);
int mt7925e_mcu_init(struct mt792x_dev *dev);
+void mt7925e_axidma_cal_cache_init(struct mt792x_dev *dev);
void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data);
void mt7928_mac_add_txs_msg(struct mt792x_dev *dev, void *evt);
void mt7925_set_runtime_pm(struct mt792x_dev *dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index 02ef09dd797da..724abd2be57c5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -9,6 +9,7 @@
#include "mac.h"
#include "mcu.h"
#include "regd.h"
+#include "cached_cal.h"
#include "../dma.h"
static const struct pci_device_id mt7925_pci_device_table[] = {
@@ -38,6 +39,62 @@ static int mt7925e_init_reset(struct mt792x_dev *dev)
return mt792x_wpdma_reset(dev, true);
}
+/* Set up the factory-calibration cache in host memory. PCIe only: the FW
+ * reaches the buffer through AXI DMA, so it has no meaning on other buses.
+ * Every failure just leaves the cache off, which is not fatal.
+ */
+void mt7925e_axidma_cal_cache_init(struct mt792x_dev *dev)
+{
+ if (!(dev->phy.chip_cap & MT792x_CHIP_CAP_AXIDMA_EN))
+ return;
+
+ if (dev->cached_cal.va) {
+ /* Carried-over buffer still holds FW-written cal data. */
+ dev->cached_cal.reused = true;
+ } else {
+ if (mt7925_axidma_alloc(dev)) {
+ dev_warn(dev->mt76.dev,
+ "AXI DMA cal cache disabled: buffer alloc failed\n");
+ return;
+ }
+ /* Freshly allocated buffer is zeroed: no cal data yet. */
+ dev->cached_cal.reused = false;
+ }
+
+ if (mt7925_mcu_send_axidma_info(dev)) {
+ dev_warn(dev->mt76.dev,
+ "AXI DMA cal cache disabled: info cmd to FW failed\n");
+ return;
+ }
+
+ /* Enable the bypass-cal flow so the FW reuses cached cal data
+ * (common / power-on group) instead of running a full calibration;
+ * must be set before the mapping table is sent.
+ */
+ if (mt7925_mcu_fact_cal_set_bypass(dev, true)) {
+ dev_warn(dev->mt76.dev,
+ "AXI DMA cal cache disabled: bypass flag set failed\n");
+ return;
+ }
+
+ if (mt7925_mcu_send_fact_cal_mapping_tbl(dev)) {
+ dev_warn(dev->mt76.dev,
+ "AXI DMA cal cache disabled: mapping tbl send failed\n");
+ return;
+ }
+
+ if (mt7925_mcu_fact_cal_set_bypass(dev, false)) {
+ dev_warn(dev->mt76.dev,
+ "AXI DMA cal cache disabled: bypass flag set failed\n");
+ return;
+ }
+
+ dev_info(dev->mt76.dev,
+ "AXI DMA cal cache enabled (DMA=%pad, size=%u, reused=%d)\n",
+ &dev->cached_cal.dma_addr, dev->cached_cal.size,
+ dev->cached_cal.reused);
+}
+
static void mt7925e_unregister_device(struct mt792x_dev *dev)
{
int i;
@@ -58,6 +115,9 @@ static void mt7925e_unregister_device(struct mt792x_dev *dev)
mt7925_tx_token_put(dev);
__mt792x_mcu_drv_pmctrl(dev);
+
+ mt7925_axidma_free(dev);
+
mt792x_dma_cleanup(dev);
mt792x_wfsys_reset(dev);
skb_queue_purge(&dev->mt76.mcu.res_q);
@@ -587,7 +647,7 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
is_mt7928_hw = (pdev->device == 0x7928 || pdev->device == 0x7935);
if (is_mt7928_hw)
- ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(34));
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34));
else
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
index 8477d21abc660..c90f129b3a34e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
@@ -135,6 +135,8 @@ int mt7925e_mac_reset(struct mt792x_dev *dev)
if (err)
goto out;
+ mt7925e_axidma_cal_cache_init(dev);
+
err = mt7925_mcu_set_eeprom(dev);
if (err)
goto out;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c
index 72707eddc3db6..258f3753db1fb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c
@@ -46,6 +46,8 @@ int mt7925e_mcu_init(struct mt792x_dev *dev)
mt76_rmw_field(dev, dev->pcie_reg->pm, MT_PCIE_MAC_PM_L0S_DIS, 1);
err = mt7925_run_firmware(dev);
+ if (!err)
+ mt7925e_axidma_cal_cache_init(dev);
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false);
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h
index 9efc251cb745f..740d517eb38bb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
@@ -33,6 +33,7 @@
#define MT792x_CHIP_CAP_REGD_EN BIT(5)
#define MT792x_CHIP_CAP_MLO_EN BIT(8)
#define MT792x_CHIP_CAP_MLO_EML_EN BIT(9)
+#define MT792x_CHIP_CAP_AXIDMA_EN BIT(16)
/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
#define MT792x_BASIC_RATES_TBL 14
@@ -342,6 +343,13 @@ struct mt792x_dev {
struct ieee80211_vif *nan_vif;
const struct ieee80211_iface_combination *iface_combinations;
int n_iface_combinations;
+
+ struct {
+ void *va;
+ dma_addr_t dma_addr;
+ u32 size;
+ bool reused;
+ } cached_cal;
};
static inline struct mt792x_bss_conf *
|
| 3/2 | 2026/08/10 06:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11476 output: 25 thoughts: 537 Thoughts: **Analyzing the Fuzzing Potential of a MediaTek MT7925 Driver Patch** Okay, so I'm looking at this patch for the `mt7925` driver, which is part of the MediaTek MT76 wireless driver family. It introduces "AXI DMA cal cache" – factory calibration cache – specifically for PCIe devices. The patch includes new files (`cached_cal.c`, `cached_cal.h`) and modifies several existing ones (`pci.c`, `pci_mac.c`, `pci_mcu.c`). My immediate concern, as always, is whether this is fuzzable. The prompt gives some exclusion criteria. The prompt specifically says to return `WorthFuzzing=false` if the changes involve code paths unreachable in virtualized environments or vendor-specific drivers needing physical hardware. Right, the question is, does this fall into that category? `mt7925` is a MediaTek Wi-Fi driver. While Wi-Fi drivers *generally* require physical hardware, sometimes they *can* be fuzzed using `mac80211_hwsim`, which is a software simulator. However, this is for a *PCIe* device, and `mt7925` itself requires a physical MT7925 device (PCIe or USB). So, `mac80211_hwsim` isn't the solution here. However, I remember Syzkaller. It does have PCI emulation capabilities. It has vhci for USB, but does it have something similar for PCI? Actually, yes, Syzkaller does have a PCI fuzzer that can emulate PCI devices. The question is: does standard QEMU emulate the MT7925? No. But, Syzkaller fuzzes PCI devices by injecting PCI config space and MMIO reads/writes. Does Syzkaller fuzz `mt7925`? Let's check! I need to see if there are Syzkaller descriptions for it. And wait, going back to the prompt, it lists specific exclusions: vendor-specific PCIe switch, SmartNIC, or GPU drivers. Wi-Fi drivers aren't *explicitly* in that list, but they *are* PCIe devices. I need to dig deeper into whether Syzkaller has sufficient PCI fuzzing support for the `mt76` family. That will be the deciding factor here. I must research the Syzkaller coverage for this specific driver. |
| 4/2 | 2026/08/10 06:12 | tool | grepper |
0mArgs:{
"Expression": "mt7925",
"PathPrefix": ""
}Results: {
"Output": "\nFull output is too long, showing 500 out of 4299 lines.\nUse more precise expression if possible.\n\ndrivers/bluetooth/btmtk.h-9-#define FIRMWARE_MT7961\t\t\"mediatek/BT_RAM_CODE_MT7961_1_2_hdr.bin\"\ndrivers/bluetooth/btmtk.h:10:#define FIRMWARE_MT7925\t\t\"mediatek/mt7925/BT_RAM_CODE_MT7925_1_1_hdr.bin\"\ndrivers/bluetooth/btmtk.h-11-#define FIRMWARE_MT7927\t\t\"mediatek/mt7927/BT_RAM_CODE_MT6639_2_1_hdr.bin\"\n--\ndrivers/net/wireless/mediatek/mt76/Kconfig=50=source \"drivers/net/wireless/mediatek/mt76/mt7996/Kconfig\"\ndrivers/net/wireless/mediatek/mt76/Kconfig:51:source \"drivers/net/wireless/mediatek/mt76/mt7925/Kconfig\"\n--\ndrivers/net/wireless/mediatek/mt76/Makefile=51=obj-$(CONFIG_MT7996E) += mt7996/\ndrivers/net/wireless/mediatek/mt76/Makefile:52:obj-$(CONFIG_MT7925_COMMON) += mt7925/\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac.h=180=static inline bool is_connac3(struct mt76_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac.h-184-\ndrivers/net/wireless/mediatek/mt76/mt76_connac.h:185:static inline bool is_mt7925(struct mt76_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt76_connac.h-186-{\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c=54=int mt76_connac_mcu_init_download(struct mt76_dev *dev, u32 addr, u32 len,\n--\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c-69-\t (is_connac2(dev) \u0026\u0026 addr == 0x900000) ||\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c:70:\t ((is_mt7925(dev) || is_mt7927(dev)) \u0026\u0026 (addr == 0x900000 || addr == 0xe0002800)) ||\ndrivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c-71-\t (is_mt7928(dev) \u0026\u0026 (addr == 0x900000 || addr == 0xe0002000)) ||\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/Makefile-2-\ndrivers/net/wireless/mediatek/mt76/mt7925/Makefile:3:obj-$(CONFIG_MT7925_COMMON) += mt7925-common.o\ndrivers/net/wireless/mediatek/mt76/mt7925/Makefile:4:obj-$(CONFIG_MT7925E) += mt7925e.o\ndrivers/net/wireless/mediatek/mt76/mt7925/Makefile:5:obj-$(CONFIG_MT7925U) += mt7925u.o\ndrivers/net/wireless/mediatek/mt76/mt7925/Makefile-6-\ndrivers/net/wireless/mediatek/mt76/mt7925/Makefile:7:mt7925-common-y := mac.o mcu.o regd.o main.o init.o debugfs.o nan.o\ndrivers/net/wireless/mediatek/mt76/mt7925/Makefile:8:mt7925-common-$(CONFIG_NL80211_TESTMODE) += testmode.o\ndrivers/net/wireless/mediatek/mt76/mt7925/Makefile:9:mt7925e-y := pci.o pci_mac.o pci_mcu.o cached_cal.o\ndrivers/net/wireless/mediatek/mt76/mt7925/Makefile:10:mt7925u-y := usb.o\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-7-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:8:static void mt7925_cal_cache_calc_layout(struct mt7925_cal_cache_layout *l)\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-9-{\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:10:\tu32 hdr = sizeof(struct mt7925_fact_cal_buf_info);\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-11-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-23-\tl-\u003etotal = l-\u003emapping_off +\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:24:\t\tsizeof(struct mt7925_fact_cal_mapping_tbl);\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-25-}\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-26-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:27:static u32 mt7925_cal_cache_region_size(void)\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-28-{\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:29:\tstruct mt7925_cal_cache_layout l;\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-30-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:31:\tmt7925_cal_cache_calc_layout(\u0026l);\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-32-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-35-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:36:int mt7925_axidma_alloc(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-37-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-44-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:45:\ttotal_size = mt7925_cal_cache_region_size();\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-46-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-58-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:59:void mt7925_axidma_free(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-60-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-69-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:70:int mt7925_mcu_send_axidma_info(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-71-{\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:72:\tstruct mt7925_axidma_info_req *req;\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-73-\tu32 remap_base, pa_offset;\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-107-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:108:static bool mt7925_cal_cache_read_slot(struct mt792x_dev *dev, u32 region_off,\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-109-\t\t\t\t u32 stride, u32 idx,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-111-{\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:112:\tconst struct mt7925_fact_cal_buf_info *bi;\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-113-\tu32 off = region_off + stride * idx;\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-117-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:118:\tbi = (const struct mt7925_fact_cal_buf_info *)\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-119-\t\t((const u8 *)dev-\u003ecached_cal.va + off);\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-126-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:127:static void mt7925_fact_cal_build_mapping_tbl(struct mt792x_dev *dev,\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:128:\t\t\t\t\t struct mt7925_fact_cal_mapping_tbl *tbl)\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-129-{\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-130-\tdma_addr_t common_pa, group_pa, channel_pa, mapping_pa;\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:131:\tu32 hdr = sizeof(struct mt7925_fact_cal_buf_info);\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-132-\tdma_addr_t base = dev-\u003ecached_cal.dma_addr;\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:133:\tstruct mt7925_cal_cache_layout l;\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-134-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:135:\tmt7925_cal_cache_calc_layout(\u0026l);\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-136-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-159-\t\tfor (i = 0; i \u003c MT7925_FACT_CAL_COMMON_BAND_NUM; i++)\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:160:\t\t\tif (mt7925_cal_cache_read_slot(dev, l.common_off,\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-161-\t\t\t\t\t\t l.common_stride, i,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-165-\t\tfor (i = 0; i \u003c MT7925_FACT_CAL_GROUP_NUM; i++)\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:166:\t\t\tif (mt7925_cal_cache_read_slot(dev, l.group_off,\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-167-\t\t\t\t\t\t l.group_stride, i,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-171-\t\tfor (i = 0; i \u003c MT7925_FACT_CAL_CH_NUM_ALL; i++)\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:172:\t\t\tif (mt7925_cal_cache_read_slot(dev, l.channel_off,\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-173-\t\t\t\t\t\t l.channel_stride, i,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-187-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:188:static int mt7925_mcu_fact_cal_rapid_set(struct mt792x_dev *dev, u8 cal_type,\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-189-\t\t\t\t\t u32 seq_num, bool done,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-191-{\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:192:\tstruct mt7925_fact_cal_req *req;\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-193-\tint ret;\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-223-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:224:int mt7925_mcu_send_fact_cal_mapping_tbl(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-225-{\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:226:\tstruct mt7925_fact_cal_mapping_tbl *tbl;\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-227-\t__le32 cfg[MT7925_FACT_CAL_BUF_CFG_LEN / sizeof(__le32)] = {0};\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-237-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:238:\tmt7925_fact_cal_build_mapping_tbl(dev, tbl);\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-239-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-241-\tcfg[2] = cpu_to_le32(MT7925_FACT_CAL_DATA_BUF_NUM_MAX);\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:242:\tret = mt7925_mcu_fact_cal_rapid_set(dev, MT7925_FACT_CAL_TYPE_MAPPING_TBL,\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-243-\t\t\t\t\t seq, false, cfg, sizeof(cfg));\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-254-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:255:\t\tret = mt7925_mcu_fact_cal_rapid_set(dev,\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-256-\t\t\t\t\t\t MT7925_FACT_CAL_TYPE_MAPPING_TBL,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-269-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:270:\tret = mt7925_mcu_fact_cal_rapid_set(dev, MT7925_FACT_CAL_TYPE_MAPPING_TBL,\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-271-\t\t\t\t\t ++seq, true, NULL, 0);\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-283-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c:284:int mt7925_mcu_fact_cal_set_bypass(struct mt792x_dev *dev, bool enable)\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c-285-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-6-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:7:enum mt7925_axidma_info_tag {\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-8-\tMT7925_AXIDMA_TAG_REMAP = 0,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-12-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:13:enum mt7925_fact_cal_tag {\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-14-\tMT7925_FACT_CAL_TAG_TRIGGER\t= 2,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-19-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:20:enum mt7925_fact_cal_type {\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-21-\tMT7925_FACT_CAL_TYPE_COMMON\t\t= 0,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-46-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:47:struct mt7925_fact_cal_buf_info {\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-48-\t__le32 cal_type;\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-58-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:59:static_assert(sizeof(struct mt7925_fact_cal_buf_info) == 88,\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-60-\t \"buf_info must match the MT7928 FW (88 bytes) or it rejects the mapping table\");\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-61-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:62:struct mt7925_fact_cal_common_map {\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-63-\t__le32 phy_addr_h;\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-69-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:70:struct mt7925_fact_cal_group_map {\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-71-\t__le32 phy_addr_h;\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-77-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:78:struct mt7925_fact_cal_channel_map {\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-79-\t__le32 phy_addr_h;\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-86-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:87:struct mt7925_fact_cal_mapping_tbl {\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:88:\tstruct mt7925_fact_cal_common_map common;\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:89:\tstruct mt7925_fact_cal_group_map group;\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:90:\tstruct mt7925_fact_cal_channel_map channel;\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-91-\t__le32 buf_info_size;\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-95-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:96:static_assert(sizeof(struct mt7925_fact_cal_mapping_tbl) == 1044,\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-97-\t \"mapping table must match the MT7928 FW (1044 bytes) or the FW parse corrupts\");\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-98-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:99:struct mt7925_cal_cache_layout {\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-100-\tu32 common_off, group_off, channel_off, mapping_off;\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-104-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:105:struct mt7925_axidma_info_req {\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-106-\tu8 _rsv[4];\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-124-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:125:struct mt7925_fact_cal_req {\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-126-\tu8 _rsv[4];\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-140-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:141:int mt7925_axidma_alloc(struct mt792x_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-142-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:143:void mt7925_axidma_free(struct mt792x_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-144-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:145:int mt7925_mcu_send_axidma_info(struct mt792x_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-146-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:147:int mt7925_mcu_send_fact_cal_mapping_tbl(struct mt792x_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-148-\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h:149:int mt7925_mcu_fact_cal_set_bypass(struct mt792x_dev *dev, bool enable);\ndrivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h-150-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-3-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:4:#include \"mt7925.h\"\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-5-#include \"mcu.h\"\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c=7=static int\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:8:mt7925_reg_set(void *data, u64 val)\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-9-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-13-\tmt792x_mutex_acquire(dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:14:\tmt7925_mcu_regval(dev, dev-\u003emt76.debugfs_reg, \u0026regval, true);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-15-\tmt792x_mutex_release(dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c=20=static int\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:21:mt7925_reg_get(void *data, u64 *val)\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-22-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-27-\tmt792x_mutex_acquire(dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:28:\tret = mt7925_mcu_regval(dev, dev-\u003emt76.debugfs_reg, \u0026regval, false);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-29-\tmt792x_mutex_release(dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-35-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:36:DEFINE_DEBUGFS_ATTRIBUTE(fops_regval, mt7925_reg_get, mt7925_reg_set,\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-37-\t\t\t \"0x%08llx\\n\");\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c=38=static int\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:39:mt7925_fw_debug_set(void *data, u64 val)\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-40-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-45-\tdev-\u003efw_debug = (u8)val;\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:46:\tmt7925_mcu_fw_log_2_host(dev, dev-\u003efw_debug);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-47-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c=53=static int\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:54:mt7925_fw_debug_get(void *data, u64 *val)\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-55-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-62-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:63:DEFINE_DEBUGFS_ATTRIBUTE(fops_fw_debug, mt7925_fw_debug_get,\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:64:\t\t\t mt7925_fw_debug_set, \"%lld\\n\");\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-65-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c=68=static void\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:69:mt7925_seq_puts_array(struct seq_file *file, const char *str,\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-70-\t\t s8 val[][2], int len, u8 band_idx)\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-82-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:83:#define mt7925_print_txpwr_entry(prefix, rate, idx)\t\\\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-84-({\t\t\t\t\t\t\t\\\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:85:\tmt7925_seq_puts_array(s, #prefix \" (tmac)\",\t\\\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-86-\t\t\t txpwr-\u003erate,\t\t\\\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c=91=static inline void\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:92:mt7925_eht_txpwr(struct seq_file *s, struct mt7925_txpwr *txpwr, u8 band_idx)\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-93-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-97-\t\t \"mcs12\", \"mcs13\", \"mcs14\", \"mcs15\");\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:98:\tmt7925_print_txpwr_entry(EHT26, eht26, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:99:\tmt7925_print_txpwr_entry(EHT52, eht52, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:100:\tmt7925_print_txpwr_entry(EHT106, eht106, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:101:\tmt7925_print_txpwr_entry(EHT242, eht242, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:102:\tmt7925_print_txpwr_entry(EHT484, eht484, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-103-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:104:\tmt7925_print_txpwr_entry(EHT996, eht996, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:105:\tmt7925_print_txpwr_entry(EHT996x2, eht996x2, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:106:\tmt7925_print_txpwr_entry(EHT996x4, eht996x4, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:107:\tmt7925_print_txpwr_entry(EHT26_52, eht26_52, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:108:\tmt7925_print_txpwr_entry(EHT26_106, eht26_106, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:109:\tmt7925_print_txpwr_entry(EHT484_242, eht484_242, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:110:\tmt7925_print_txpwr_entry(EHT996_484, eht996_484, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:111:\tmt7925_print_txpwr_entry(EHT996_484_242, eht996_484_242, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:112:\tmt7925_print_txpwr_entry(EHT996x2_484, eht996x2_484, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:113:\tmt7925_print_txpwr_entry(EHT996x3, eht996x3, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:114:\tmt7925_print_txpwr_entry(EHT996x3_484, eht996x3_484, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-115-}\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c=117=static int\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:118:mt7925_txpwr(struct seq_file *s, void *data)\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-119-{\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-120-\tstruct mt792x_dev *dev = dev_get_drvdata(s-\u003eprivate);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:121:\tstruct mt7925_txpwr *txpwr = NULL;\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-122-\tu8 band_idx = dev-\u003emphy.band_idx;\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-130-\tmt792x_mutex_acquire(dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:131:\tret = mt7925_get_txpwr_info(dev, band_idx, txpwr);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-132-\tmt792x_mutex_release(dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-138-\t\t \" \", \"1m\", \"2m\", \"5m\", \"11m\");\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:139:\tmt7925_print_txpwr_entry(CCK, cck, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-140-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-143-\t\t \"48m\", \"54m\");\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:144:\tmt7925_print_txpwr_entry(OFDM, ofdm, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-145-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-148-\t\t \"mcs6\", \"mcs7\");\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:149:\tmt7925_print_txpwr_entry(HT20, ht20, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-150-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-153-\t\t \"mcs6\", \"mcs7\", \"mcs32\");\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:154:\tmt7925_print_txpwr_entry(HT40, ht40, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-155-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-158-\t\t \"mcs6\", \"mcs7\", \"mcs8\", \"mcs9\", \"mcs10\", \"mcs11\");\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:159:\tmt7925_print_txpwr_entry(VHT20, vht20, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:160:\tmt7925_print_txpwr_entry(VHT40, vht40, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-161-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:162:\tmt7925_print_txpwr_entry(VHT80, vht80, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:163:\tmt7925_print_txpwr_entry(VHT160, vht160, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-164-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:165:\tmt7925_print_txpwr_entry(HE26, he26, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:166:\tmt7925_print_txpwr_entry(HE52, he52, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:167:\tmt7925_print_txpwr_entry(HE106, he106, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:168:\tmt7925_print_txpwr_entry(HE242, he242, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:169:\tmt7925_print_txpwr_entry(HE484, he484, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-170-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:171:\tmt7925_print_txpwr_entry(HE996, he996, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:172:\tmt7925_print_txpwr_entry(HE996x2, he996x2, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-173-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:174:\tmt7925_eht_txpwr(s, txpwr, band_idx);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-175-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c=181=static int\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:182:mt7925_pm_set(void *data, u64 val)\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-183-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-205-\tpm-\u003eenable_user = val;\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:206:\tmt7925_set_runtime_pm(dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-207-\tmt76_connac_power_save_sched(\u0026dev-\u003emphy, pm);\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c=214=static int\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:215:mt7925_pm_get(void *data, u64 *val)\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-216-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-223-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:224:DEFINE_DEBUGFS_ATTRIBUTE(fops_pm, mt7925_pm_get, mt7925_pm_set, \"%lld\\n\");\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-225-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c=226=static int\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:227:mt7925_deep_sleep_set(void *data, u64 val)\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-228-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-242-\tpm-\u003eds_enable = enable \u0026\u0026 !monitor;\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:243:\tmt7925_mcu_set_deep_sleep(dev, pm-\u003eds_enable);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-244-out:\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c=250=static int\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:251:mt7925_deep_sleep_get(void *data, u64 *val)\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-252-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-259-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:260:DEFINE_DEBUGFS_ATTRIBUTE(fops_ds, mt7925_deep_sleep_get,\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:261:\t\t\t mt7925_deep_sleep_set, \"%lld\\n\");\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-262-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c=263=DEFINE_DEBUGFS_ATTRIBUTE(fops_pm_idle_timeout, mt792x_pm_idle_timeout_get,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-265-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:266:static int mt7925_chip_reset(void *data, u64 val)\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-267-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-278-\t\tmt792x_mutex_acquire(dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:279:\t\tret = mt7925_mcu_chip_config(dev, \"assert\");\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-280-\t\tmt792x_mutex_release(dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-286-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:287:DEFINE_DEBUGFS_ATTRIBUTE(fops_reset, NULL, mt7925_chip_reset, \"%lld\\n\");\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-288-\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:289:int mt7925_init_debugfs(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-290-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-304-\tdebugfs_create_devm_seqfile(dev-\u003emt76.dev, \"txpower_sku\", dir,\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c:305:\t\t\t\t mt7925_txpwr);\ndrivers/net/wireless/mediatek/mt76/mt7925/debugfs.c-306-\tdebugfs_create_file(\"tx_stats\", 0400, dir, dev, \u0026mt792x_tx_stats_fops);\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-8-#include \u003clinux/firmware.h\u003e\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:9:#include \"mt7925.h\"\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-10-#include \"regd.h\"\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-13-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:14:static ssize_t mt7925_thermal_temp_show(struct device *dev,\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-15-\t\t\t\t\tstruct device_attribute *attr,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-24-\t\tmt792x_mutex_acquire(mdev);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:25:\t\ttemperature = mt7925_mcu_get_temperature(phy);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-26-\t\tmt792x_mutex_release(mdev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-36-}\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:37:static SENSOR_DEVICE_ATTR_RO(temp1_input, mt7925_thermal_temp, 0);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-38-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:39:static struct attribute *mt7925_hwmon_attrs[] = {\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-40-\t\u0026sensor_dev_attr_temp1_input.dev_attr.attr,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-42-};\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:43:ATTRIBUTE_GROUPS(mt7925_hwmon);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-44-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:45:static int mt7925_thermal_init(struct mt792x_phy *phy)\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-46-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-53-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:54:\tname = devm_kasprintf(\u0026wiphy-\u003edev, GFP_KERNEL, \"mt7925_%s\",\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-55-\t\t\t wiphy_name(wiphy));\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-59-\thwmon = devm_hwmon_device_register_with_groups(\u0026wiphy-\u003edev, name, phy,\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:60:\t\t\t\t\t\t mt7925_hwmon_groups);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-61-\treturn PTR_ERR_OR_ZERO(hwmon);\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-63-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:64:static void mt7925_mac_init_basic_rates(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-65-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-73-\t\t FIELD_PREP(MT_TX_RATE_IDX, rate \u0026 GENMASK(7, 0));\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:74:\t\tmt7925_mac_set_fixed_rate_table(dev, idx, rate);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-75-\t}\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-77-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:78:int mt7925_mac_init(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-79-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-86-\tfor (i = 0; i \u003c MT792x_WTBL_SIZE; i++)\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:87:\t\tmt7925_mac_wtbl_update(dev, i,\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-88-\t\t\t\t MT_WTBL_UPDATE_ADM_COUNT_CLEAR);\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-91-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:92:\tmt7925_mac_init_basic_rates(dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-93-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-97-}\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:98:EXPORT_SYMBOL_GPL(mt7925_mac_init);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-99-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:100:static int __mt7925_init_hardware(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-101-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-111-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:112:\tret = mt7925_mcu_set_eeprom(dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-113-\tif (ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-115-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:116:\tret = mt7925_mac_init(dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-117-\tif (ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-120-\tif (is_mt7927(\u0026dev-\u003emt76)) {\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:121:\t\tret = mt7925_mcu_set_dbdc(\u0026dev-\u003emphy, true);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-122-\t\tif (ret) {\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-132-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:133:static int mt7925_init_hardware(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-134-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-144-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:145:\t\tret = __mt7925_init_hardware(dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-146-\t\tif (!ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-162-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:163:static int mt7925_init_nan_cap(struct mt76_dev *mdev)\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-164-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-189-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:190:static void mt7925_init_work(struct work_struct *work)\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-191-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-195-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:196:\tret = mt7925_init_hardware(dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-197-\tif (ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-200-\tmt76_set_stream_caps(\u0026dev-\u003emphy, true);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:201:\tmt7925_set_stream_he_eht_caps(\u0026dev-\u003ephy);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-202-\tmt792x_config_mac_addr_list(dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-203-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:204:\tret = mt7925_init_mlo_caps(\u0026dev-\u003ephy);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-205-\tif (ret) {\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-209-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:210:\tdev-\u003emt76.init_wiphy = mt7925_init_nan_cap;\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-211-\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-218-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:219:\tret = mt7925_init_debugfs(dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-220-\tif (ret) {\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-224-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:225:\tret = mt7925_thermal_init(\u0026dev-\u003ephy);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-226-\tif (ret) {\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-230-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:231:\tret = mt7925_mcu_set_thermal_protect(dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-232-\tif (ret) {\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-239-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:240:\tmt7925_mcu_set_deep_sleep(dev, dev-\u003epm.ds_enable);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-241-}\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-242-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:243:int mt7925_register_device(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-244-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-253-\tINIT_DELAYED_WORK(\u0026dev-\u003epm.ps_work, mt792x_pm_power_save_work);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:254:\tINIT_DELAYED_WORK(\u0026dev-\u003emlo_pm_work, mt7925_mlo_pm_work);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-255-\tINIT_WORK(\u0026dev-\u003epm.wake_work, mt792x_pm_wake_work);\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-261-\tINIT_DELAYED_WORK(\u0026dev-\u003emphy.mac_work, mt792x_mac_work);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:262:\tINIT_DELAYED_WORK(\u0026dev-\u003ephy.scan_work, mt7925_scan_work);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:263:\tINIT_DELAYED_WORK(\u0026dev-\u003ecoredump.work, mt7925_coredump_work);\n\n"
} |
| 5/2 | 2026/08/10 06:12 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 29723 output: 36 thoughts: 1106 Thoughts: **Analyzing the Fuzzing Potential of the MT7925 Wi-Fi Driver** Okay, so I'm looking at this `mt7925` driver, which is a MediaTek Wi-Fi driver, with both PCI and USB variants. The immediate question is, is standard QEMU emulating this specific device? No, it doesn't seem to be. Now, the next logical step: Does syzkaller even fuzz it? I need to check for syzkaller descriptions. But wait, this prompt gives a crucial limitation: I can't directly search for `syzlang` descriptions or expressions starting with `syz_`, because those are pseudo-syscalls specific to syzkaller, not present in the kernel. I don't have the `read-syz-spec` and `syz-grepper` tools, so I'm a bit stuck. Let me re-read the prompt. It points out that code in specific drivers – vendor-specific PCIe switch, SmartNIC, or GPU drivers – is problematic because they need physical PCIe hardware, which isn't emulated in standard QEMU. Syzkaller generally fuzzes Wi-Fi drivers via `mac80211_hwsim`, but the `mt7925` is a hardware driver. That makes me think: Syzkaller *does* have a PCI fuzzer, which injects PCI config space and MMIO reads/writes. But does that apply here? The prompt mentions those problematic drivers again... Is `mt7925` in that category? It *is* a Wi-Fi driver, which might be vendor-specific... Also, the prompt mentions other code paths that are impossible to reach in virtualized environments. Is `mt7925` reachable in QEMU? If there's no QEMU emulation for this, and it isn't a USB gadget or `mac80211_hwsim`, how can it be reached? Oh, right, syzkaller *does* have a USB fuzzer (using `vhci`) that can emulate ANY USB device using descriptors. However, this patch I'm looking at modifies `mt7925/pci.c`, `pci_mac.c`, `pci_mcu.c`, and adds `cached_cal.c`. The new feature focuses on PCIe specifically: "Set up the factory-calibration cache in host memory. PCIe only: the FW reaches the buffer through AXI DMA, so it has no meaning on other buses." The comments reinforce that this is PCIe-only. And the function `mt7925e_axidma_cal_cache_init` is called from `mt7925e_mac_reset` and `mt7925e_mcu_init`, which are in `pci_mac.c` and `pci_mcu.c`. This PCIe aspect is really critical. If there's no QEMU emulation, can it actually be tested? I'm remembering that syzkaller's PCI fuzzer can emulate PCI devices by matching the PCI vendor/device ID and injecting MMIO. But does it support `mt7925` specifically? Usually, it's more generic, and the driver's `probe` function is then called. The driver then tries to read and write MMIO, and syzkaller provides random data. But, that prompt keeps echoing in my mind: "Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers ... that require physical PCIe hardware cards not emulated in standard QEMU." Is this Wi-Fi driver considered "vendor-specific PCIe"? If so, that could mean it's *not* fuzzed in the usual way. But wait! The commit author is `syz-cluster <triage@syzkaller.com>`... but the commit message says "syz-cluster: applied patch under review". So, that just means syzkaller applied the patch to test it. Alright, let's focus on the PCIe aspect and see if it's reachable via PCI fuzzing. If the driver does DMA allocation and sends a message to the MCU (firmware), it relies on that firmware being loaded and running, or at least MMIO reads returning sensible values. Looking at `mt7925e_axidma_cal_cache_init`: ```c if (!(dev->phy.chip_cap & MT792x_CHIP_CAP_AXIDMA_EN)) return; ``` I need to understand where `chip_cap` is set. |
| 6/2 | 2026/08/10 06:13 | tool | grepper |
0mArgs:{
"Expression": "MT792x_CHIP_CAP_AXIDMA_EN",
"PathPrefix": ""
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7925/pci.c=46=void mt7925e_axidma_cal_cache_init(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-47-{\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c:48:\tif (!(dev-\u003ephy.chip_cap \u0026 MT792x_CHIP_CAP_AXIDMA_EN))\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-49-\t\treturn;\n--\ndrivers/net/wireless/mediatek/mt76/mt792x.h-35-#define MT792x_CHIP_CAP_MLO_EML_EN BIT(9)\ndrivers/net/wireless/mediatek/mt76/mt792x.h:36:#define MT792x_CHIP_CAP_AXIDMA_EN BIT(16)\ndrivers/net/wireless/mediatek/mt76/mt792x.h-37-\n"
} |
| 7/2 | 2026/08/10 06:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 32165 output: 25 thoughts: 47 Thoughts: Okay, let me delve into this. **Investigating the Missing `MT792x_CHIP_CAP_AXIDMA_EN` Definition** Hmm, this is curious. I was under the impression that the kernel source would have defined `MT792x_CHIP_CAP_AXIDMA_EN`, especially given its context. I need to be sure. My initial scan didn't reveal it, which raises a flag. I need to methodically verify that it's *not* defined anywhere, either directly in the relevant header files or indirectly through some macro magic. There's always the chance I missed something in my initial perusal. The next step is a more thorough search of the patch itself. Perhaps it's defined within this patch and I overlooked it, or maybe it's conditionally included somewhere. If it's *not* present here, I'll have to investigate how this symbol is used and if there is another way to determine the use of AXI DMA. |
| 8/2 | 2026/08/10 06:13 | tool | grepper |
0mArgs:{
"Expression": "AXIDMA_EN",
"PathPrefix": ""
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7925/pci.c=46=void mt7925e_axidma_cal_cache_init(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-47-{\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c:48:\tif (!(dev-\u003ephy.chip_cap \u0026 MT792x_CHIP_CAP_AXIDMA_EN))\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-49-\t\treturn;\n--\ndrivers/net/wireless/mediatek/mt76/mt792x.h-35-#define MT792x_CHIP_CAP_MLO_EML_EN BIT(9)\ndrivers/net/wireless/mediatek/mt76/mt792x.h:36:#define MT792x_CHIP_CAP_AXIDMA_EN BIT(16)\ndrivers/net/wireless/mediatek/mt76/mt792x.h-37-\n--\ndrivers/net/wireless/realtek/rtw89/mac.c=1652=static int dmac_func_en_ax(struct rtw89_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw89/mac.c-1663-\t\t\t B_AX_WD_RLS_EN | B_AX_MPDU_PROC_EN |\ndrivers/net/wireless/realtek/rtw89/mac.c:1664:\t\t\t B_AX_DMAC_CRPRT | B_AX_H_AXIDMA_EN);\ndrivers/net/wireless/realtek/rtw89/mac.c-1665-\telse\n--\ndrivers/net/wireless/realtek/rtw89/mac.c=4208=static void rtw89_mac_hci_func_en_ax(struct rtw89_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw89/mac.c-4214-\t\tval = B_AX_MAC_FUNC_EN | B_AX_DMAC_FUNC_EN | B_AX_DISPATCHER_EN |\ndrivers/net/wireless/realtek/rtw89/mac.c:4215:\t\t B_AX_PKT_BUF_EN | B_AX_H_AXIDMA_EN;\ndrivers/net/wireless/realtek/rtw89/mac.c-4216-\telse\n--\ndrivers/net/wireless/realtek/rtw89/mac.c=4222=static void rtw89_mac_dmac_func_pre_en_ax(struct rtw89_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw89/mac.c-4254-\trtw89_write32_clr(rtwdev, R_AX_HAXI_DMA_STOP2, B_AX_STOP_CH10 | B_AX_STOP_CH11);\ndrivers/net/wireless/realtek/rtw89/mac.c:4255:\trtw89_write32_set(rtwdev, R_AX_PLATFORM_ENABLE, B_AX_AXIDMA_EN);\ndrivers/net/wireless/realtek/rtw89/mac.c-4256-}\n--\ndrivers/net/wireless/realtek/rtw89/mac_be.c=768=static int dmac_func_en_be(struct rtw89_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw89/mac_be.c-782-\t\t\t B_BE_DISPATCHER_EN | B_BE_BBRPT_EN |\ndrivers/net/wireless/realtek/rtw89/mac_be.c:783:\t\t\t B_BE_MAC_SEC_EN | B_BE_H_AXIDMA_EN |\ndrivers/net/wireless/realtek/rtw89/mac_be.c-784-\t\t\t B_BE_DMAC_MLO_EN | B_BE_PLRLS_EN |\ndrivers/net/wireless/realtek/rtw89/mac_be.c:785:\t\t\t B_BE_P_AXIDMA_EN | B_BE_DLE_DATACPUIO_EN);\ndrivers/net/wireless/realtek/rtw89/mac_be.c-786-\n--\ndrivers/net/wireless/realtek/rtw89/reg.h-143-#define R_AX_PLATFORM_ENABLE 0x0088\ndrivers/net/wireless/realtek/rtw89/reg.h:144:#define B_AX_AXIDMA_EN BIT(3)\ndrivers/net/wireless/realtek/rtw89/reg.h-145-#define B_AX_APB_WRAP_EN BIT(2)\n--\ndrivers/net/wireless/realtek/rtw89/reg.h-569-#define B_AX_MAC_UN_EN BIT(15)\ndrivers/net/wireless/realtek/rtw89/reg.h:570:#define B_AX_H_AXIDMA_EN BIT(14)\ndrivers/net/wireless/realtek/rtw89/reg.h-571-\n--\ndrivers/net/wireless/realtek/rtw89/reg.h-4891-#define B_BE_DMACREG_GCKEN BIT(15)\ndrivers/net/wireless/realtek/rtw89/reg.h:4892:#define B_BE_H_AXIDMA_EN BIT(14)\ndrivers/net/wireless/realtek/rtw89/reg.h-4893-#define B_BE_DMAC_MLO_EN BIT(11)\ndrivers/net/wireless/realtek/rtw89/reg.h-4894-#define B_BE_PLRLS_EN BIT(10)\ndrivers/net/wireless/realtek/rtw89/reg.h:4895:#define B_BE_P_AXIDMA_EN BIT(9)\ndrivers/net/wireless/realtek/rtw89/reg.h-4896-#define B_BE_DLE_DATACPUIO_EN BIT(8)\n--\ndrivers/net/wireless/realtek/rtw89/rtw8852c.c=327=static int rtw8852c_pwr_on_func(struct rtw89_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw89/rtw8852c.c-438-\t\t\t B_AX_DISPATCHER_EN | B_AX_BBRPT_EN | B_AX_MAC_SEC_EN |\ndrivers/net/wireless/realtek/rtw89/rtw8852c.c:439:\t\t\t B_AX_MAC_UN_EN | B_AX_H_AXIDMA_EN);\ndrivers/net/wireless/realtek/rtw89/rtw8852c.c-440-\n--\ndrivers/net/wireless/realtek/rtw89/rtw8922a.c=475=static int rtw8922a_pwr_on_func(struct rtw89_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw89/rtw8922a.c-610-\t\tB_BE_DISPATCHER_EN | B_BE_BBRPT_EN | B_BE_MAC_SEC_EN |\ndrivers/net/wireless/realtek/rtw89/rtw8922a.c:611:\t\tB_BE_H_AXIDMA_EN | B_BE_DMAC_MLO_EN | B_BE_PLRLS_EN |\ndrivers/net/wireless/realtek/rtw89/rtw8922a.c:612:\t\tB_BE_P_AXIDMA_EN | B_BE_DLE_DATACPUIO_EN;\ndrivers/net/wireless/realtek/rtw89/rtw8922a.c-613-\tif (rtwdev-\u003ehci.type == RTW89_HCI_TYPE_PCIE)\n--\ndrivers/net/wireless/realtek/rtw89/rtw8922d.c=501=static int rtw8922d_pwr_on_func(struct rtw89_dev *rtwdev)\n--\ndrivers/net/wireless/realtek/rtw89/rtw8922d.c-629-\t\t\t B_BE_DISPATCHER_EN | B_BE_BBRPT_EN |\ndrivers/net/wireless/realtek/rtw89/rtw8922d.c:630:\t\t\t B_BE_MAC_SEC_EN | B_BE_H_AXIDMA_EN |\ndrivers/net/wireless/realtek/rtw89/rtw8922d.c-631-\t\t\t B_BE_DMAC_MLO_EN | B_BE_PLRLS_EN |\ndrivers/net/wireless/realtek/rtw89/rtw8922d.c:632:\t\t\t B_BE_P_AXIDMA_EN | B_BE_DLE_DATACPUIO_EN |\ndrivers/net/wireless/realtek/rtw89/rtw8922d.c-633-\t\t\t B_BE_LTR_CTL_EN);\n"
} |
| 9/2 | 2026/08/10 06:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 34884 output: 29 thoughts: 92 Thoughts: Okay, here's my summary, considering my expertise: **Digging into the MT792x AXIDMA Enable Flag** Alright, this is interesting. I'm looking at `MT792x_CHIP_CAP_AXIDMA_EN` and immediately see a potential issue. This define is only declared in `mt792x.h` and used within the `pci.c` file within the same directory. That’s a red flag. Where the heck is this thing being *set*? I need to be sure the flag is enabled as the rest of the code is written in a way that suggests it *should* be. My next step is to drill down into the MT7925-specific code. I need to be sure the function of the flag and its use are clear. I'll check `mt7925/pci.c`, because that's where I would expect to see PCI-specific initialization, but I'll also glance at `mt7925/init.c` and `mt7925/main.c` just to be thorough and rule out any other potential initialization or conditional enabling logic. This needs to be resolved quickly. |
| 10/2 | 2026/08/10 06:13 | tool | grepper |
0mArgs:{
"Expression": "chip_cap.*AXIDMA_EN",
"PathPrefix": ""
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7925/pci.c=46=void mt7925e_axidma_cal_cache_init(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-47-{\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c:48:\tif (!(dev-\u003ephy.chip_cap \u0026 MT792x_CHIP_CAP_AXIDMA_EN))\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-49-\t\treturn;\n"
} |
| 11/2 | 2026/08/10 06:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 35452 output: 43 thoughts: 140 Thoughts: **Debugging a Mysterious Code Path** Okay, this is strange. How is this particular code even executing if a crucial flag isn't defined anywhere? It's making me scratch my head, because this doesn't make any sense. My first thought is to meticulously trace where this flag, `MT792x_CHIP_CAP_AXIDMA_EN`, *might* be set. Let me start by scanning the likely candidates: `mt7925/main.c` and `mt7925/pci.c`. But I need to broaden the search, too. I need to consider that it might be defined in an unincluded patch, too. Need to make sure I don't miss something obvious. Aha! Now that I think about it, if `MT792x_CHIP_CAP_AXIDMA_EN` remains undefined, the function `mt7925e_axidma_cal_cache_init` will simply return right away, so I'm not looking at a functional bug. Still, this is unexpected behavior so I should double-check to make sure it's not a latent bug. I'll need to confirm that `mt7925/pci.c` is the place to do so, because it looks like it's where the initial chip configuration might happen. |
| 12/2 | 2026/08/10 06:13 | tool | grepper |
0mArgs:{
"Expression": "chip_cap.*=",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7925"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7925/mcu.c=1070=mt7925_mcu_get_nic_capability(struct mt792x_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/mcu.c-1123-\t\tcase MT_NIC_CAP_CHIP_CAP:\ndrivers/net/wireless/mediatek/mt76/mt7925/mcu.c:1124:\t\t\tdev-\u003ephy.chip_cap = le64_to_cpu(*(__le64 *)tlv-\u003edata);\ndrivers/net/wireless/mediatek/mt76/mt7925/mcu.c-1125-\t\t\tbreak;\n"
} |
| 13/2 | 2026/08/10 06:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 36130 output: 32 thoughts: 681 Thoughts: **Reaching the Vulnerable Code Path** Okay, so I've been digging into this code and it looks like `dev->phy.chip_cap` gets its value from the firmware through `MT_NIC_CAP_CHIP_CAP` within the `mt7925_mcu_get_nic_capability` function. So, the firmware's essentially telling the driver whether it's got AXIDMA_EN support. If that firmware sets the bit, the code in question is reachable. The immediate question then, is whether a fuzzer like syzkaller could influence this process? Syzkaller, being a PCI fuzzer, works by fuzzing the PCI device, but it *doesn't* emulate firmware. It seems to throw random data at MMIO reads. At first, I was worried the driver might just read a random capability value if syzkaller messed with MMIO. However, it's not a direct read: `mt7925_mcu_get_nic_capability` sends a message to the MCU (firmware) and waits for a response. So, if syzkaller *doesn't* emulate the MCU, we're likely looking at a timeout, or a case where syzkaller might intercept the MCU's response (maybe via DMA or MMIO) and provide its own random data! The critical point is whether syzkaller can manipulate the DMA or MMIO paths, and it can! The MCU's responses tend to land in a DMA ring buffer. Syzkaller can inject random data there, meaning the driver would parse a completely arbitrary MCU response and potentially set `chip_cap` to a random value, potentially including `MT792x_CHIP_CAP_AXIDMA_EN`. This means the code is definitely reachable in a fuzzed environment. Now, I need to make sure this meets the criteria for "WorthFuzzing". The prompt says to return `WorthFuzzing=false` if the patch concerns "vendor-specific PCIe switch, SmartNIC, or GPU drivers that require physical PCIe hardware not emulated in standard QEMU." Is this one of those? Is `mt7925` a vendor-specific PCIe driver that needs physical hardware? No, this is a Wi-Fi driver, and generally, Wi-Fi drivers aren't in that "not worth fuzzing" category. But is it supported by syzkaller? It *is* a PCIe Wi-Fi driver. Does syzkaller fuzz it? Let's see. I can check if `CONFIG_MT7925E` is enabled in syzkaller. I don't have the config file handy, but I know syzkaller fuzzer Wi-Fi drivers, but it usually does so via `mac80211_hwsim`, which is a *software* simulator, and doesn't actually use `mt7925`. But wait, syzkaller *does* have a PCI fuzzer. Does that fuzzer target `mt7925`? Yes, the PCI fuzzer goes after all PCI drivers, by matching PCI IDs. I should double check, let's look at `mt7925_pci_device_table` in `drivers/net/wireless/mediatek/mt76/mt7925/pci.c` to be sure. |
| 14/2 | 2026/08/10 06:13 | tool | grepper |
0mArgs:{
"Expression": "mt7925_pci_device_table",
"PathPrefix": ""
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7925/pci.c-14-\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c:15:static const struct pci_device_id mt7925_pci_device_table[] = {\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-16-\t{ PCI_DEVICE(PCI_VENDOR_ID_MEDIATEK, 0x7925),\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c=974=static struct pci_driver mt7925_pci_driver = {\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-975-\t.name\t\t= KBUILD_MODNAME,\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c:976:\t.id_table\t= mt7925_pci_device_table,\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-977-\t.probe\t\t= mt7925_pci_probe,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c=983=module_pci_driver(mt7925_pci_driver);\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-984-\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c:985:MODULE_DEVICE_TABLE(pci, mt7925_pci_device_table);\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-986-MODULE_FIRMWARE(MT7925_FIRMWARE_WM);\n"
} |
| 15/2 | 2026/08/10 06:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 38076 output: 31 thoughts: 506 Thoughts: **Reaching the MT7925 Driver with Syzkaller** Okay, so the initial thought is that Syzkaller's PCI fuzzer *can* definitely interact with this `mt7925` driver and trigger some fuzzing. But hang on, the prompt specifically mentions code paths unreachable in virtualized environments like GCE or QEMU, particularly when dealing with emulated hardware like USB gadgets or `mac80211_hwsim`. If this driver *requires* a real PCIe card that QEMU doesn't emulate, that's a problem, right? But wait a minute… Syzkaller's PCI fuzzer *is* effectively software-emulated hardware! It intercepts those PCI config space and MMIO accesses. So, we're good; it *can* be reached within a virtualized setting using Syzkaller's PCI fuzzer. Okay, let's step back, the prompt gives examples of specific drivers. Are we talking about something like a vendor-specific PCIe switch, SmartNIC, or GPU driver, which relies on physical hardware that QEMU doesn't emulate? Drivers like `mlxsw`, `pds_core`, `qed`, `ionic`, or `amdgpu`? Is the `mt7925` driver even *in* that category? No, it's a Wi-Fi driver, so that doesn't apply. But now I have to ask myself, does Syzkaller's PCI fuzzer actually get *deep* into the driver's internals? Does it hit the interesting bits? Yes, it can. Let's review the patch more closely. It adds these new functions: `mt7925e_axidma_cal_cache_init`, and associated functions, which involves DMA memory allocation, MCU message sending, and mapping table setup. The specific functions added are: `mt7925_axidma_alloc`, `mt7925_axidma_free`, `mt7925_mcu_send_axidma_info`, `mt7925_mcu_send_fact_cal_mapping_tbl`, `mt7925_mcu_fact_cal_set_bypass`, and that initialization function. Now, where are these functions actually *called*? Looks like `mt7925e_mac_reset` and `mt7925e_mcu_init`. Crucially, `mt7925e_mcu_init` is called during the probe operation. So, the question is, can we actually reach `mt7925e_mcu_init` during probe? If we can reach probe, we can reach these functions, and then we have a potential entry point for fuzzing. |
| 16/2 | 2026/08/10 06:13 | tool | grepper |
0mArgs:{
"Expression": "mt7925e_mcu_init",
"PathPrefix": ""
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h=354=int mt7925e_mac_reset(struct mt792x_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/mt7925.h:355:int mt7925e_mcu_init(struct mt792x_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/mt7925.h-356-void mt7925e_axidma_cal_cache_init(struct mt792x_dev *dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c=588=static int mt7925_pci_probe(struct pci_dev *pdev,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-612-\t\t.reset = mt7925e_mac_reset,\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c:613:\t\t.mcu_init = mt7925e_mcu_init,\ndrivers/net/wireless/mediatek/mt76/mt7925/pci.c-614-\t\t.drv_own = mt792xe_mcu_drv_pmctrl,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c=8=mt7925_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c-26-\ndrivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c:27:int mt7925e_mcu_init(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c-28-{\n"
} |
| 17/2 | 2026/08/10 06:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 39780 output: 37 thoughts: 47 Thoughts: Okay, here's my interpretation of that thought process, assuming I'm deeply familiar with embedded systems and driver development: **Initial Assessment of MCU Initialization in mt7925e** Right, so `mt7925e_mcu_init` is definitely assigned to the `.mcu_init` callback within this driver, and I know that `.mcu_init` gets called during the device probe sequence. That's a good starting point. Now, the next logical step is to pinpoint precisely *where* that `.mcu_init` function gets invoked within the broader context of the probe function. Understanding the call stack around it is crucial. I need to trace the execution path and identify any potential dependencies or timing considerations related to the MCU initialization. |
| 18/2 | 2026/08/10 06:13 | tool | grepper |
0mArgs:{
"Expression": "mcu_init\\(",
"PathPrefix": "drivers/net/wireless/mediatek/mt76"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7603/init.c=278=mt7603_init_hardware(struct mt7603_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7603/init.c-302-\ndrivers/net/wireless/mediatek/mt76/mt7603/init.c:303:\tret = mt7603_mcu_init(dev);\ndrivers/net/wireless/mediatek/mt76/mt7603/init.c-304-\tif (ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt7603/mcu.c=116=static int mt7603_load_firmware(struct mt7603_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7603/mcu.c-217-\ndrivers/net/wireless/mediatek/mt76/mt7603/mcu.c:218:int mt7603_mcu_init(struct mt7603_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7603/mcu.c-219-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7603/mt7603.h=187=void mt7603_dma_cleanup(struct mt7603_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7603/mt7603.h:188:int mt7603_mcu_init(struct mt7603_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7603/mt7603.h-189-void mt7603_init_debugfs(struct mt7603_dev *dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c=33=mt7615_radar_pattern_set(void *data, u64 val)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-37-\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c:38:\tif (!mt7615_wait_for_mcu_init(dev))\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-39-\t\treturn 0;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c=66=mt7615_scs_set(void *data, u64 val)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-70-\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c:71:\tif (!mt7615_wait_for_mcu_init(dev))\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-72-\t\treturn 0;\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-101-\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c:102:\tif (!mt7615_wait_for_mcu_init(dev))\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-103-\t\treturn 0;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c=192=mt7615_dbdc_set(void *data, u64 val)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-195-\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c:196:\tif (!mt7615_wait_for_mcu_init(dev))\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-197-\t\treturn 0;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c=221=mt7615_fw_debug_set(void *data, u64 val)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-224-\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c:225:\tif (!mt7615_wait_for_mcu_init(dev))\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-226-\t\treturn 0;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c=251=mt7615_reset_test_set(void *data, u64 val)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-255-\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c:256:\tif (!mt7615_wait_for_mcu_init(dev))\ndrivers/net/wireless/mediatek/mt76/mt7615/debugfs.c-257-\t\treturn 0;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c=18=static ssize_t mt7615_thermal_show_temp(struct device *dev,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c-24-\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c:25:\tif (!mt7615_wait_for_mcu_init(mdev))\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c-26-\t\treturn 0;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c=188=mt7615_check_offload_capability(struct mt7615_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c-220-\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c:221:bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7615/init.c-222-{\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-34-\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c:35:\tif (!mt7615_wait_for_mcu_init(dev))\ndrivers/net/wireless/mediatek/mt76/mt7615/main.c-36-\t\treturn -EIO;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c=1681=static int mt7663_load_firmware(struct mt7615_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-1695-\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c:1696:int mt7615_mcu_init(struct mt7615_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7615/mcu.c-1697-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h=395=void mt7615_dma_cleanup(struct mt7615_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h:396:int mt7615_mcu_init(struct mt7615_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h:397:bool mt7615_wait_for_mcu_init(struct mt7615_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h-398-void mt7615_mac_set_rates(struct mt7615_phy *phy, struct mt7615_sta *sta,\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h=550=int mt7663_usb_sdio_register_device(struct mt7615_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h:551:int mt7663u_mcu_init(struct mt7615_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h-552-int mt7663u_mcu_power_on(struct mt7615_dev *dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h-554-/* sdio */\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h:555:int mt7663s_mcu_init(struct mt7615_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/mt7615.h-556-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/pci_init.c=15=static void mt7615_pci_init_work(struct work_struct *work)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/pci_init.c-20-\ndrivers/net/wireless/mediatek/mt76/mt7615/pci_init.c:21:\tret = mt7615_mcu_init(dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/pci_init.c-22-\tfor (i = 0; (ret == -EAGAIN) \u0026\u0026 (i \u003c 10); i++) {\ndrivers/net/wireless/mediatek/mt76/mt7615/pci_init.c-23-\t\tmsleep(200);\ndrivers/net/wireless/mediatek/mt76/mt7615/pci_init.c:24:\t\tret = mt7615_mcu_init(dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/pci_init.c-25-\t}\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/pci_init.c=112=void mt7615_unregister_device(struct mt7615_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/pci_init.c-115-\ndrivers/net/wireless/mediatek/mt76/mt7615/pci_init.c:116:\tmcu_running = mt7615_wait_for_mcu_init(dev);\ndrivers/net/wireless/mediatek/mt76/mt7615/pci_init.c-117-\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/sdio.c=42=static void mt7663s_init_work(struct work_struct *work)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/sdio.c-46-\tdev = container_of(work, struct mt7615_dev, mcu_work);\ndrivers/net/wireless/mediatek/mt76/mt7615/sdio.c:47:\tif (mt7663s_mcu_init(dev))\ndrivers/net/wireless/mediatek/mt76/mt7615/sdio.c-48-\t\treturn;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c=98=static int mt7663s_mcu_fw_pmctrl(struct mt7615_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c-132-\ndrivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c:133:int mt7663s_mcu_init(struct mt7615_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7615/sdio_mcu.c-134-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/usb.c=101=static void mt7663u_init_work(struct work_struct *work)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/usb.c-105-\tdev = container_of(work, struct mt7615_dev, mcu_work);\ndrivers/net/wireless/mediatek/mt76/mt7615/usb.c:106:\tif (mt7663u_mcu_init(dev))\ndrivers/net/wireless/mediatek/mt76/mt7615/usb.c-107-\t\treturn;\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c=45=int mt7663u_mcu_power_on(struct mt7615_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c-64-\ndrivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c:65:int mt7663u_mcu_init(struct mt7615_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7615/usb_mcu.c-66-{\n--\ndrivers/net/wireless/mediatek/mt76/mt76x0/mcu.h=22=enum mcu_calibrate {\n--\ndrivers/net/wireless/mediatek/mt76/mt76x0/mcu.h-38-\ndrivers/net/wireless/mediatek/mt76/mt76x0/mcu.h:39:int mt76x0e_mcu_init(struct mt76x02_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt76x0/mcu.h:40:int mt76x0u_mcu_init(struct mt76x02_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt76x0/mcu.h-41-static inline int mt76x0_firmware_running(struct mt76x02_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x0/pci.c=95=static int mt76x0e_init_hardware(struct mt76x02_dev *dev, bool resume)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x0/pci.c-103-\tmt76x02_dma_disable(dev);\ndrivers/net/wireless/mediatek/mt76/mt76x0/pci.c:104:\terr = mt76x0e_mcu_init(dev);\ndrivers/net/wireless/mediatek/mt76/mt76x0/pci.c-105-\tif (err \u003c 0)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c=13=static int mt76x0e_load_firmware(struct mt76x02_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c-115-\ndrivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c:116:int mt76x0e_mcu_init(struct mt76x02_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt76x0/pci_mcu.c-117-{\n--\ndrivers/net/wireless/mediatek/mt76/mt76x0/usb.c=151=static int mt76x0u_init_hardware(struct mt76x02_dev *dev, bool reset)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x0/usb.c-159-\ndrivers/net/wireless/mediatek/mt76/mt76x0/usb.c:160:\terr = mt76x0u_mcu_init(dev);\ndrivers/net/wireless/mediatek/mt76/mt76x0/usb.c-161-\tif (err \u003c 0)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c=85=static int mt76x0u_load_firmware(struct mt76x02_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c-163-\ndrivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c:164:int mt76x0u_mcu_init(struct mt76x02_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt76x0/usb_mcu.c-165-{\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h=58=void mt76x2_phy_set_txpower(struct mt76x02_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h-59-\ndrivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h:60:int mt76x2_mcu_init(struct mt76x02_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt76x2/mt76x2.h-61-int mt76x2_mcu_set_channel(struct mt76x02_dev *dev, u8 channel, u8 bw,\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h=33=void mt76x2u_mcu_complete_urb(struct urb *urb);\ndrivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h:34:int mt76x2u_mcu_init(struct mt76x02_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt76x2/mt76x2u.h-35-int mt76x2u_mcu_fw_init(struct mt76x02_dev *dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c=220=int mt76x2_resume_device(struct mt76x02_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c-233-\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c:234:\treturn mt76x2_mcu_init(dev);\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c-235-}\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c=237=static int mt76x2_init_hardware(struct mt76x02_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c-261-\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c:262:\tret = mt76x2_mcu_init(dev);\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_init.c-263-\tif (ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c=158=mt76pci_mcu_restart(struct mt76_dev *mdev)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c-176-\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c:177:int mt76x2_mcu_init(struct mt76x02_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt76x2/pci_mcu.c-178-{\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c=126=int mt76x2u_init_hardware(struct mt76x02_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c-150-\ndrivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c:151:\terr = mt76x2u_mcu_init(dev);\ndrivers/net/wireless/mediatek/mt76/mt76x2/usb_init.c-152-\tif (err \u003c 0)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c=235=int mt76x2u_mcu_fw_init(struct mt76x02_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c-245-\ndrivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c:246:int mt76x2u_mcu_init(struct mt76x02_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt76x2/usb_mcu.c-247-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7915/init.c=858=mt7915_init_hardware(struct mt7915_dev *dev, struct mt7915_phy *phy2)\n--\ndrivers/net/wireless/mediatek/mt76/mt7915/init.c-872-\ndrivers/net/wireless/mediatek/mt76/mt7915/init.c:873:\tret = mt7915_mcu_init(dev);\ndrivers/net/wireless/mediatek/mt76/mt7915/init.c-874-\tif (ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt7915/mcu.c=2410=int mt7915_mcu_init_firmware(struct mt7915_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7915/mcu.c-2464-\ndrivers/net/wireless/mediatek/mt76/mt7915/mcu.c:2465:int mt7915_mcu_init(struct mt7915_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7915/mcu.c-2466-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7915/mt7915.h=473=int mt7915_run(struct ieee80211_hw *hw);\ndrivers/net/wireless/mediatek/mt76/mt7915/mt7915.h:474:int mt7915_mcu_init(struct mt7915_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7915/mt7915.h-475-int mt7915_mcu_init_firmware(struct mt7915_dev *dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/init.c=84=static int __mt7921_init_hardware(struct mt792x_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/init.c-91-\tmt76_wr(dev, MT_SWDEF_MODE, MT_SWDEF_NORMAL_MODE);\ndrivers/net/wireless/mediatek/mt76/mt7921/init.c:92:\tret = mt792x_mcu_init(dev);\ndrivers/net/wireless/mediatek/mt76/mt7921/init.c-93-\tif (ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/mt7921.h=307=int mt7921e_mac_reset(struct mt792x_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7921/mt7921.h:308:int mt7921e_mcu_init(struct mt792x_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7921/mt7921.h-309-int mt7921s_wfsys_reset(struct mt792x_dev *dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/mt7921.h=311=int mt7921s_init_reset(struct mt792x_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7921/mt7921.h-312-\ndrivers/net/wireless/mediatek/mt76/mt7921/mt7921.h:313:int mt7921s_mcu_init(struct mt792x_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7921/mt7921.h-314-int mt7921s_mcu_drv_pmctrl(struct mt792x_dev *dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c=22=mt7921_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c-40-\ndrivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c:41:int mt7921e_mcu_init(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7921/pci_mcu.c-42-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c=61=static u32 mt7921s_clear_rm3r_drv_own(struct mt792x_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c-73-\ndrivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c:74:int mt7921s_mcu_init(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7921/sdio_mcu.c-75-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/usb.c=36=mt7921u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,\n--\ndrivers/net/wireless/mediatek/mt76/mt7921/usb.c-64-\ndrivers/net/wireless/mediatek/mt76/mt7921/usb.c:65:static int mt7921u_mcu_init(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7921/usb.c-66-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c=100=static int __mt7925_init_hardware(struct mt792x_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-103-\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c:104:\tret = mt792x_mcu_init(dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/init.c-105-\tif (ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/mt7925.h=354=int mt7925e_mac_reset(struct mt792x_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/mt7925.h:355:int mt7925e_mcu_init(struct mt792x_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7925/mt7925.h-356-void mt7925e_axidma_cal_cache_init(struct mt792x_dev *dev);\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c=8=mt7925_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c-26-\ndrivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c:27:int mt7925e_mcu_init(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c-28-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/usb.c=27=mt7925u_mcu_send_message(struct mt76_dev *mdev, struct sk_buff *skb,\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/usb.c-55-\ndrivers/net/wireless/mediatek/mt76/mt7925/usb.c:56:static int mt7925u_mcu_init(struct mt792x_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7925/usb.c-57-{\n--\ndrivers/net/wireless/mediatek/mt76/mt792x.h=263=struct mt792x_dma_layout {\n--\ndrivers/net/wireless/mediatek/mt76/mt792x.h-276-#define mt792x_dev_reset(dev)\t\t((dev)-\u003ehif_ops-\u003ereset(dev))\ndrivers/net/wireless/mediatek/mt76/mt792x.h:277:#define mt792x_mcu_init(dev)\t\t((dev)-\u003ehif_ops-\u003emcu_init(dev))\ndrivers/net/wireless/mediatek/mt76/mt792x.h-278-#define __mt792x_mcu_drv_pmctrl(dev)\t((dev)-\u003ehif_ops-\u003edrv_own(dev))\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/init.c=1264=static int mt7996_init_hardware(struct mt7996_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/init.c-1288-\ndrivers/net/wireless/mediatek/mt76/mt7996/init.c:1289:\tret = mt7996_mcu_init(dev);\ndrivers/net/wireless/mediatek/mt76/mt7996/init.c-1290-\tif (ret)\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/mcu.c=3713=int mt7996_mcu_init_firmware(struct mt7996_dev *dev)\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/mcu.c-3758-\ndrivers/net/wireless/mediatek/mt76/mt7996/mcu.c:3759:int mt7996_mcu_init(struct mt7996_dev *dev)\ndrivers/net/wireless/mediatek/mt76/mt7996/mcu.c-3760-{\n--\ndrivers/net/wireless/mediatek/mt76/mt7996/mt7996.h=703=int mt7996_run(struct mt7996_phy *phy);\ndrivers/net/wireless/mediatek/mt76/mt7996/mt7996.h:704:int mt7996_mcu_init(struct mt7996_dev *dev);\ndrivers/net/wireless/mediatek/mt76/mt7996/mt7996.h-705-int mt7996_mcu_init_firmware(struct mt7996_dev *dev);\n"
} |
| 19/2 | 2026/08/10 06:13 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 49095 output: 44 thoughts: 744 Thoughts: **Analyzing the Impact of a Code Patch** Okay, let's break this down. First, I'm tracing the execution path of `mt7925e_mcu_init`. It looks like that function is called through a series of macros and function calls: `mt792x_mcu_init`, which expands to `(dev)->hif_ops->mcu_init(dev)`, which ultimately leads to `mt7925e_mcu_init`. This `mt792x_mcu_init` function is called within `__mt7925_init_hardware`, which in turn is called by `mt7925_init_hardware`. And, crucially, `mt7925_init_hardware` is initiated via `mt7925_init_work`, which is scheduled during the driver probe. Excellent, that confirms it; this code is definitely hit during the initial probe sequence. Now, the important question: Is this patch merely cosmetic, or does it introduce substantial changes? I'm seeing that it's introducing a completely new feature – AXI DMA calibration cache – with allocations, MCU messaging, and state management. It's not just a documentation update or a change to logging, or constants. No, it's modifying core driver logic. Therefore, this warrants fuzzing; `WorthFuzzing = true`. Next, I need to pinpoint the kernel functions that need the most scrutiny. The new functionality directly touches these: * `mt7925_axidma_alloc` * `mt7925_axidma_free` * `mt7925_mcu_send_axidma_info` * `mt7925_mcu_send_fact_cal_mapping_tbl` * `mt7925_mcu_fact_cal_set_bypass` * `mt7925e_axidma_cal_cache_init` These aren't static; they are exported or have external linkage within the driver. Let's make sure I've got the source files right. Ah, `mt7925_axidma_alloc`, `mt7925_axidma_free`, `mt7925_mcu_send_axidma_info`, `mt7925_mcu_send_fact_cal_mapping_tbl`, and `mt7925_mcu_fact_cal_set_bypass` are in `cached_cal.c` and exported in `cached_cal.h`. `mt7925e_axidma_cal_cache_init` is in `pci.c` and exported in `mt7925.h`. Let's list those functions in FocusSymbols: * `mt7925e_axidma_cal_cache_init` * `mt7925_axidma_alloc` * `mt7925_axidma_free` * `mt7925_mcu_send_axidma_info` * `mt7925_mcu_send_fact_cal_mapping_tbl` * `mt7925_mcu_fact_cal_set_bypass` Finally, I need to check the Kconfig to see what, if any, specific CONFIG options are needed to make sure this new feature is enabled and tested. The driver is `mt7925`, so I'll check `drivers/net/wireless/mediatek/mt76/mt7925/Kconfig`. I'll see if there are any that are relevant. |
| 20/2 | 2026/08/10 06:14 | tool | grepper |
0mArgs:{
"Expression": "config MT7925",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/mt7925"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/mt7925/Kconfig-1-# SPDX-License-Identifier: BSD-3-Clause-Clear\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig:2:config MT7925_COMMON\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig-3-\ttristate\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig-6-\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig:7:config MT7925E\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig-8-\ttristate \"MediaTek MT7925E (PCIe) support\"\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"
} |
| 21/2 | 2026/08/10 06:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 51029 output: 43 thoughts: 124 Thoughts: **Analyzing the PCIe Factory Calibration Feature** Okay, so this feature is *definitely* PCIe-specific. The comment is pretty clear: it's about setting up a factory calibration cache in host memory, and it explicitly says "PCIe only." The Firmware is accessing this cache via AXI DMA, which wouldn't make sense on a different bus architecture. Plus, the code changes confirm this; it's touching `mt7925/pci.c`, `mt7925/pci_mac.c`, and `mt7925/pci_mcu.c`. That means the target configuration is undeniably `MT7925E`. Now, before I dive deeper, I'd better confirm the dependencies of `MT7925E` to see if there are any other configurations or pre-requisites I need to be aware of. Gotta make sure I have the full picture before I start picking this apart. |
| 22/2 | 2026/08/10 06:14 | tool | grepper |
0mArgs:{
"Expression": "depends on",
"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-9-\tselect MT7925_COMMON\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig:10:\tdepends on MAC80211\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig:11:\tdepends on PCI\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig-12-\thelp\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig=19=config MT7925U\n--\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig-22-\tselect MT7925_COMMON\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig:23:\tdepends on MAC80211\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig:24:\tdepends on USB\ndrivers/net/wireless/mediatek/mt76/mt7925/Kconfig-25-\thelp\n"
} |
| 23/2 | 2026/08/10 06:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 51737 output: 39 thoughts: 88 Thoughts: Okay, let's break this down. **Analyzing the MT7925E Configuration Dependencies** Alright, so the `MT7925E` driver, as I see it, relies fundamentally on `MAC80211` and `PCI`. That's the baseline. Now, before I go any further, I should make a quick note to see if there are any other parent configurations I'm missing. Always good to have a complete picture. Looking a bit deeper, I see that `MT76_CORE` is, as expected, selected by `MT7925_COMMON`. That makes sense in terms of the usual Mediatek driver architecture. And finally, I'll need to double-check whether or not `WLAN` and `WLAN_VENDOR_MEDIATEK` are necessary. Let me pop over to `drivers/net/wireless/mediatek/Kconfig` to confirm those selections and dependencies. Gotta be thorough. |
| 24/2 | 2026/08/10 06:14 | tool | grepper |
0mArgs:{
"Expression": "config WLAN_VENDOR_MEDIATEK",
"PathPrefix": "drivers/net/wireless/mediatek/Kconfig"
}Results: {
"Output": "drivers/net/wireless/mediatek/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\ndrivers/net/wireless/mediatek/Kconfig:2:config WLAN_VENDOR_MEDIATEK\ndrivers/net/wireless/mediatek/Kconfig-3-\tbool \"MediaTek devices\"\n"
} |
| 25/2 | 2026/08/10 06:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 52157 output: 41 thoughts: 21 Thoughts: Here's a summary of my thought process, as requested: **Diving into the MT76 Kconfig** Okay, so I need to understand something related to the Mediatek wireless drivers, and my starting point is the `drivers/net/wireless/mediatek/mt76/Kconfig` file. That's usually the place to start when I need to configure or troubleshoot anything within a Linux kernel module. I'm assuming that this Kconfig file will outline all the build options, dependencies, and default values for the MT76 wireless driver, which is a pretty standard approach for this kind of kernel infrastructure. I'll be looking for things like: * **Configuration options:** What features can be enabled or disabled? Is there support for specific chipsets, frequency bands, or wireless standards like 802.11ax? * **Dependencies:** What other kernel components or drivers are required for the MT76 driver to function? This might include things like firmware, other networking subsystems, or even specific hardware drivers. * **Default values:** What are the default settings for the various configuration options? This can give me a quick understanding of the expected behavior of the driver out-of-the-box. * **Help text:** Hopefully, there's some useful help text associated with each option explaining its purpose and impact. That will save me a lot of time. Essentially, I'm expecting this file to give me a high-level overview of the MT76 driver's configurable aspects and how it's integrated into the larger kernel system. Now, let's open it and see what's what! |
| 26/2 | 2026/08/10 06:14 | tool | grepper |
0mArgs:{
"Expression": "config MT76_CORE",
"PathPrefix": "drivers/net/wireless/mediatek/mt76/Kconfig"
}Results: {
"Output": "drivers/net/wireless/mediatek/mt76/Kconfig-1-# SPDX-License-Identifier: BSD-3-Clause-Clear\ndrivers/net/wireless/mediatek/mt76/Kconfig:2:config MT76_CORE\ndrivers/net/wireless/mediatek/mt76/Kconfig-3-\ttristate\n"
} |
| 27/2 | 2026/08/10 06:14 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 52660 output: 260 thoughts: 721 Thoughts: **My Analysis of the MT7925E AXI DMA Calibration Cache Feature** Okay, so I'm looking at enabling this new AXI DMA calibration cache feature for the MT7925 PCIe Wi-Fi driver. Let's break this down. First, I need to make sure the right kernel configs are enabled. `MT7925E`, `MAC80211`, `WLAN`, and `WLAN_VENDOR_MEDIATEK` are definitely necessary. I'm noting that `PCI` is usually enabled by default on x86, and `MAC80211` is standard, so I'll trust those are already taken care of. Now, let's get into the API entrypoints. I've checked the symbol list, and identified: * `mt7925e_axidma_cal_cache_init` * `mt7925_axidma_alloc` * `mt7925_axidma_free` * `mt7925_mcu_send_axidma_info` * `mt7925_mcu_send_fact_cal_mapping_tbl` * `mt7925_mcu_fact_cal_set_bypass` I've also seen a few static helper functions: `mt7925_cal_cache_calc_layout`, `mt7925_cal_cache_region_size`, `mt7925_cal_cache_read_slot`, `mt7925_fact_cal_build_mapping_tbl`, and `mt7925_mcu_fact_cal_rapid_set`. However, since the goal is to favor non-static API entrypoints to allow fuzzing, and these internal helper functions are inlined by the compiler, I'm excluding the static ones. I've verified that `mt7925e_axidma_cal_cache_init` is indeed non-static, defined in `pci.c` and exported in `mt7925.h`, and the others are in `cached_cal.c` and exported in `cached_cal.h`. Essentially, this patch is introducing DMA memory management, MCU messaging and state control to reduce complete calibration by reusing cached data. This will affect the driver's initialization and reset paths. From a fuzzing perspective, the functionality is reachable via PCI device probing and MMIO/DMA interactions, making it an excellent target for syzkaller's PCI fuzzer. Okay, I'm comfortable with the configuration and the relevant entry points. Let's call `set-results`. |
| 28/2 | 2026/08/10 06:14 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"MT7925E",
"MAC80211",
"WLAN",
"WLAN_VENDOR_MEDIATEK"
],
"FocusSymbols": [
"mt7925e_axidma_cal_cache_init",
"mt7925_axidma_alloc",
"mt7925_axidma_free",
"mt7925_mcu_send_axidma_info",
"mt7925_mcu_send_fact_cal_mapping_tbl",
"mt7925_mcu_fact_cal_set_bypass"
],
"Reasoning": "The patch introduces a new AXI DMA factory calibration cache feature for the MediaTek MT7925 PCIe Wi-Fi driver. It adds DMA memory allocation, MCU messaging, and state management to bypass full calibration by reusing cached data. These are functional changes to the driver's initialization and reset paths, reachable via PCI device probing and MMIO/DMA interactions, which can be fuzzed by syzkaller's PCI fuzzer.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"MT7925E",
"MAC80211",
"WLAN",
"WLAN_VENDOR_MEDIATEK"
],
"FocusSymbols": [
"mt7925e_axidma_cal_cache_init",
"mt7925_axidma_alloc",
"mt7925_axidma_free",
"mt7925_mcu_send_axidma_info",
"mt7925_mcu_send_fact_cal_mapping_tbl",
"mt7925_mcu_fact_cal_set_bypass"
],
"Reasoning": "The patch introduces a new AXI DMA factory calibration cache feature for the MediaTek MT7925 PCIe Wi-Fi driver. It adds DMA memory allocation, MCU messaging, and state management to bypass full calibration by reusing cached data. These are functional changes to the driver's initialization and reset paths, reachable via PCI device probing and MMIO/DMA interactions, which can be fuzzed by syzkaller's PCI fuzzer.",
"WorthFuzzing": true
} |
| 29/1 | 2026/08/10 06:14 | action | If |
0mArgs:{
"WorthFuzzing": true
}Results: null |
| 30/2 | 2026/08/10 06:14 | agent | kmsan-evaluator |
0mModel:best-expensive Args: null Results: {
"KMSANReasoning": "The patch introduces a new factory calibration caching mechanism for the MT7925 wireless driver using AXI DMA. All structures sent to the MCU (e.g., `mt7925_axidma_info_req`, `mt7925_fact_cal_req`, `mt7925_fact_cal_mapping_tbl`, and the bypass request) are fully zero-initialized using `kzalloc`, `memset`, or C struct initializers. The DMA buffer itself is allocated with `dma_alloc_coherent`, which guarantees zero-initialization. There is no risk of uninitialized memory being leaked to the MCU or user space, nor is there any control flow dependent on uninitialized variables. Any potential memory corruption, out-of-bounds access, or use-after-free bugs in this code would be effectively caught by standard KASAN. Therefore, a dedicated KMSAN fuzzing session is not required.",
"NeedsKMSAN": false
}Instruction: You are an expert Linux kernel security engineer specializing in kernel memory
error detectors (KASAN and KMSAN). Your job is to review the provided patch series and
determine if the code changes justify spawning a dedicated KMSAN (KernelMemorySanitizer)
fuzzing session in addition to standard KASAN fuzzing.
CRITICAL DISTINCTION BETWEEN KASAN AND KMSAN:
- Standard KASAN kernel builds (upstream-apparmor-kasan.config) already enable
a comprehensive suite of debugging tools and sanitizers, including KASAN
(out-of-bounds accesses, use-after-free, double free, invalid free), LOCKDEP
(locking bugs and deadlocks), UB-sanitizers, and memory corruption checks.
- KMSAN (KernelMemorySanitizer) detects reads of UNINITIALIZED memory (stack, heap,
or page allocations) and kernel-to-user memory info-leaks.
Rule: THERE IS NO SENSE IN RUNNING A KMSAN SESSION IF A BUG CAN BE CAUGHT BY KASAN,
LOCKDEP, OR OTHER STANDARD BUG DETECTORS.
A dedicated KMSAN fuzzing session incurs significant resource costs. You must ONLY
set NeedsKMSAN=true if the code changes introduce or expose UNINITIALIZED MEMORY risks
that are detected ONLY by KMSAN.
Look holistically at the patch series and surrounding code. Even if no direct
uninitialized field accesses or new buffer allocations are added in the diff itself,
a patch may alter control flow, bounds checking, or data length calculations in ways
that change how the rest of the code operates on existing buffers (e.g. allowing
uninitialized stack/heap memory to be read, copied to user space, or used in control
flow). Do not hesitate to use your code access tools to inspect the surrounding code,
called functions, and callers.
Set NeedsKMSAN=true ONLY IF the patch introduces or modifies:
1. Kernel structures sent to user space (via copy_to_user, put_user, netlink skb
attributes, ioctl output arguments, socket options, or BPF buffers) where fields
or structure padding might not be fully initialized/zeroed.
2. Conditional logic or branching that depends on potentially uninitialized variables
or struct fields.
3. Allocation or initialization of complex data structures where uninitialized fields
could be read later in reachable code paths.
4. Bounds checks, lengths, or logic in a way that allows surrounding code to access
uninitialized bytes of existing buffers.
Set NeedsKMSAN=false IF:
- The code changes primarily risk out-of-bounds access, array overflows, NULL pointer
dereferences, locking deadlocks, or use-after-free bugs (these are already caught
by KASAN, LOCKDEP, or standard bug detectors).
- All stack/heap structures touched or introduced by the patch are fully zeroed
or initialized (e.g. using = {0}, memset, kzalloc) before being read or copied.
- The patch does not introduce any risk of uninitialized memory usage or info-leaks.
Use your code access tools to inspect the surrounding code if necessary, then provide
detailed KMSANReasoning contrasting KASAN vs KMSAN applicability for this patch.
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 211b10cacfc32c164f8edcef15e7517d1020bc42
Author: syz-cluster <triage@syzkaller.com>
Date: Mon Aug 10 06:12:37 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
index 0ededa569e9a5..e46cb4ae37a98 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
@@ -1357,9 +1357,11 @@ enum {
MCU_UNI_CMD_ALL_STA_INFO = 0x6e,
MCU_UNI_CMD_ASSERT_DUMP = 0x6f,
MCU_UNI_CMD_EXT_EEPROM_CTRL = 0x74,
+ MCU_UNI_CMD_FACT_CAL = 0x7c,
MCU_UNI_CMD_RADIO_STATUS = 0x80,
MCU_UNI_CMD_MLD = 0x82,
MCU_UNI_CMD_SDO = 0x88,
+ MCU_UNI_CMD_AXIDMA = 0xa2,
};
enum {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/Makefile b/drivers/net/wireless/mediatek/mt76/mt7925/Makefile
index f9dcc0bba393c..33539121a15cd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/Makefile
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/Makefile
@@ -6,5 +6,5 @@ obj-$(CONFIG_MT7925U) += mt7925u.o
mt7925-common-y := mac.o mcu.o regd.o main.o init.o debugfs.o nan.o
mt7925-common-$(CONFIG_NL80211_TESTMODE) += testmode.o
-mt7925e-y := pci.o pci_mac.o pci_mcu.o
+mt7925e-y := pci.o pci_mac.o pci_mcu.o cached_cal.o
mt7925u-y := usb.o
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c b/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c
new file mode 100644
index 0000000000000..03bd682f1224b
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.c
@@ -0,0 +1,304 @@
+// SPDX-License-Identifier: BSD-3-Clause-Clear
+/* Copyright (C) 2026 MediaTek Inc. */
+
+#include <linux/dma-mapping.h>
+#include "../mt792x.h"
+#include "cached_cal.h"
+
+static void mt7925_cal_cache_calc_layout(struct mt7925_cal_cache_layout *l)
+{
+ u32 hdr = sizeof(struct mt7925_fact_cal_buf_info);
+
+ l->common_stride = hdr + MT7925_FACT_CAL_LEN_COM;
+ l->group_stride = hdr + MT7925_FACT_CAL_LEN_GRP;
+ l->channel_stride = hdr + MT7925_FACT_CAL_LEN_CH;
+
+ l->common_off = 0;
+ l->group_off = l->common_off +
+ l->common_stride * MT7925_FACT_CAL_COMMON_BAND_NUM;
+ l->channel_off = l->group_off +
+ l->group_stride * MT7925_FACT_CAL_GROUP_NUM;
+ l->mapping_off = l->channel_off +
+ l->channel_stride * MT7925_FACT_CAL_CH_NUM_ALL;
+ l->total = l->mapping_off +
+ sizeof(struct mt7925_fact_cal_mapping_tbl);
+}
+
+static u32 mt7925_cal_cache_region_size(void)
+{
+ struct mt7925_cal_cache_layout l;
+
+ mt7925_cal_cache_calc_layout(&l);
+
+ return l.total;
+}
+
+int mt7925_axidma_alloc(struct mt792x_dev *dev)
+{
+ u32 total_size;
+ dma_addr_t dma_addr;
+ void *va;
+
+ if (dev->cached_cal.va)
+ return 0;
+
+ total_size = mt7925_cal_cache_region_size();
+
+ va = dma_alloc_coherent(dev->mt76.dev, total_size, &dma_addr,
+ GFP_KERNEL);
+ if (!va)
+ return -ENOMEM;
+
+ dev->cached_cal.va = va;
+ dev->cached_cal.dma_addr = dma_addr;
+ dev->cached_cal.size = total_size;
+
+ return 0;
+}
+
+void mt7925_axidma_free(struct mt792x_dev *dev)
+{
+ if (!dev->cached_cal.va)
+ return;
+
+ dma_free_coherent(dev->mt76.dev, dev->cached_cal.size,
+ dev->cached_cal.va, dev->cached_cal.dma_addr);
+
+ memset(&dev->cached_cal, 0, sizeof(dev->cached_cal));
+}
+
+int mt7925_mcu_send_axidma_info(struct mt792x_dev *dev)
+{
+ struct mt7925_axidma_info_req *req;
+ u32 remap_base, pa_offset;
+ int ret;
+
+ if (!dev->cached_cal.va)
+ return -EINVAL;
+
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ remap_base = (u32)(dev->cached_cal.dma_addr >> 16);
+ pa_offset = (u32)(dev->cached_cal.dma_addr & 0xFFFF);
+
+ req->remap.tag = cpu_to_le16(MT7925_AXIDMA_TAG_REMAP);
+ req->remap.len = cpu_to_le16(sizeof(req->remap));
+ req->remap.remap_addr = cpu_to_le32(remap_base);
+
+ req->fact_cal.tag = cpu_to_le16(MT7925_AXIDMA_TAG_FACT_CAL);
+ req->fact_cal.len = cpu_to_le16(sizeof(req->fact_cal));
+ req->fact_cal.host_addr_offset = cpu_to_le32(pa_offset);
+ req->fact_cal.size = cpu_to_le32(dev->cached_cal.size);
+ req->fact_cal.bound = cpu_to_le32(pa_offset + dev->cached_cal.size - 1);
+
+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(AXIDMA),
+ req, sizeof(*req), true);
+
+ kfree(req);
+
+ if (ret)
+ dev_err(dev->mt76.dev,
+ "failed to send AXI DMA info: %d\n", ret);
+
+ return ret;
+}
+
+static bool mt7925_cal_cache_read_slot(struct mt792x_dev *dev, u32 region_off,
+ u32 stride, u32 idx,
+ u32 *cal_param, u32 *total_buf_num)
+{
+ const struct mt7925_fact_cal_buf_info *bi;
+ u32 off = region_off + stride * idx;
+
+ if (!dev->cached_cal.va || off + sizeof(*bi) > dev->cached_cal.size)
+ return false;
+
+ bi = (const struct mt7925_fact_cal_buf_info *)
+ ((const u8 *)dev->cached_cal.va + off);
+ if (cal_param)
+ *cal_param = le32_to_cpu(bi->cal_param);
+ if (total_buf_num)
+ *total_buf_num = le32_to_cpu(bi->total_buf_num);
+ return true;
+}
+
+static void mt7925_fact_cal_build_mapping_tbl(struct mt792x_dev *dev,
+ struct mt7925_fact_cal_mapping_tbl *tbl)
+{
+ dma_addr_t common_pa, group_pa, channel_pa, mapping_pa;
+ u32 hdr = sizeof(struct mt7925_fact_cal_buf_info);
+ dma_addr_t base = dev->cached_cal.dma_addr;
+ struct mt7925_cal_cache_layout l;
+
+ mt7925_cal_cache_calc_layout(&l);
+
+ common_pa = base + l.common_off;
+ group_pa = base + l.group_off;
+ channel_pa = base + l.channel_off;
+ mapping_pa = base + l.mapping_off;
+
+ memset(tbl, 0, sizeof(*tbl));
+
+ tbl->common.phy_addr_h = cpu_to_le32(upper_32_bits(common_pa));
+ tbl->common.phy_addr_l = cpu_to_le32(lower_32_bits(common_pa));
+ tbl->common.offset = cpu_to_le32(l.common_stride);
+
+ tbl->group.phy_addr_h = cpu_to_le32(upper_32_bits(group_pa));
+ tbl->group.phy_addr_l = cpu_to_le32(lower_32_bits(group_pa));
+ tbl->group.offset = cpu_to_le32(l.group_stride);
+
+ tbl->channel.phy_addr_h = cpu_to_le32(upper_32_bits(channel_pa));
+ tbl->channel.phy_addr_l = cpu_to_le32(lower_32_bits(channel_pa));
+ tbl->channel.offset = cpu_to_le32(l.channel_stride);
+
+ if (dev->cached_cal.reused) {
+ u32 i, cal_param, total_buf_num;
+
+ for (i = 0; i < MT7925_FACT_CAL_COMMON_BAND_NUM; i++)
+ if (mt7925_cal_cache_read_slot(dev, l.common_off,
+ l.common_stride, i,
+ &cal_param, NULL))
+ tbl->common.band[i] = cal_param & 0xff;
+
+ for (i = 0; i < MT7925_FACT_CAL_GROUP_NUM; i++)
+ if (mt7925_cal_cache_read_slot(dev, l.group_off,
+ l.group_stride, i,
+ &cal_param, NULL))
+ tbl->group.group[i] = cal_param & 0xff;
+
+ for (i = 0; i < MT7925_FACT_CAL_CH_NUM_ALL; i++)
+ if (mt7925_cal_cache_read_slot(dev, l.channel_off,
+ l.channel_stride, i,
+ &cal_param,
+ &total_buf_num)) {
+ tbl->channel.cal_param[i] =
+ cpu_to_le32(cal_param);
+ tbl->channel.total_buf_num[i] =
+ total_buf_num & 0xff;
+ }
+ }
+
+ tbl->buf_info_size = cpu_to_le32(hdr);
+ tbl->phy_addr_h = cpu_to_le32(upper_32_bits(mapping_pa));
+ tbl->phy_addr_l = cpu_to_le32(lower_32_bits(mapping_pa));
+}
+
+static int mt7925_mcu_fact_cal_rapid_set(struct mt792x_dev *dev, u8 cal_type,
+ u32 seq_num, bool done,
+ const void *data, u32 data_len)
+{
+ struct mt7925_fact_cal_req *req;
+ int ret;
+
+ if (data_len > MT7925_FACT_CAL_DATA_BUF_LEN)
+ return -EINVAL;
+
+ req = kzalloc(sizeof(*req), GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ req->set.tag = cpu_to_le16(MT7925_FACT_CAL_TAG_RAPID_SET);
+ req->set.len = cpu_to_le16(sizeof(req->set));
+ req->set.seq_num = cpu_to_le32(seq_num);
+ req->set.buf_data_len = cpu_to_le32(data_len);
+ req->set.cal_type = cal_type;
+ req->set.done = done;
+ if (data && data_len)
+ memcpy(req->set.buf_data, data, data_len);
+
+ /* Wait for the ACK on the final chunk only: the FW applies the whole
+ * table there (DMAs the cached common / power-on group cal data in and
+ * programs the PHY), so its ACK is the completion point. Waiting also
+ * drains the ACKs the earlier chunks left in the MCU response queue,
+ * since UNI commands always request one.
+ */
+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(FACT_CAL),
+ req, sizeof(*req), done);
+ kfree(req);
+
+ return ret;
+}
+
+int mt7925_mcu_send_fact_cal_mapping_tbl(struct mt792x_dev *dev)
+{
+ struct mt7925_fact_cal_mapping_tbl *tbl;
+ __le32 cfg[MT7925_FACT_CAL_BUF_CFG_LEN / sizeof(__le32)] = {0};
+ u32 seq = 0, off = 0, left;
+ int ret;
+
+ if (!dev->cached_cal.va)
+ return -EINVAL;
+
+ tbl = kzalloc(sizeof(*tbl), GFP_KERNEL);
+ if (!tbl)
+ return -ENOMEM;
+
+ mt7925_fact_cal_build_mapping_tbl(dev, tbl);
+
+ cfg[1] = cpu_to_le32(sizeof(*tbl));
+ cfg[2] = cpu_to_le32(MT7925_FACT_CAL_DATA_BUF_NUM_MAX);
+ ret = mt7925_mcu_fact_cal_rapid_set(dev, MT7925_FACT_CAL_TYPE_MAPPING_TBL,
+ seq, false, cfg, sizeof(cfg));
+ if (ret) {
+ dev_err(dev->mt76.dev,
+ "fact-cal mapping tbl header send failed (seq=%u): %d\n",
+ seq, ret);
+ goto out;
+ }
+
+ left = sizeof(*tbl);
+ while (left) {
+ u32 chunk = min_t(u32, left, MT7925_FACT_CAL_DATA_BUF_LEN);
+
+ ret = mt7925_mcu_fact_cal_rapid_set(dev,
+ MT7925_FACT_CAL_TYPE_MAPPING_TBL,
+ ++seq, false,
+ (u8 *)tbl + off, chunk);
+ if (ret) {
+ dev_err(dev->mt76.dev,
+ "fact-cal mapping tbl data send failed (seq=%u, off=%u, chunk=%u): %d\n",
+ seq, off, chunk, ret);
+ goto out;
+ }
+
+ off += chunk;
+ left -= chunk;
+ }
+
+ ret = mt7925_mcu_fact_cal_rapid_set(dev, MT7925_FACT_CAL_TYPE_MAPPING_TBL,
+ ++seq, true, NULL, 0);
+ if (ret) {
+ dev_err(dev->mt76.dev,
+ "fact-cal mapping tbl done send failed (seq=%u): %d\n",
+ seq, ret);
+ goto out;
+ }
+out:
+ kfree(tbl);
+
+ return ret;
+}
+
+int mt7925_mcu_fact_cal_set_bypass(struct mt792x_dev *dev, bool enable)
+{
+ struct {
+ u8 _rsv[4];
+
+ struct {
+ __le16 tag;
+ __le16 len;
+ __le32 data;
+ } __packed update_flag;
+ } req = {
+ .update_flag = {
+ .tag = cpu_to_le16(MT7925_FACT_CAL_TAG_UPDATE_FLAG),
+ .len = cpu_to_le16(sizeof(req.update_flag)),
+ .data = cpu_to_le32(enable ? 1 : 0),
+ },
+ };
+
+ return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(FACT_CAL),
+ &req, sizeof(req), false);
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h b/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h
new file mode 100644
index 0000000000000..6572513b76466
--- /dev/null
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/cached_cal.h
@@ -0,0 +1,151 @@
+/* SPDX-License-Identifier: BSD-3-Clause-Clear */
+/* Copyright (C) 2026 MediaTek Inc. */
+
+#ifndef __CACHED_CAL_H
+#define __CACHED_CAL_H
+
+enum mt7925_axidma_info_tag {
+ MT7925_AXIDMA_TAG_REMAP = 0,
+ MT7925_AXIDMA_TAG_FACT_CAL = 1,
+ MT7925_AXIDMA_TAG_NUM
+};
+
+enum mt7925_fact_cal_tag {
+ MT7925_FACT_CAL_TAG_TRIGGER = 2,
+ MT7925_FACT_CAL_TAG_UPDATE_FLAG = 3,
+ MT7925_FACT_CAL_TAG_RAPID_GET = 4,
+ MT7925_FACT_CAL_TAG_RAPID_SET = 5,
+};
+
+enum mt7925_fact_cal_type {
+ MT7925_FACT_CAL_TYPE_COMMON = 0,
+ MT7925_FACT_CAL_TYPE_GROUP = 1,
+ MT7925_FACT_CAL_TYPE_CHANNEL = 2,
+ MT7925_FACT_CAL_TYPE_MAPPING_TBL = 4,
+};
+
+#define MT7925_FACT_CAL_DATA_BUF_LEN 1400
+#define MT7925_FACT_CAL_BUF_CFG_LEN 16
+#define MT7925_FACT_CAL_DATA_BUF_NUM_MAX 4
+#define MT7925_FACT_CAL_BUF_CFG_U32_LEN 4
+#define MT7925_FACT_CAL_DATA_MAX_BUF_LEN \
+ (MT7925_FACT_CAL_DATA_BUF_NUM_MAX * MT7925_FACT_CAL_BUF_CFG_U32_LEN)
+
+#define MT7925_FACT_CAL_COMMON_BAND_NUM 2
+#define MT7925_FACT_CAL_GROUP_NUM 35
+#define MT7925_FACT_CAL_CH_NUM_2G 14
+#define MT7925_FACT_CAL_CH_NUM_5G 68
+#define MT7925_FACT_CAL_CH_NUM_6G 109
+#define MT7925_FACT_CAL_CH_NUM_ALL \
+ (MT7925_FACT_CAL_CH_NUM_2G + MT7925_FACT_CAL_CH_NUM_5G + \
+ MT7925_FACT_CAL_CH_NUM_6G)
+
+#define MT7925_FACT_CAL_LEN_COM 600
+#define MT7925_FACT_CAL_LEN_GRP 4500
+#define MT7925_FACT_CAL_LEN_CH 2800
+
+struct mt7925_fact_cal_buf_info {
+ __le32 cal_type;
+ __le32 cal_param;
+ __le32 buf_seq_num;
+ __le32 total_buf_num;
+ __le32 buf_data_len;
+ u8 valid;
+ u8 done;
+ u8 rsv[2];
+ __le32 buf_cfg_info[MT7925_FACT_CAL_DATA_MAX_BUF_LEN];
+} __packed;
+
+static_assert(sizeof(struct mt7925_fact_cal_buf_info) == 88,
+ "buf_info must match the MT7928 FW (88 bytes) or it rejects the mapping table");
+
+struct mt7925_fact_cal_common_map {
+ __le32 phy_addr_h;
+ __le32 phy_addr_l;
+ __le32 offset;
+ u8 band[MT7925_FACT_CAL_COMMON_BAND_NUM];
+ u8 rsv[2];
+} __packed;
+
+struct mt7925_fact_cal_group_map {
+ __le32 phy_addr_h;
+ __le32 phy_addr_l;
+ __le32 offset;
+ u8 group[MT7925_FACT_CAL_GROUP_NUM];
+ u8 rsv;
+} __packed;
+
+struct mt7925_fact_cal_channel_map {
+ __le32 phy_addr_h;
+ __le32 phy_addr_l;
+ __le32 offset;
+ __le32 cal_param[MT7925_FACT_CAL_CH_NUM_ALL];
+ u8 total_buf_num[MT7925_FACT_CAL_CH_NUM_ALL];
+ u8 rsv;
+} __packed;
+
+struct mt7925_fact_cal_mapping_tbl {
+ struct mt7925_fact_cal_common_map common;
+ struct mt7925_fact_cal_group_map group;
+ struct mt7925_fact_cal_channel_map channel;
+ __le32 buf_info_size;
+ __le32 phy_addr_h;
+ __le32 phy_addr_l;
+} __packed;
+
+static_assert(sizeof(struct mt7925_fact_cal_mapping_tbl) == 1044,
+ "mapping table must match the MT7928 FW (1044 bytes) or the FW parse corrupts");
+
+struct mt7925_cal_cache_layout {
+ u32 common_off, group_off, channel_off, mapping_off;
+ u32 common_stride, group_stride, channel_stride;
+ u32 total;
+};
+
+struct mt7925_axidma_info_req {
+ u8 _rsv[4];
+
+ struct {
+ __le16 tag;
+ __le16 len;
+ __le32 remap_addr;
+ __le32 reserved;
+ } __packed remap;
+
+ struct {
+ __le16 tag;
+ __le16 len;
+ __le32 host_addr_offset;
+ __le32 size;
+ __le32 bound;
+ __le32 reserved;
+ } __packed fact_cal;
+} __packed;
+
+struct mt7925_fact_cal_req {
+ u8 _rsv[4];
+
+ struct {
+ __le16 tag;
+ __le16 len;
+ __le32 data;
+ __le32 seq_num;
+ __le32 buf_data_len;
+ u8 cal_type;
+ u8 done;
+ u8 rsv[2];
+ u8 buf_data[MT7925_FACT_CAL_DATA_BUF_LEN];
+ } __packed set;
+} __packed;
+
+int mt7925_axidma_alloc(struct mt792x_dev *dev);
+
+void mt7925_axidma_free(struct mt792x_dev *dev);
+
+int mt7925_mcu_send_axidma_info(struct mt792x_dev *dev);
+
+int mt7925_mcu_send_fact_cal_mapping_tbl(struct mt792x_dev *dev);
+
+int mt7925_mcu_fact_cal_set_bypass(struct mt792x_dev *dev, bool enable);
+
+#endif /* __CACHED_CAL_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
index 321e732347f2f..4d79c1e66e66b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/mt7925.h
@@ -353,6 +353,7 @@ int mt7925_mcu_parse_response(struct mt76_dev *mdev, int cmd,
int mt7925e_mac_reset(struct mt792x_dev *dev);
int mt7925e_mcu_init(struct mt792x_dev *dev);
+void mt7925e_axidma_cal_cache_init(struct mt792x_dev *dev);
void mt7925_mac_add_txs(struct mt792x_dev *dev, void *data);
void mt7928_mac_add_txs_msg(struct mt792x_dev *dev, void *evt);
void mt7925_set_runtime_pm(struct mt792x_dev *dev);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
index 02ef09dd797da..724abd2be57c5 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci.c
@@ -9,6 +9,7 @@
#include "mac.h"
#include "mcu.h"
#include "regd.h"
+#include "cached_cal.h"
#include "../dma.h"
static const struct pci_device_id mt7925_pci_device_table[] = {
@@ -38,6 +39,62 @@ static int mt7925e_init_reset(struct mt792x_dev *dev)
return mt792x_wpdma_reset(dev, true);
}
+/* Set up the factory-calibration cache in host memory. PCIe only: the FW
+ * reaches the buffer through AXI DMA, so it has no meaning on other buses.
+ * Every failure just leaves the cache off, which is not fatal.
+ */
+void mt7925e_axidma_cal_cache_init(struct mt792x_dev *dev)
+{
+ if (!(dev->phy.chip_cap & MT792x_CHIP_CAP_AXIDMA_EN))
+ return;
+
+ if (dev->cached_cal.va) {
+ /* Carried-over buffer still holds FW-written cal data. */
+ dev->cached_cal.reused = true;
+ } else {
+ if (mt7925_axidma_alloc(dev)) {
+ dev_warn(dev->mt76.dev,
+ "AXI DMA cal cache disabled: buffer alloc failed\n");
+ return;
+ }
+ /* Freshly allocated buffer is zeroed: no cal data yet. */
+ dev->cached_cal.reused = false;
+ }
+
+ if (mt7925_mcu_send_axidma_info(dev)) {
+ dev_warn(dev->mt76.dev,
+ "AXI DMA cal cache disabled: info cmd to FW failed\n");
+ return;
+ }
+
+ /* Enable the bypass-cal flow so the FW reuses cached cal data
+ * (common / power-on group) instead of running a full calibration;
+ * must be set before the mapping table is sent.
+ */
+ if (mt7925_mcu_fact_cal_set_bypass(dev, true)) {
+ dev_warn(dev->mt76.dev,
+ "AXI DMA cal cache disabled: bypass flag set failed\n");
+ return;
+ }
+
+ if (mt7925_mcu_send_fact_cal_mapping_tbl(dev)) {
+ dev_warn(dev->mt76.dev,
+ "AXI DMA cal cache disabled: mapping tbl send failed\n");
+ return;
+ }
+
+ if (mt7925_mcu_fact_cal_set_bypass(dev, false)) {
+ dev_warn(dev->mt76.dev,
+ "AXI DMA cal cache disabled: bypass flag set failed\n");
+ return;
+ }
+
+ dev_info(dev->mt76.dev,
+ "AXI DMA cal cache enabled (DMA=%pad, size=%u, reused=%d)\n",
+ &dev->cached_cal.dma_addr, dev->cached_cal.size,
+ dev->cached_cal.reused);
+}
+
static void mt7925e_unregister_device(struct mt792x_dev *dev)
{
int i;
@@ -58,6 +115,9 @@ static void mt7925e_unregister_device(struct mt792x_dev *dev)
mt7925_tx_token_put(dev);
__mt792x_mcu_drv_pmctrl(dev);
+
+ mt7925_axidma_free(dev);
+
mt792x_dma_cleanup(dev);
mt792x_wfsys_reset(dev);
skb_queue_purge(&dev->mt76.mcu.res_q);
@@ -587,7 +647,7 @@ static int mt7925_pci_probe(struct pci_dev *pdev,
is_mt7928_hw = (pdev->device == 0x7928 || pdev->device == 0x7935);
if (is_mt7928_hw)
- ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(34));
+ ret = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(34));
else
ret = dma_set_mask(&pdev->dev, DMA_BIT_MASK(32));
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
index 8477d21abc660..c90f129b3a34e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mac.c
@@ -135,6 +135,8 @@ int mt7925e_mac_reset(struct mt792x_dev *dev)
if (err)
goto out;
+ mt7925e_axidma_cal_cache_init(dev);
+
err = mt7925_mcu_set_eeprom(dev);
if (err)
goto out;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c
index 72707eddc3db6..258f3753db1fb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7925/pci_mcu.c
@@ -46,6 +46,8 @@ int mt7925e_mcu_init(struct mt792x_dev *dev)
mt76_rmw_field(dev, dev->pcie_reg->pm, MT_PCIE_MAC_PM_L0S_DIS, 1);
err = mt7925_run_firmware(dev);
+ if (!err)
+ mt7925e_axidma_cal_cache_init(dev);
mt76_queue_tx_cleanup(dev, dev->mt76.q_mcu[MT_MCUQ_FWDL], false);
diff --git a/drivers/net/wireless/mediatek/mt76/mt792x.h b/drivers/net/wireless/mediatek/mt76/mt792x.h
index 9efc251cb745f..740d517eb38bb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt792x.h
+++ b/drivers/net/wireless/mediatek/mt76/mt792x.h
@@ -33,6 +33,7 @@
#define MT792x_CHIP_CAP_REGD_EN BIT(5)
#define MT792x_CHIP_CAP_MLO_EN BIT(8)
#define MT792x_CHIP_CAP_MLO_EML_EN BIT(9)
+#define MT792x_CHIP_CAP_AXIDMA_EN BIT(16)
/* NOTE: used to map mt76_rates. idx may change if firmware expands table */
#define MT792x_BASIC_RATES_TBL 14
@@ -342,6 +343,13 @@ struct mt792x_dev {
struct ieee80211_vif *nan_vif;
const struct ieee80211_iface_combination *iface_combinations;
int n_iface_combinations;
+
+ struct {
+ void *va;
+ dma_addr_t dma_addr;
+ u32 size;
+ bool reused;
+ } cached_cal;
};
static inline struct mt792x_bss_conf *
|
| 31/3 | 2026/08/10 06:14 | llm | kmsan-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 11473 output: 223 thoughts: 1947 Thoughts: **KMSAN Check: MT7925 Factory Calibration Data Caching with AXI DMA**
Okay, so this patch introduces a new feature for the MT7925 wireless driver, allowing for caching of factory calibration data using AXI DMA. My initial focus, as always, is on potential uninitialized memory issues. The code allocates a DMA buffer using `dma_alloc_coherent`, sends its address to the MCU, and also sends a mapping table. My primary concern is if there are any uninitialized fields being sent to the MCU, or even worse, user space.
Let me go through the key areas systematically. First, I examined `mt7925_mcu_send_axidma_info`. Here, a `req` structure is allocated using `kzalloc`. Good, `kzalloc` guarantees zero-initialization. This is a critical first step. The code then populates some fields related to DMA remapping and factory calibration data. The crucial part is that `kzalloc` takes care of the initialization.
Next, `mt7925_fact_cal_build_mapping_tbl` is examined. The code initializes `tbl` structure by calling `memset`, so it is fully zeroed.
I also checked `mt7925_mcu_fact_cal_rapid_set`. The `req` is allocated using `kzalloc` there too, which ensures the buffer is zeroed, and any data copied into `req->set.buf_data` will be populated from data passed in the function.
Then, there's `mt7925_mcu_fact_cal_set_bypass`. This one had a bit of an interesting structure with a reserved field `_rsv`. But, since the structure uses an initializer, the C standard guarantees that the uninitialized members will also be zero-initialized. Therefore, `_rsv` will also be zero.
Let's not forget `mt7925_mcu_send_fact_cal_mapping_tbl` which uses `__le32 cfg[] = {0}`. The `cfg` variable is also fully zeroed.
Are there any other structures sent to the MCU? No, it's just `req` and `tbl`. I'm systematically going through the code.
Then I considered whether there were any reads from uninitialized memory. In `mt7925_cal_cache_read_slot`, there's a read from `dev->cached_cal.va`. Ah, but that memory is allocated by `dma_alloc_coherent`. This function zeros the allocated memory, ensuring that the read operation won't expose uninitialized data. Specifically, I confirmed that `dma_alloc_coherent` zero-initializes the memory.
Are there any writes to user space? No, this is all internal communication with the MCU.
Going back to the `mt7925_mcu_fact_cal_rapid_set`, `kzalloc` is definitely the way to go here for the memory allocation, which is exactly what happens.
I did a double check of the `mt7925_mcu_fact_cal_set_bypass` structure again, to make sure it is indeed zero initialized.
Finally, `mt7925_mcu_send_fact_cal_mapping_tbl` is also checked to be allocated with `kzalloc`.
Given all of this, I'm confident that all structures sent to the MCU are fully zero-initialized and there is no risk of uninitialized memory being sent to either the MCU or, vitally, user space. This patch doesn't introduce any KASAN or KMSAN issues related to uninitialized memory. Standard KASAN should be sufficient for addressing potential out-of-bounds or use-after-free issues, and so I will set `NeedsKMSAN=false`.
|
| 32/3 | 2026/08/10 06:14 | tool | set-results |
0mArgs:{
"KMSANReasoning": "The patch introduces a new factory calibration caching mechanism for the MT7925 wireless driver using AXI DMA. All structures sent to the MCU (e.g., `mt7925_axidma_info_req`, `mt7925_fact_cal_req`, `mt7925_fact_cal_mapping_tbl`, and the bypass request) are fully zero-initialized using `kzalloc`, `memset`, or C struct initializers. The DMA buffer itself is allocated with `dma_alloc_coherent`, which guarantees zero-initialization. There is no risk of uninitialized memory being leaked to the MCU or user space, nor is there any control flow dependent on uninitialized variables. Any potential memory corruption, out-of-bounds access, or use-after-free bugs in this code would be effectively caught by standard KASAN. Therefore, a dedicated KMSAN fuzzing session is not required.",
"NeedsKMSAN": false
}Results: {
"KMSANReasoning": "The patch introduces a new factory calibration caching mechanism for the MT7925 wireless driver using AXI DMA. All structures sent to the MCU (e.g., `mt7925_axidma_info_req`, `mt7925_fact_cal_req`, `mt7925_fact_cal_mapping_tbl`, and the bypass request) are fully zero-initialized using `kzalloc`, `memset`, or C struct initializers. The DMA buffer itself is allocated with `dma_alloc_coherent`, which guarantees zero-initialization. There is no risk of uninitialized memory being leaked to the MCU or user space, nor is there any control flow dependent on uninitialized variables. Any potential memory corruption, out-of-bounds access, or use-after-free bugs in this code would be effectively caught by standard KASAN. Therefore, a dedicated KMSAN fuzzing session is not required.",
"NeedsKMSAN": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|