| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/07/31 15:41 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies memory allocation logic in the ath12k driver (Qualcomm Wi-Fi 7), which is a vendor-specific PCIe/AHB hardware driver. This code requires physical hardware to be present and cannot be reached or tested in standard virtualized environments like QEMU or GCE.",
"WorthFuzzing": false
} |
| 1/1 | 2026/07/31 15:41 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 28d875124667c13896da5ff7981ec03522dba45b\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Fri Jul 31 15:41:56 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h\nindex bb1c104e1a65c..78a13b169e99c 100644\n--- a/drivers/net/wireless/ath/ath12k/hw.h\n+++ b/drivers/net/wireless/ath/ath12k/hw.h\n@@ -167,6 +167,7 @@ struct ath12k_hw_params {\n \tu8 max_radios;\n \tbool single_pdev_only:1;\n \tu32 qmi_service_ins_id;\n+\tu32 qmi_max_chunk_size;\n \tbool internal_sleep_clock:1;\n \n \tconst struct ath12k_hw_ops *hw_ops;\ndiff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c\nindex bb61c78e5c29d..bfb5b6659f214 100644\n--- a/drivers/net/wireless/ath/ath12k/qmi.c\n+++ b/drivers/net/wireless/ath/ath12k/qmi.c\n@@ -14,11 +14,11 @@\n #include \u003clinux/of_address.h\u003e\n #include \u003clinux/ioport.h\u003e\n #include \u003clinux/of_reserved_mem.h\u003e\n+#include \u003clinux/sizes.h\u003e\n \n #define SLEEP_CLOCK_SELECT_INTERNAL_BIT\t0x02\n #define HOST_CSTATE_BIT\t\t\t0x04\n #define PLATFORM_CAP_PCIE_GLOBAL_RESET\t0x08\n-#define ATH12K_QMI_MAX_CHUNK_SIZE\t2097152\n \n static const struct qmi_elem_info wlfw_host_mlo_chip_info_s_v01_ei[] = {\n \t{\n@@ -2584,46 +2584,63 @@ static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab,\n \t\tmlo_chunk-\u003ev.ioaddr = NULL;\n \t} else if (mlo_chunk-\u003ev.addr) {\n \t\tdma_free_coherent(ab-\u003edev,\n-\t\t\t\t mlo_chunk-\u003esize,\n-\t\t\t\t mlo_chunk-\u003ev.addr,\n-\t\t\t\t mlo_chunk-\u003epaddr);\n+\t\t\t\t mlo_chunk-\u003etotal_size,\n+\t\t\t\t mlo_chunk-\u003evaddr_unaligned,\n+\t\t\t\t mlo_chunk-\u003epaddr_unaligned);\n+\t\tmlo_chunk-\u003evaddr_unaligned = NULL;\n \t\tmlo_chunk-\u003ev.addr = NULL;\n \t}\n \n \tmlo_chunk-\u003epaddr = 0;\n+\tmlo_chunk-\u003epaddr_unaligned = 0;\n \tmlo_chunk-\u003esize = 0;\n-\tif (fixed_mem)\n+\tmlo_chunk-\u003etotal_size = 0;\n+\n+\tif (fixed_mem) {\n \t\tchunk-\u003ev.ioaddr = NULL;\n-\telse\n+\t} else {\n \t\tchunk-\u003ev.addr = NULL;\n+\t\tchunk-\u003evaddr_unaligned = NULL;\n+\t}\n \tchunk-\u003epaddr = 0;\n+\tchunk-\u003epaddr_unaligned = 0;\n \tchunk-\u003esize = 0;\n+\tchunk-\u003etotal_size = 0;\n }\n \n static void ath12k_qmi_free_target_mem_chunk(struct ath12k_base *ab)\n {\n \tstruct ath12k_hw_group *ag = ab-\u003eag;\n+\tstruct target_mem_chunk *chunk;\n \tint i, mlo_idx;\n \n \tfor (i = 0, mlo_idx = 0; i \u003c ab-\u003eqmi.mem_seg_count; i++) {\n-\t\tif (ab-\u003eqmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) {\n+\t\tchunk = \u0026ab-\u003eqmi.target_mem[i];\n+\n+\t\tif (chunk-\u003etype == MLO_GLOBAL_MEM_REGION_TYPE) {\n \t\t\tath12k_qmi_free_mlo_mem_chunk(ab,\n-\t\t\t\t\t\t \u0026ab-\u003eqmi.target_mem[i],\n+\t\t\t\t\t\t chunk,\n \t\t\t\t\t\t mlo_idx++);\n \t\t} else {\n \t\t\tif (test_bit(ATH12K_FLAG_FIXED_MEM_REGION, \u0026ab-\u003edev_flags) \u0026\u0026\n-\t\t\t ab-\u003eqmi.target_mem[i].v.ioaddr) {\n-\t\t\t\tiounmap(ab-\u003eqmi.target_mem[i].v.ioaddr);\n-\t\t\t\tab-\u003eqmi.target_mem[i].v.ioaddr = NULL;\n+\t\t\t chunk-\u003ev.ioaddr) {\n+\t\t\t\tiounmap(chunk-\u003ev.ioaddr);\n+\t\t\t\tchunk-\u003ev.ioaddr = NULL;\n \t\t\t} else {\n-\t\t\t\tif (!ab-\u003eqmi.target_mem[i].v.addr)\n+\t\t\t\tif (!chunk-\u003ev.addr)\n \t\t\t\t\tcontinue;\n \t\t\t\tdma_free_coherent(ab-\u003edev,\n-\t\t\t\t\t\t ab-\u003eqmi.target_mem[i].prev_size,\n-\t\t\t\t\t\t ab-\u003eqmi.target_mem[i].v.addr,\n-\t\t\t\t\t\t ab-\u003eqmi.target_mem[i].paddr);\n-\t\t\t\tab-\u003eqmi.target_mem[i].v.addr = NULL;\n+\t\t\t\t\t\t chunk-\u003etotal_size,\n+\t\t\t\t\t\t chunk-\u003evaddr_unaligned,\n+\t\t\t\t\t\t chunk-\u003epaddr_unaligned);\n+\t\t\t\tchunk-\u003evaddr_unaligned = NULL;\n+\t\t\t\tchunk-\u003ev.addr = NULL;\n \t\t\t}\n+\n+\t\t\tchunk-\u003epaddr = 0;\n+\t\t\tchunk-\u003epaddr_unaligned = 0;\n+\t\t\tchunk-\u003esize = 0;\n+\t\t\tchunk-\u003etotal_size = 0;\n \t\t}\n \t}\n \n@@ -2636,6 +2653,10 @@ static void ath12k_qmi_free_target_mem_chunk(struct ath12k_base *ab)\n static int ath12k_qmi_alloc_chunk(struct ath12k_base *ab,\n \t\t\t\t struct target_mem_chunk *chunk)\n {\n+\tdma_addr_t paddr;\n+\tsize_t size;\n+\tvoid *vaddr;\n+\n \t/* Firmware reloads in recovery/resume.\n \t * In such cases, no need to allocate memory for FW again.\n \t */\n@@ -2645,29 +2666,56 @@ static int ath12k_qmi_alloc_chunk(struct ath12k_base *ab,\n \t\t\tgoto this_chunk_done;\n \n \t\t/* cannot reuse the existing chunk */\n-\t\tdma_free_coherent(ab-\u003edev, chunk-\u003eprev_size,\n-\t\t\t\t chunk-\u003ev.addr, chunk-\u003epaddr);\n+\t\tdma_free_coherent(ab-\u003edev, chunk-\u003etotal_size,\n+\t\t\t\t chunk-\u003evaddr_unaligned, chunk-\u003epaddr_unaligned);\n \t\tchunk-\u003ev.addr = NULL;\n+\t\tchunk-\u003evaddr_unaligned = NULL;\n+\t\tchunk-\u003epaddr_unaligned = 0;\n+\t\tchunk-\u003etotal_size = 0;\n \t}\n \n-\tchunk-\u003ev.addr = dma_alloc_coherent(ab-\u003edev,\n-\t\t\t\t\t chunk-\u003esize,\n-\t\t\t\t\t \u0026chunk-\u003epaddr,\n+\t/*\n+\t * Each unaligned chunk costs the firmware extra TLB entries when\n+\t * mapping it, and too many unaligned chunks exhaust the TLB and\n+\t * crash the firmware, so align the base to 64 KB. The DMA\n+\t * allocator only guarantees page alignment, but a natural\n+\t * allocation is often already 64 KB aligned. Try the exact size\n+\t * first and keep it when it happens to be aligned; only fall back\n+\t * to over-allocating and rounding up when it is not.\n+\t */\n+\tsize = chunk-\u003esize;\n+\tvaddr = dma_alloc_coherent(ab-\u003edev, size, \u0026paddr,\n+\t\t\t\t GFP_KERNEL | __GFP_NOWARN);\n+\tif (vaddr \u0026\u0026 !IS_ALIGNED(paddr, SZ_64K)) {\n+\t\tdma_free_coherent(ab-\u003edev, size, vaddr, paddr);\n+\n+\t\tsize = chunk-\u003esize + SZ_64K - PAGE_SIZE;\n+\t\tvaddr = dma_alloc_coherent(ab-\u003edev, size, \u0026paddr,\n \t\t\t\t\t GFP_KERNEL | __GFP_NOWARN);\n-\tif (!chunk-\u003ev.addr) {\n-\t\tif (chunk-\u003esize \u003e ATH12K_QMI_MAX_CHUNK_SIZE) {\n+\t}\n+\n+\tif (!vaddr) {\n+\t\tif (chunk-\u003esize \u003e ab-\u003ehw_params-\u003eqmi_max_chunk_size) {\n \t\t\tab-\u003eqmi.target_mem_delayed = true;\n \t\t\tath12k_warn(ab,\n-\t\t\t\t \"qmi dma allocation failed (%u B type %u), will try later with small size\\n\",\n-\t\t\t\t chunk-\u003esize,\n+\t\t\t\t \"qmi dma allocation failed (%zu B type %u), will try later with small size\\n\",\n+\t\t\t\t size,\n \t\t\t\t chunk-\u003etype);\n \t\t\tath12k_qmi_free_target_mem_chunk(ab);\n \t\t\treturn -EAGAIN;\n \t\t}\n-\t\tath12k_warn(ab, \"memory allocation failure for %u size: %u\\n\",\n-\t\t\t chunk-\u003etype, chunk-\u003esize);\n+\t\tath12k_warn(ab, \"memory allocation failure for %u size: %zu\\n\",\n+\t\t\t chunk-\u003etype, size);\n \t\treturn -ENOMEM;\n \t}\n+\n+\tchunk-\u003evaddr_unaligned = vaddr;\n+\tchunk-\u003epaddr_unaligned = paddr;\n+\tchunk-\u003etotal_size = size;\n+\n+\tchunk-\u003epaddr = ALIGN(paddr, SZ_64K);\n+\tchunk-\u003ev.addr = (u8 *)vaddr + (chunk-\u003epaddr - paddr);\n+\n \tchunk-\u003eprev_type = chunk-\u003etype;\n \tchunk-\u003eprev_size = chunk-\u003esize;\n this_chunk_done:\ndiff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h\nindex cbe5be30053a0..afa380f5e9347 100644\n--- a/drivers/net/wireless/ath/ath12k/qmi.h\n+++ b/drivers/net/wireless/ath/ath12k/qmi.h\n@@ -101,6 +101,10 @@ struct target_mem_chunk {\n \t\tvoid __iomem *ioaddr;\n \t\tvoid *addr;\n \t} v;\n+\n+\tdma_addr_t paddr_unaligned;\n+\tvoid *vaddr_unaligned;\n+\tu32 total_size;\n };\n \n struct target_info {\ndiff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c\nindex 296180fbdc21e..23a855018bc48 100644\n--- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c\n+++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c\n@@ -7,6 +7,7 @@\n #include \u003clinux/types.h\u003e\n #include \u003clinux/bitops.h\u003e\n #include \u003clinux/bitfield.h\u003e\n+#include \u003clinux/sizes.h\u003e\n \n #include \"../debug.h\"\n #include \"../core.h\"\n@@ -369,6 +370,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {\n \t\t.max_radios = 1,\n \t\t.single_pdev_only = false,\n \t\t.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9274,\n+\t\t.qmi_max_chunk_size = SZ_2M,\n \t\t.internal_sleep_clock = false,\n \n \t\t.hw_ops = \u0026qcn9274_ops,\n@@ -461,6 +463,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {\n \t\t.max_radios = 1,\n \t\t.single_pdev_only = true,\n \t\t.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_WCN7850,\n+\t\t.qmi_max_chunk_size = SZ_512K,\n \t\t.internal_sleep_clock = true,\n \n \t\t.hw_ops = \u0026wcn7850_ops,\n@@ -553,6 +556,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {\n \t\t.max_radios = 2,\n \t\t.single_pdev_only = false,\n \t\t.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9274,\n+\t\t.qmi_max_chunk_size = SZ_2M,\n \t\t.internal_sleep_clock = false,\n \n \t\t.hw_ops = \u0026qcn9274_ops,\n@@ -643,6 +647,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {\n \t\t.max_radios = 1,\n \t\t.single_pdev_only = false,\n \t\t.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ5332,\n+\t\t.qmi_max_chunk_size = SZ_2M,\n \t\t.internal_sleep_clock = false,\n \n \t\t.hw_ops = \u0026qcn9274_ops,\n@@ -728,6 +733,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {\n \t\t.max_radios = 1,\n \t\t.single_pdev_only = true,\n \t\t.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_WCN7850,\n+\t\t.qmi_max_chunk_size = SZ_512K,\n \t\t.internal_sleep_clock = true,\n \n \t\t.hw_ops = \u0026qcc2072_ops,\n@@ -821,6 +827,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {\n \t\t.max_radios = 1,\n \t\t.single_pdev_only = false,\n \t\t.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ5332,\n+\t\t.qmi_max_chunk_size = SZ_2M,\n \t\t.internal_sleep_clock = false,\n \n \t\t.hw_ops = \u0026qcn9274_ops,\n"
} |
| 2/1 | 2026/07/31 15:41 | agent | patch-evaluator |
0mModel:best-expensive Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies memory allocation logic in the ath12k driver (Qualcomm Wi-Fi 7), which is a vendor-specific PCIe/AHB hardware driver. This code requires physical hardware to be present and cannot be reached or tested in standard virtualized environments like QEMU or GCE.",
"WorthFuzzing": false
}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 28d875124667c13896da5ff7981ec03522dba45b
Author: syz-cluster <triage@syzkaller.com>
Date: Fri Jul 31 15:41:56 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h
index bb1c104e1a65c..78a13b169e99c 100644
--- a/drivers/net/wireless/ath/ath12k/hw.h
+++ b/drivers/net/wireless/ath/ath12k/hw.h
@@ -167,6 +167,7 @@ struct ath12k_hw_params {
u8 max_radios;
bool single_pdev_only:1;
u32 qmi_service_ins_id;
+ u32 qmi_max_chunk_size;
bool internal_sleep_clock:1;
const struct ath12k_hw_ops *hw_ops;
diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c
index bb61c78e5c29d..bfb5b6659f214 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.c
+++ b/drivers/net/wireless/ath/ath12k/qmi.c
@@ -14,11 +14,11 @@
#include <linux/of_address.h>
#include <linux/ioport.h>
#include <linux/of_reserved_mem.h>
+#include <linux/sizes.h>
#define SLEEP_CLOCK_SELECT_INTERNAL_BIT 0x02
#define HOST_CSTATE_BIT 0x04
#define PLATFORM_CAP_PCIE_GLOBAL_RESET 0x08
-#define ATH12K_QMI_MAX_CHUNK_SIZE 2097152
static const struct qmi_elem_info wlfw_host_mlo_chip_info_s_v01_ei[] = {
{
@@ -2584,46 +2584,63 @@ static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab,
mlo_chunk->v.ioaddr = NULL;
} else if (mlo_chunk->v.addr) {
dma_free_coherent(ab->dev,
- mlo_chunk->size,
- mlo_chunk->v.addr,
- mlo_chunk->paddr);
+ mlo_chunk->total_size,
+ mlo_chunk->vaddr_unaligned,
+ mlo_chunk->paddr_unaligned);
+ mlo_chunk->vaddr_unaligned = NULL;
mlo_chunk->v.addr = NULL;
}
mlo_chunk->paddr = 0;
+ mlo_chunk->paddr_unaligned = 0;
mlo_chunk->size = 0;
- if (fixed_mem)
+ mlo_chunk->total_size = 0;
+
+ if (fixed_mem) {
chunk->v.ioaddr = NULL;
- else
+ } else {
chunk->v.addr = NULL;
+ chunk->vaddr_unaligned = NULL;
+ }
chunk->paddr = 0;
+ chunk->paddr_unaligned = 0;
chunk->size = 0;
+ chunk->total_size = 0;
}
static void ath12k_qmi_free_target_mem_chunk(struct ath12k_base *ab)
{
struct ath12k_hw_group *ag = ab->ag;
+ struct target_mem_chunk *chunk;
int i, mlo_idx;
for (i = 0, mlo_idx = 0; i < ab->qmi.mem_seg_count; i++) {
- if (ab->qmi.target_mem[i].type == MLO_GLOBAL_MEM_REGION_TYPE) {
+ chunk = &ab->qmi.target_mem[i];
+
+ if (chunk->type == MLO_GLOBAL_MEM_REGION_TYPE) {
ath12k_qmi_free_mlo_mem_chunk(ab,
- &ab->qmi.target_mem[i],
+ chunk,
mlo_idx++);
} else {
if (test_bit(ATH12K_FLAG_FIXED_MEM_REGION, &ab->dev_flags) &&
- ab->qmi.target_mem[i].v.ioaddr) {
- iounmap(ab->qmi.target_mem[i].v.ioaddr);
- ab->qmi.target_mem[i].v.ioaddr = NULL;
+ chunk->v.ioaddr) {
+ iounmap(chunk->v.ioaddr);
+ chunk->v.ioaddr = NULL;
} else {
- if (!ab->qmi.target_mem[i].v.addr)
+ if (!chunk->v.addr)
continue;
dma_free_coherent(ab->dev,
- ab->qmi.target_mem[i].prev_size,
- ab->qmi.target_mem[i].v.addr,
- ab->qmi.target_mem[i].paddr);
- ab->qmi.target_mem[i].v.addr = NULL;
+ chunk->total_size,
+ chunk->vaddr_unaligned,
+ chunk->paddr_unaligned);
+ chunk->vaddr_unaligned = NULL;
+ chunk->v.addr = NULL;
}
+
+ chunk->paddr = 0;
+ chunk->paddr_unaligned = 0;
+ chunk->size = 0;
+ chunk->total_size = 0;
}
}
@@ -2636,6 +2653,10 @@ static void ath12k_qmi_free_target_mem_chunk(struct ath12k_base *ab)
static int ath12k_qmi_alloc_chunk(struct ath12k_base *ab,
struct target_mem_chunk *chunk)
{
+ dma_addr_t paddr;
+ size_t size;
+ void *vaddr;
+
/* Firmware reloads in recovery/resume.
* In such cases, no need to allocate memory for FW again.
*/
@@ -2645,29 +2666,56 @@ static int ath12k_qmi_alloc_chunk(struct ath12k_base *ab,
goto this_chunk_done;
/* cannot reuse the existing chunk */
- dma_free_coherent(ab->dev, chunk->prev_size,
- chunk->v.addr, chunk->paddr);
+ dma_free_coherent(ab->dev, chunk->total_size,
+ chunk->vaddr_unaligned, chunk->paddr_unaligned);
chunk->v.addr = NULL;
+ chunk->vaddr_unaligned = NULL;
+ chunk->paddr_unaligned = 0;
+ chunk->total_size = 0;
}
- chunk->v.addr = dma_alloc_coherent(ab->dev,
- chunk->size,
- &chunk->paddr,
+ /*
+ * Each unaligned chunk costs the firmware extra TLB entries when
+ * mapping it, and too many unaligned chunks exhaust the TLB and
+ * crash the firmware, so align the base to 64 KB. The DMA
+ * allocator only guarantees page alignment, but a natural
+ * allocation is often already 64 KB aligned. Try the exact size
+ * first and keep it when it happens to be aligned; only fall back
+ * to over-allocating and rounding up when it is not.
+ */
+ size = chunk->size;
+ vaddr = dma_alloc_coherent(ab->dev, size, &paddr,
+ GFP_KERNEL | __GFP_NOWARN);
+ if (vaddr && !IS_ALIGNED(paddr, SZ_64K)) {
+ dma_free_coherent(ab->dev, size, vaddr, paddr);
+
+ size = chunk->size + SZ_64K - PAGE_SIZE;
+ vaddr = dma_alloc_coherent(ab->dev, size, &paddr,
GFP_KERNEL | __GFP_NOWARN);
- if (!chunk->v.addr) {
- if (chunk->size > ATH12K_QMI_MAX_CHUNK_SIZE) {
+ }
+
+ if (!vaddr) {
+ if (chunk->size > ab->hw_params->qmi_max_chunk_size) {
ab->qmi.target_mem_delayed = true;
ath12k_warn(ab,
- "qmi dma allocation failed (%u B type %u), will try later with small size\n",
- chunk->size,
+ "qmi dma allocation failed (%zu B type %u), will try later with small size\n",
+ size,
chunk->type);
ath12k_qmi_free_target_mem_chunk(ab);
return -EAGAIN;
}
- ath12k_warn(ab, "memory allocation failure for %u size: %u\n",
- chunk->type, chunk->size);
+ ath12k_warn(ab, "memory allocation failure for %u size: %zu\n",
+ chunk->type, size);
return -ENOMEM;
}
+
+ chunk->vaddr_unaligned = vaddr;
+ chunk->paddr_unaligned = paddr;
+ chunk->total_size = size;
+
+ chunk->paddr = ALIGN(paddr, SZ_64K);
+ chunk->v.addr = (u8 *)vaddr + (chunk->paddr - paddr);
+
chunk->prev_type = chunk->type;
chunk->prev_size = chunk->size;
this_chunk_done:
diff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h
index cbe5be30053a0..afa380f5e9347 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.h
+++ b/drivers/net/wireless/ath/ath12k/qmi.h
@@ -101,6 +101,10 @@ struct target_mem_chunk {
void __iomem *ioaddr;
void *addr;
} v;
+
+ dma_addr_t paddr_unaligned;
+ void *vaddr_unaligned;
+ u32 total_size;
};
struct target_info {
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
index 296180fbdc21e..23a855018bc48 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
@@ -7,6 +7,7 @@
#include <linux/types.h>
#include <linux/bitops.h>
#include <linux/bitfield.h>
+#include <linux/sizes.h>
#include "../debug.h"
#include "../core.h"
@@ -369,6 +370,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.max_radios = 1,
.single_pdev_only = false,
.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9274,
+ .qmi_max_chunk_size = SZ_2M,
.internal_sleep_clock = false,
.hw_ops = &qcn9274_ops,
@@ -461,6 +463,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.max_radios = 1,
.single_pdev_only = true,
.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_WCN7850,
+ .qmi_max_chunk_size = SZ_512K,
.internal_sleep_clock = true,
.hw_ops = &wcn7850_ops,
@@ -553,6 +556,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.max_radios = 2,
.single_pdev_only = false,
.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_QCN9274,
+ .qmi_max_chunk_size = SZ_2M,
.internal_sleep_clock = false,
.hw_ops = &qcn9274_ops,
@@ -643,6 +647,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.max_radios = 1,
.single_pdev_only = false,
.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ5332,
+ .qmi_max_chunk_size = SZ_2M,
.internal_sleep_clock = false,
.hw_ops = &qcn9274_ops,
@@ -728,6 +733,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.max_radios = 1,
.single_pdev_only = true,
.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_WCN7850,
+ .qmi_max_chunk_size = SZ_512K,
.internal_sleep_clock = true,
.hw_ops = &qcc2072_ops,
@@ -821,6 +827,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
.max_radios = 1,
.single_pdev_only = false,
.qmi_service_ins_id = ATH12K_QMI_WLFW_SERVICE_INS_ID_V01_IPQ5332,
+ .qmi_max_chunk_size = SZ_2M,
.internal_sleep_clock = false,
.hw_ops = &qcn9274_ops,
|
| 3/2 | 2026/07/31 15:41 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 5809 output: 93 thoughts: 787 Thoughts: **WorthFuzzing=false: ath12k QMI Memory Allocation** Okay, so I've got this patch that modifies the QMI memory chunk allocation within the `ath12k` driver. It's touching `qmi.c`, `hw.h`, `qmi.h`, and `wifi7/hw.c`. The key thing is this: `ath12k` is Qualcomm's Wi-Fi 7 driver. My initial thought is, can I even *get* to this code in a standard virtualization setup, like QEMU? I know `ath12k` is a PCIe/AHB driver, which immediately makes me think "physical hardware requirement". I briefly wonder if something like `mac80211_hwsim` could emulate it, but no, `ath12k` is specific to the Qualcomm hardware, so that's a dead end. The prompt specifically flags vendor-specific PCIe drivers that need physical hardware as un-fuzzable, like mlxsw, qed, and so on. *ath12k* fits that description perfectly, being a vendor-specific Wi-Fi driver for Qualcomm (QCN9274, WCN7850, IPQ5332, etc.) and relying on PCIe/AHB. There's no QEMU emulation here. I need to be sure. I'm checking if there's *any* way to touch `ath12k_qmi_alloc_chunk`. It seems to be triggered during device initialization or QMI message handling. Since it requires a physical PCIe/AHB device, I'm pretty confident it's not reachable in a standard QEMU environment. Let me confirm that ath12k is vendor-specific, which is a yes, Qualcomm. I need to confirm if there is a way to emulate it. No, there isn't. Now, considering the prompt's criteria: "Code paths that are impossible to reach in virtualized environments... even when utilizing software-emulated hardware", and "vendor-specific PCIe... drivers that require physical PCIe... hardware... not emulated in standard QEMU," I'm solidly concluding that this patch is *not* worth fuzzing within a virtualized setting like QEMU. Therefore, I'm setting `WorthFuzzing=false`. Time to finalize the results. |
| 4/2 | 2026/07/31 15:42 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch modifies memory allocation logic in the ath12k driver (Qualcomm Wi-Fi 7), which is a vendor-specific PCIe/AHB hardware driver. This code requires physical hardware to be present and cannot be reached or tested in standard virtualized environments like QEMU or GCE.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies memory allocation logic in the ath12k driver (Qualcomm Wi-Fi 7), which is a vendor-specific PCIe/AHB hardware driver. This code requires physical hardware to be present and cannot be reached or tested in standard virtualized environments like QEMU or GCE.",
"WorthFuzzing": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|