| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/09/21 14:24 | flow | patch-triage |
9mArgs:null Results: {
"EnableConfigs": [
"MM81X",
"MM81X_USB",
"WLAN_VENDOR_MORSEMICRO",
"MAC80211",
"USB"
],
"FocusSymbols": [
"mm81x_yaps_hw_read_pkts",
"mm81x_yaps_rx_handler",
"mm81x_yaps_work"
],
"KMSANReasoning": "The patch adds a bounds check in mm81x_yaps_hw_read_pkts() ensuring that bytes_remaining \u003e= sizeof(delim) before reading a 32-bit delimiter from read_ptr. Previously, if bytes_remaining was between 1 and 3, reading 4 bytes could perform an out-of-bounds read past the buffer or valid data and underflow bytes_remaining to a negative value, leading to severe out-of-bounds memcpy issues. These types of bugs (out-of-bounds reads/writes and buffer overflows) are directly caught by KASAN. The patch does not introduce or expose uninitialized memory, does not alter uninitialized padding or structures copied to user space, and does not branch on uninitialized variables. Therefore, a dedicated KMSAN fuzzing session is not justified.",
"NeedsKMSAN": false,
"Reasoning": "The patch adds a bounds check in mm81x_yaps_hw_read_pkts to prevent out-of-bounds reads when parsing received packet delimiters from the chip buffer. The Morse Micro MM81x wireless driver supports USB devices (CONFIG_MM81X_USB), which can be probed and fuzzed in standard virtualized environments using USB emulation (such as Raw Gadget). Therefore, the modified executable code is reachable and worth fuzzing.",
"WorthFuzzing": true
} |
| 1/1 | 2026/09/21 14:24 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 0ffa363bb947a4fc8b8cbb1ffa89fbf41b792e59\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Mon Sep 21 14:24:11 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/wireless/morsemicro/mm81x/yaps_hw.c b/drivers/net/wireless/morsemicro/mm81x/yaps_hw.c\nindex 3d641d23c35ba..e1102b8fb8020 100644\n--- a/drivers/net/wireless/morsemicro/mm81x/yaps_hw.c\n+++ b/drivers/net/wireless/morsemicro/mm81x/yaps_hw.c\n@@ -486,6 +486,9 @@ static int mm81x_yaps_hw_read_pkts(struct mm81x_yaps *yaps,\n \t\tint total_len;\n \t\tint pkt_size;\n \n+\t\tif (bytes_remaining \u003c (int)sizeof(delim))\n+\t\t\tbreak;\n+\n \t\tdelim = le32_to_cpu(*((__le32 *)read_ptr));\n \t\tread_ptr += sizeof(delim);\n \t\tbytes_remaining -= sizeof(delim);\n"
} |
| 2/1 | 2026/09/21 14:24 | agent | patch-evaluator |
6mModel:core Args: null Results: {
"EnableConfigs": [
"MM81X",
"MM81X_USB",
"WLAN_VENDOR_MORSEMICRO",
"MAC80211",
"USB"
],
"FocusSymbols": [
"mm81x_yaps_hw_read_pkts",
"mm81x_yaps_rx_handler",
"mm81x_yaps_work"
],
"Reasoning": "The patch adds a bounds check in mm81x_yaps_hw_read_pkts to prevent out-of-bounds reads when parsing received packet delimiters from the chip buffer. The Morse Micro MM81x wireless driver supports USB devices (CONFIG_MM81X_USB), which can be probed and fuzzed in standard virtualized environments using USB emulation (such as Raw Gadget). Therefore, the modified executable code is reachable and worth fuzzing.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.
IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.
================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.
- REACHABILITY IS THE PRIMARY GATE:
Fuzzing can only discover bugs in code that can actually execute in standard virtualized
environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
regardless of whether it adds assertions or complex logic.
- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
Patch authors routinely label changes as "cleanups", "refactorings", or state
"No functional change intended". Do NOT take these claims at face value.
Code refactorings that rearrange logic, introduce helper functions, or alter state management
in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
If reachable executable code is modified or refactored, it MUST be fuzzed.
- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
Even if the author believes the invariant always holds, fuzzing is essential to verify whether
an unusual sequence of operations can violate it.
================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:
- Non-kernel and non-executable changes:
* Modifications to Documentation/, comments, or spelling fixes.
* User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
that do not affect the compiled kernel image (vmlinux) or kernel modules.
* Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
that do not alter control flow or data structures.
* Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
* Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
* Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
physical PCI hot-unplug or manual sysfs driver unbinding.
* Code paths exclusive to architectures other than the target architecture.
================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
* Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
* Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
* Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
* Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).
================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:
- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
Do NOT list generic, ubiquitous functions called by almost every program in the corpus
(including, but not limited to: general memory allocators and deallocators, page fault
and trap handlers, or core synchronization primitives; this is not an exhaustive list).
Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
which severely dilutes fuzzing effort away from the actual changes.
- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
List functions that specifically implement the logic being added or altered, or direct API entrypoints
for the subsystem feature under review.
- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).
================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any '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: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit 0ffa363bb947a4fc8b8cbb1ffa89fbf41b792e59
Author: syz-cluster <triage@syzkaller.com>
Date: Mon Sep 21 14:24:11 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/wireless/morsemicro/mm81x/yaps_hw.c b/drivers/net/wireless/morsemicro/mm81x/yaps_hw.c
index 3d641d23c35ba..e1102b8fb8020 100644
--- a/drivers/net/wireless/morsemicro/mm81x/yaps_hw.c
+++ b/drivers/net/wireless/morsemicro/mm81x/yaps_hw.c
@@ -486,6 +486,9 @@ static int mm81x_yaps_hw_read_pkts(struct mm81x_yaps *yaps,
int total_len;
int pkt_size;
+ if (bytes_remaining < (int)sizeof(delim))
+ break;
+
delim = le32_to_cpu(*((__le32 *)read_ptr));
read_ptr += sizeof(delim);
bytes_remaining -= sizeof(delim);
|
| 3/2 | 2026/09/21 14:24 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 2923 output: 32 thoughts: 282 Thoughts: **Analyzing a Kernel Patch** Okay, here's the deal. I've got this patch in front of me, and my immediate goal is to understand precisely what's being tweaked. The patch is touching `drivers/net/wireless/morsemicro/mm81x/yaps_hw.c`. Alright, so we're dealing with the Morse Micro mm81x wireless driver. *yaps_hw.c*… that likely handles the hardware-specific aspects of packet processing, probably related to their YAPS (Yet Another Packet Structure) protocol. The added code checks if there are enough bytes remaining to read the delimiter. If not it bails from the packet read loop. I see, this is a safety check to prevent reading beyond the available data and prevent a crash. Makes sense. Now, let's zoom out a bit. I need to understand the architectural context of this driver. What kind of bus is the `mm81x` module communicating over? Is it SDIO, SPI, PCIe, or USB? That will give me a more complete picture of the hardware interaction and performance implications of this change. Time to dive into the rest of the files within the `drivers/net/wireless/morsemicro/mm81x/` directory to get a better overview. |
| 4/2 | 2026/09/21 14:24 | tool | codesearch-dir-index |
0mArgs:{
"Dir": "drivers/net/wireless/morsemicro/mm81x"
}Results: {
"Files": [
"bus.h",
"command.c",
"command.h",
"command_defs.h",
"core.c",
"core.h",
"fw.c",
"fw.h",
"hif.h",
"hw.c",
"hw.h",
"mac.c",
"mac.h",
"mmrc.c",
"mmrc.h",
"ps.c",
"ps.h",
"rate_code.h",
"rc.c",
"rc.h",
"sdio.c",
"skbq.c",
"skbq.h",
"usb.c",
"yaps.c",
"yaps.h",
"yaps_hw.c",
"yaps_hw.h"
],
"Subdirs": null
} |
| 5/2 | 2026/09/21 14:24 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 3711 output: 80 thoughts: 43 Thoughts: Okay, here's my take on those thoughts, framed as my own, given my expertise: **Diving into the Wireless Driver Landscape** Alright, my internal radar just pinged on those two files: `usb.c` and `sdio.c`. They're screaming "network interface" to me. Specifically, their presence is making me think of a potential wireless driver. Given the context, I immediately want to dig into how those interfaces are being used. My first instinct? Let's go spelunking in the `drivers/net/wireless/morsemicro/` directory (or a directory of that nature, depending on the kernel version and project organization). I'll be looking for relevant `Kconfig` files alongside `usb.c`, because I know that's where the conditional compilation and device support definitions are stored. I want to understand how these USB and SDIO interfaces are being leveraged for wireless communication within this specific driver. Knowing the connection configuration can give some hints as to the capabilities and the underlying hardware. |
| 6/2 | 2026/09/21 14:24 | tool | grepper |
0mArgs:{
"Expression": "CONFIG_.*MM81X",
"PathPrefix": "drivers/net/wireless/morsemicro"
}Results: {
"Output": "drivers/net/wireless/morsemicro/Makefile-1-# SPDX-License-Identifier: GPL-2.0\ndrivers/net/wireless/morsemicro/Makefile:2:obj-$(CONFIG_MM81X) += mm81x/\n--\ndrivers/net/wireless/morsemicro/mm81x/Makefile-2-\ndrivers/net/wireless/morsemicro/mm81x/Makefile:3:obj-$(CONFIG_MM81X) += mm81x_core.o\ndrivers/net/wireless/morsemicro/mm81x/Makefile-4-\n--\ndrivers/net/wireless/morsemicro/mm81x/Makefile=15=mm81x_core-y += mmrc.o\ndrivers/net/wireless/morsemicro/mm81x/Makefile-16-\ndrivers/net/wireless/morsemicro/mm81x/Makefile:17:obj-$(CONFIG_MM81X_USB) += mm81x_usb.o\ndrivers/net/wireless/morsemicro/mm81x/Makefile-18-mm81x_usb-y += usb.o\ndrivers/net/wireless/morsemicro/mm81x/Makefile-19-\ndrivers/net/wireless/morsemicro/mm81x/Makefile:20:obj-$(CONFIG_MM81X_SDIO) += mm81x_sdio.o\ndrivers/net/wireless/morsemicro/mm81x/Makefile-21-mm81x_sdio-y += sdio.o\n"
} |
| 7/2 | 2026/09/21 14:24 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/usb.c",
"FirstLine": 1,
"LineCount": 50
}Results: {
"Contents": " 1:\t// SPDX-License-Identifier: GPL-2.0-only\n 2:\t/*\n 3:\t * Copyright (c) 2017-2026 Morse Micro\n 4:\t */\n 5:\t#include \u003clinux/jiffies.h\u003e\n 6:\t#include \u003clinux/module.h\u003e\n 7:\t#include \u003clinux/usb.h\u003e\n 8:\t#include \"hif.h\"\n 9:\t#include \"bus.h\"\n 10:\t#include \"mac.h\"\n 11:\t#include \"core.h\"\n 12:\t\n 13:\t/*\n 14:\t * URB timeout in milliseconds. If an URB does not complete within this\n 15:\t * time, it will be killed. This timeout needs to account for USB suspendand\n 16:\t * resume occurring before the URB can be transferred, and it also needs to\n 17:\t * account for transferring USB_MAX_TRANSFER_SIZE bytes over a potentially\n 18:\t * slow, congested USB Full Speed link.\n 19:\t */\n 20:\t#define URB_TIMEOUT_MS 250\n 21:\t\n 22:\t/* High speed USB 2^(4-1) * 125usec = 1msec */\n 23:\t#define MM81X_USB_INTERRUPT_INTERVAL 4\n 24:\t\n 25:\t/* Max bytes per USB read/write */\n 26:\t#define USB_MAX_TRANSFER_SIZE (16 * 1024)\n 27:\t\n 28:\t/* INT EP buffer size */\n 29:\t#define MM81X_EP_INT_BUFFER_SIZE 8\n 30:\t\n 31:\t/* Morse vendor IDs*/\n 32:\t#define MM81X_VENDOR_ID 0x325b\n 33:\t#define MM81X_MM810X_PRODUCT_ID 0x8100\n 34:\t\n 35:\t/* Power management runtime auto-suspend delay value in milliseconds */\n 36:\t#define PM_RUNTIME_AUTOSUSPEND_DELAY_MS 100\n 37:\t\n 38:\tenum mm81x_usb_endpoints {\n 39:\t\tMM81X_EP_CMD = 0,\n 40:\t\tMM81X_EP_INT,\n 41:\t\tMM81X_EP_MEM_RD,\n 42:\t\tMM81X_EP_MEM_WR,\n 43:\t\tMM81X_EP_REG_RD,\n 44:\t\tMM81X_EP_REG_WR,\n 45:\t\tMM81X_EP_EP_MAX,\n 46:\t};\n 47:\t\n 48:\tstruct mm81x_usb_endpoint {\n 49:\t\tunsigned char *buffer;\n 50:\t\tstruct urb *urb;\n"
} |
| 8/2 | 2026/09/21 14:24 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 5185 output: 49 thoughts: 82 Thoughts: **USB Driver Exploration** Okay, so I've stumbled upon something interesting - a USB driver. This opens up some exciting possibilities, namely the emulation of USB devices! I know there are a few options here: USB raw gadget, syzkaller's USB emulation, or even VirtualUSB. Seems like we can play around with the hardware directly. But before I dive into the deep end, let's step back and understand the broader context. I'm getting ahead of myself, I want to find the entry point. Specifically, I need to figure out how `mm81x_yaps_hw_read_pkts` is actually reached. This smells like a good starting point for investigation. Where's that function defined? Looks like I need to dig into the `drivers/net/wireless/morsemicro/mm81x/yaps_hw.c` file. This should give me the low-down on how the hardware interactions work. |
| 9/2 | 2026/09/21 14:24 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/yaps_hw.c",
"FirstLine": 470,
"LineCount": 50
}Results: {
"Contents": " 470:\t\tret = mm81x_yaps_hw_lock(yaps);\n 471:\t\tif (ret) {\n 472:\t\t\tdev_dbg(yaps-\u003emors-\u003edev, \"yaps lock failed %d\", ret);\n 473:\t\t\treturn ret;\n 474:\t\t}\n 475:\t\n 476:\t\t/* Read all available packets to the buffer */\n 477:\t\tret = mm81x_dm_read(yaps-\u003emors, yaps-\u003eaux_data-\u003eysl_addr,\n 478:\t\t\t\t from_chip_buffer_aligned, bytes_remaining);\n 479:\t\n 480:\t\tif (ret)\n 481:\t\t\tgoto exit;\n 482:\t\n 483:\t\t/* Split serialised packets from buffer */\n 484:\t\twhile (i \u003c num_pkts_max \u0026\u0026 bytes_remaining \u003e 0) {\n 485:\t\t\tu32 delim;\n 486:\t\t\tint total_len;\n 487:\t\t\tint pkt_size;\n 488:\t\n 489:\t\t\tif (bytes_remaining \u003c (int)sizeof(delim))\n 490:\t\t\t\tbreak;\n 491:\t\n 492:\t\t\tdelim = le32_to_cpu(*((__le32 *)read_ptr));\n 493:\t\t\tread_ptr += sizeof(delim);\n 494:\t\t\tbytes_remaining -= sizeof(delim);\n 495:\t\n 496:\t\t\t/* End of stream */\n 497:\t\t\tif (!delim)\n 498:\t\t\t\tbreak;\n 499:\t\n 500:\t\t\tif (!mm81x_read_pkts_h_is_valid_delim(delim)) {\n 501:\t\t\t\t/*\n 502:\t\t\t\t * This will start a hunt for a valid delimiter. Given\n 503:\t\t\t\t * the CRC is only 7 bit it's possible to find an\n 504:\t\t\t\t * invalid block with a valid delimiter, leading to\n 505:\t\t\t\t * desynchronisation.\n 506:\t\t\t\t */\n 507:\t\t\t\tdev_warn(yaps-\u003emors-\u003edev, \"yaps invalid delim\");\n 508:\t\t\t\tbreak;\n 509:\t\t\t}\n 510:\t\n 511:\t\t\t/* Total length in chip */\n 512:\t\t\tpkt_size = YAPS_DELIM_GET_PKT_SIZE(delim);\n 513:\t\t\ttotal_len = pkt_size + YAPS_DELIM_GET_PADDING(delim);\n 514:\t\n 515:\t\t\tif (pkts[i].skb)\n 516:\t\t\t\tdev_err(yaps-\u003emors-\u003edev, \"yaps packet leak\");\n 517:\t\n 518:\t\t\t/* SKB doesn't want padding */\n 519:\t\t\tpkts[i].skb = dev_alloc_skb(pkt_size);\n"
} |
| 10/2 | 2026/09/21 14:24 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 6280 output: 48 thoughts: 23 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience and written in the first person: **Investigating the Callers of `mm81x_yaps_hw_read_pkts`** Okay, so I need to understand what's actually *using* `mm81x_yaps_hw_read_pkts`. It's a low-level function, likely dealing with hardware packet reads in the YAPS (likely Yet Another Packet System or similar) module, judging by the naming convention. I have a hunch it's probably critical to the data path, so I need to figure out the upstream dependencies quickly. This isn't just about code browsing; I need to understand the execution flow. First, I'll identify all the immediate callers of that function. I'll need to use my preferred tool, be it static analysis with a tool like `ctags`, `cscope`, a dedicated IDE's call graph functionality, or perhaps a more dynamic tracing approach if the codebase supports it. I need to quickly see the call hierarchy. I'm looking for the direct functions that invoke `mm81x_yaps_hw_read_pkts`. Then, I'll need to quickly assess the context of those calls. What are the calling functions doing? What data are they manipulating before and after the call? Are there any obvious critical sections or locking mechanisms involved? Are we talking about interrupt handlers, DMA completion routines, or something else entirely? Knowing the context will help me understand the implications of any issues within `mm81x_yaps_hw_read_pkts`. I also want to know if that function is handling errors or just assuming the read is successful. Depending on the architecture, there could be interesting implications for the error handling or recovery. I'm anticipating some level of error checking in the caller, but the sophistication might vary, based on the age of the code and the target platform. I'm expecting some kind of sanity check on the return value or any errors reported in global state. Finally, I'll need to build a mental model of the data flow. Where does the data from `mm81x_yaps_hw_read_pkts` go? Is it buffered? Processed immediately? Passed on to another subsystem? Knowing the destination will tell me which other areas I need to investigate further if I encounter problems with this code. So, let's get started – tracing those calls and building the bigger picture. |
| 11/2 | 2026/09/21 14:24 | tool | grepper |
0mArgs:{
"Expression": "mm81x_yaps_hw_read_pkts",
"PathPrefix": "drivers/net/wireless/morsemicro/mm81x"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/yaps_hw.c=423=static int mm81x_read_pkts_h_bytes_remaining(struct mm81x_yaps *yaps)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-438-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:439:static int mm81x_yaps_hw_read_pkts(struct mm81x_yaps *yaps,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-440-\t\t\t\t struct mm81x_yaps_pkt *pkts,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c=644=static const struct mm81x_yaps_ops mm81x_yaps_hw_ops = {\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-645-\t.write_pkts = mm81x_yaps_hw_write_pkts,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:646:\t.read_pkts = mm81x_yaps_hw_read_pkts,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-647-\t.update_status = mm81x_yaps_hw_update_status,\n"
} |
| 12/2 | 2026/09/21 14:24 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 7275 output: 38 thoughts: 17 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Analyzing `read_pkts` Call Sites** Okay, so I need to understand the control flow around `read_pkts`. My first step, naturally, is to pinpoint *every* place that function is invoked within the driver. I need a comprehensive overview of how this function is integrated and what its purpose is within the broader data flow. This isn't just about finding the direct calls; I'm looking for indirect calls, calls within conditionals, calls within loops – the complete picture. I'm thinking of using my IDE's "find references" or "call hierarchy" functionality, but I might just go for a grep with some carefully crafted regex if that's easier given the codebase. Ultimately, I need to understand the execution paths leading to `read_pkts` to form a solid mental model of how it operates in the system. I have to keep in mind possible race conditions or other edge cases given how it's called. This will give me a basis to fully understanding any subsequent modifications, optimization or security considerations. |
| 13/2 | 2026/09/21 14:24 | tool | grepper |
0mArgs:{
"Expression": "read_pkts",
"PathPrefix": "drivers/net/wireless/morsemicro/mm81x"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/yaps.c=51=static int mm81x_yaps_write_pkts(struct mm81x_yaps *yaps,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-57-\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:58:static int mm81x_yaps_read_pkts(struct mm81x_yaps *yaps,\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-59-\t\t\t\tstruct mm81x_yaps_pkt *pkts, int num_pkts_max,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-61-{\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:62:\treturn yaps-\u003eops-\u003eread_pkts(yaps, pkts, num_pkts_max,\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-63-\t\t\t\t num_pkts_received);\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c=386=static bool mm81x_yaps_rx_handler(struct mm81x_yaps *yaps)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-395-\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:396:\tret = mm81x_yaps_read_pkts(yaps, yaps-\u003ehw.from_chip_pkts,\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-397-\t\t\t\t MAX_PKTS_PER_RX_TXN, \u0026num_pks_received);\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-398-\tif (ret \u0026\u0026 ret != -EAGAIN) {\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:399:\t\tdev_err(yaps-\u003emors-\u003edev, \"YAPS read_pkts fail: %d\", ret);\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-400-\t\tgoto exit;\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.h=59=struct mm81x_yaps_ops {\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.h-61-\t\t\t int num_pkts, int *num_pkts_sent);\ndrivers/net/wireless/morsemicro/mm81x/yaps.h:62:\tint (*read_pkts)(struct mm81x_yaps *yaps, struct mm81x_yaps_pkt *pkts,\ndrivers/net/wireless/morsemicro/mm81x/yaps.h-63-\t\t\t int num_pkts_max, int *num_pkts_received);\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c=308=static int mm81x_yaps_hw_write_pkts(struct mm81x_yaps *yaps,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-400-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:401:static bool mm81x_read_pkts_h_is_valid_delim(u32 delim)\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-402-{\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-422-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:423:static int mm81x_read_pkts_h_bytes_remaining(struct mm81x_yaps *yaps)\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-424-{\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-438-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:439:static int mm81x_yaps_hw_read_pkts(struct mm81x_yaps *yaps,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-440-\t\t\t\t struct mm81x_yaps_pkt *pkts,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-448-\tchar *read_ptr = from_chip_buffer_aligned;\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:449:\tint bytes_remaining = mm81x_read_pkts_h_bytes_remaining(yaps);\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-450-\tbool again = false;\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-499-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:500:\t\tif (!mm81x_read_pkts_h_is_valid_delim(delim)) {\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-501-\t\t\t/*\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c=566=static int mm81x_yaps_hw_update_status(struct mm81x_yaps *yaps)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-635-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:636:\tif (mm81x_read_pkts_h_bytes_remaining(yaps))\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-637-\t\tset_bit(MM81X_HIF_EVT_RX_PEND, \u0026yaps-\u003emors-\u003ehif.event_flags);\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c=644=static const struct mm81x_yaps_ops mm81x_yaps_hw_ops = {\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-645-\t.write_pkts = mm81x_yaps_hw_write_pkts,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:646:\t.read_pkts = mm81x_yaps_hw_read_pkts,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-647-\t.update_status = mm81x_yaps_hw_update_status,\n"
} |
| 14/2 | 2026/09/21 14:24 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 9381 output: 33 thoughts: 12 Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person: **Diving into the MM81X Kconfig** Alright, time to get my hands dirty. "Let's see Kconfig for MM81X." That's the starting point. I need to understand the configuration space for this particular MM81X, whatever that specific SoC or platform entails. I'm assuming, given my level of expertise, this is either a new project, an update to an existing one, or perhaps I'm troubleshooting some configuration issue. Either way, the Kconfig is the roadmap. I immediately start thinking about what I expect to find. What's the target architecture? Are we dealing with a standard ARM core, or something more specialized? Are there any obvious vendor-specific extensions or configurations I should be immediately looking out for? What's the general layout of the Kconfig likely to be? Common modules first? Specific board options? I'll probably be quickly scanning for any unusual or vendor-specific symbols that might hold the key to the hardware's unique features or potential quirks. I'm mentally parsing the likely structure, expecting to find sections for core CPU, memory management, peripherals, power management, and board-specific settings. The specific MM81X variant and its intended use case will likely dictate the organization and depth of this particular Kconfig. This is a crucial first step; I'm preparing my mental model of the configuration landscape. The journey begins. |
| 15/2 | 2026/09/21 14:24 | tool | grepper |
0mArgs:{
"Expression": "MM81X",
"PathPrefix": "drivers/net/wireless/morsemicro"
}Results: {
"Output": "\nFull output is too long, showing 500 out of 2202 lines.\nUse more precise expression if possible.\n\ndrivers/net/wireless/morsemicro/Makefile-1-# SPDX-License-Identifier: GPL-2.0\ndrivers/net/wireless/morsemicro/Makefile:2:obj-$(CONFIG_MM81X) += mm81x/\n--\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-2-\ndrivers/net/wireless/morsemicro/mm81x/Kconfig:3:config MM81X\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-4-\ttristate \"Morse Micro MM81x wireless devices\" if COMPILE_TEST\n--\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-11-\ndrivers/net/wireless/morsemicro/mm81x/Kconfig:12:config MM81X_USB\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-13-\ttristate \"Morse Micro MM81x USB support\"\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-14-\tdepends on MAC80211 \u0026\u0026 USB\ndrivers/net/wireless/morsemicro/mm81x/Kconfig:15:\tselect MM81X\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-16-\thelp\n--\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-19-\ndrivers/net/wireless/morsemicro/mm81x/Kconfig:20:config MM81X_SDIO\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-21-\ttristate \"Morse Micro MM81x SDIO support\"\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-22-\tdepends on MAC80211 \u0026\u0026 MMC\ndrivers/net/wireless/morsemicro/mm81x/Kconfig:23:\tselect MM81X\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-24-\thelp\n--\ndrivers/net/wireless/morsemicro/mm81x/Makefile-2-\ndrivers/net/wireless/morsemicro/mm81x/Makefile:3:obj-$(CONFIG_MM81X) += mm81x_core.o\ndrivers/net/wireless/morsemicro/mm81x/Makefile-4-\n--\ndrivers/net/wireless/morsemicro/mm81x/Makefile=15=mm81x_core-y += mmrc.o\ndrivers/net/wireless/morsemicro/mm81x/Makefile-16-\ndrivers/net/wireless/morsemicro/mm81x/Makefile:17:obj-$(CONFIG_MM81X_USB) += mm81x_usb.o\ndrivers/net/wireless/morsemicro/mm81x/Makefile-18-mm81x_usb-y += usb.o\ndrivers/net/wireless/morsemicro/mm81x/Makefile-19-\ndrivers/net/wireless/morsemicro/mm81x/Makefile:20:obj-$(CONFIG_MM81X_SDIO) += mm81x_sdio.o\ndrivers/net/wireless/morsemicro/mm81x/Makefile-21-mm81x_sdio-y += sdio.o\n--\ndrivers/net/wireless/morsemicro/mm81x/bus.h-5-\ndrivers/net/wireless/morsemicro/mm81x/bus.h:6:#ifndef _MM81X_BUS_H_\ndrivers/net/wireless/morsemicro/mm81x/bus.h:7:#define _MM81X_BUS_H_\ndrivers/net/wireless/morsemicro/mm81x/bus.h-8-\n--\ndrivers/net/wireless/morsemicro/mm81x/bus.h=12=enum mm81x_bus_type {\ndrivers/net/wireless/morsemicro/mm81x/bus.h:13:\tMM81X_BUS_TYPE_USB,\ndrivers/net/wireless/morsemicro/mm81x/bus.h:14:\tMM81X_BUS_TYPE_SDIO,\ndrivers/net/wireless/morsemicro/mm81x/bus.h-15-};\n--\ndrivers/net/wireless/morsemicro/mm81x/bus.h=17=struct mm81x_bus_ops {\n--\ndrivers/net/wireless/morsemicro/mm81x/bus.h-34- */\ndrivers/net/wireless/morsemicro/mm81x/bus.h:35:#define MM81X_BUS_DEFAULT_BULK_ALIGNMENT (2)\ndrivers/net/wireless/morsemicro/mm81x/bus.h-36-\n--\ndrivers/net/wireless/morsemicro/mm81x/bus.h=94=static inline unsigned int mm81x_bus_get_alignment(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/bus.h-98-\ndrivers/net/wireless/morsemicro/mm81x/bus.h:99:#endif /* !_MM81X_BUS_H_ */\n--\ndrivers/net/wireless/morsemicro/mm81x/command.c=33=static int mm81x_cmd_tx(struct mm81x *mors, struct host_cmd_resp *resp,\n--\ndrivers/net/wireless/morsemicro/mm81x/command.c-84-\t\tret = mm81x_skbq_skb_tx(cmd_q, \u0026skb, NULL,\ndrivers/net/wireless/morsemicro/mm81x/command.c:85:\t\t\t\t\tMM81X_SKB_CHAN_COMMAND);\ndrivers/net/wireless/morsemicro/mm81x/command.c-86-\t\tmutex_unlock(\u0026mors-\u003ecmd_lock);\n--\ndrivers/net/wireless/morsemicro/mm81x/command.c=324=int mm81x_cmd_hw_scan(struct mm81x *mors, struct mm81x_hw_scan_params *params,\n--\ndrivers/net/wireless/morsemicro/mm81x/command.c-343-\t\tflags = HOST_CMD_HW_SCAN_FLAGS_STORE;\ndrivers/net/wireless/morsemicro/mm81x/command.c:344:\telse if (params-\u003eoperation == MM81X_HW_SCAN_OP_START)\ndrivers/net/wireless/morsemicro/mm81x/command.c-345-\t\tflags |= HOST_CMD_HW_SCAN_FLAGS_START;\ndrivers/net/wireless/morsemicro/mm81x/command.c:346:\telse if (params-\u003eoperation == MM81X_HW_SCAN_OP_STOP)\ndrivers/net/wireless/morsemicro/mm81x/command.c-347-\t\tflags |= HOST_CMD_HW_SCAN_FLAGS_ABORT;\n--\ndrivers/net/wireless/morsemicro/mm81x/command.c-350-\ndrivers/net/wireless/morsemicro/mm81x/command.c:351:\tif (params-\u003eoperation == MM81X_HW_SCAN_OP_START) {\ndrivers/net/wireless/morsemicro/mm81x/command.c-352-\t\treq-\u003edwell_time_ms = cpu_to_le32(params-\u003edwell_time_ms);\n--\ndrivers/net/wireless/morsemicro/mm81x/command.h-5-\ndrivers/net/wireless/morsemicro/mm81x/command.h:6:#ifndef _MM81X_COMMAND_H_\ndrivers/net/wireless/morsemicro/mm81x/command.h:7:#define _MM81X_COMMAND_H_\ndrivers/net/wireless/morsemicro/mm81x/command.h-8-\n--\ndrivers/net/wireless/morsemicro/mm81x/command.h=21=enum mm81x_cmd_return_code {\ndrivers/net/wireless/morsemicro/mm81x/command.h:22:\tMM81X_RET_SUCCESS = 0,\ndrivers/net/wireless/morsemicro/mm81x/command.h:23:\tMM81X_RET_EPERM = -1,\ndrivers/net/wireless/morsemicro/mm81x/command.h:24:\tMM81X_RET_ENOMEM = -12,\ndrivers/net/wireless/morsemicro/mm81x/command.h:25:\tMM81X_RET_CMD_NOT_HANDLED = -32757,\ndrivers/net/wireless/morsemicro/mm81x/command.h-26-};\n--\ndrivers/net/wireless/morsemicro/mm81x/command.h=81=int mm81x_cmd_get_disabled_channels(\n--\ndrivers/net/wireless/morsemicro/mm81x/command.h-84-\ndrivers/net/wireless/morsemicro/mm81x/command.h:85:#endif /* !_MM81X_COMMAND_H_ */\n--\ndrivers/net/wireless/morsemicro/mm81x/command_defs.h-4- */\ndrivers/net/wireless/morsemicro/mm81x/command_defs.h:5:#ifndef _MM81X_COMMAND_DEFS_H_\ndrivers/net/wireless/morsemicro/mm81x/command_defs.h:6:#define _MM81X_COMMAND_DEFS_H_\ndrivers/net/wireless/morsemicro/mm81x/command_defs.h-7-\n--\ndrivers/net/wireless/morsemicro/mm81x/core.c=44=char *mm81x_core_get_fw_path(u32 chip_id, u32 fw_ver)\n--\ndrivers/net/wireless/morsemicro/mm81x/core.c-55-\ndrivers/net/wireless/morsemicro/mm81x/core.c:56:\treturn kasprintf(GFP_KERNEL, MM81X_FW_DIR \"/v%u/%s\" MM81X_FW_EXT,\ndrivers/net/wireless/morsemicro/mm81x/core.c-57-\t\t\t fw_ver, fw_base);\n--\ndrivers/net/wireless/morsemicro/mm81x/core.c=67=int mm81x_core_init(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/core.c-70-\ndrivers/net/wireless/morsemicro/mm81x/core.c:71:\tset_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags);\ndrivers/net/wireless/morsemicro/mm81x/core.c:72:\tset_bit(MM81X_STATE_RELOAD_FW_AFTER_START, \u0026mors-\u003estate_flags);\ndrivers/net/wireless/morsemicro/mm81x/core.c-73-\n--\ndrivers/net/wireless/morsemicro/mm81x/core.c=136=MODULE_AUTHOR(\"Morse Micro\");\ndrivers/net/wireless/morsemicro/mm81x/core.c:137:MODULE_DESCRIPTION(\"Driver support for Morse Micro MM81X core\");\ndrivers/net/wireless/morsemicro/mm81x/core.c-138-MODULE_LICENSE(\"Dual BSD/GPL\");\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-5-\ndrivers/net/wireless/morsemicro/mm81x/core.h:6:#ifndef _MM81X_CORE_H_\ndrivers/net/wireless/morsemicro/mm81x/core.h:7:#define _MM81X_CORE_H_\ndrivers/net/wireless/morsemicro/mm81x/core.h-8-\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-24-\ndrivers/net/wireless/morsemicro/mm81x/core.h:25:#define MM81X_DRIVER_SEMVER_MAJOR 56\ndrivers/net/wireless/morsemicro/mm81x/core.h:26:#define MM81X_DRIVER_SEMVER_MINOR 3\ndrivers/net/wireless/morsemicro/mm81x/core.h:27:#define MM81X_DRIVER_SEMVER_PATCH 0\ndrivers/net/wireless/morsemicro/mm81x/core.h-28-\ndrivers/net/wireless/morsemicro/mm81x/core.h:29:#define MM81X_SEMVER_GET_MAJOR(x) (((x) \u003e\u003e 22) \u0026 0x3FF)\ndrivers/net/wireless/morsemicro/mm81x/core.h:30:#define MM81X_SEMVER_GET_MINOR(x) (((x) \u003e\u003e 10) \u0026 0xFFF)\ndrivers/net/wireless/morsemicro/mm81x/core.h:31:#define MM81X_SEMVER_GET_PATCH(x) ((x) \u0026 0x3FF)\ndrivers/net/wireless/morsemicro/mm81x/core.h-32-\ndrivers/net/wireless/morsemicro/mm81x/core.h:33:#define DRV_VERSION __stringify(MM81X_VERSION)\ndrivers/net/wireless/morsemicro/mm81x/core.h-34-\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=56=struct mm81x_hif_ops;\ndrivers/net/wireless/morsemicro/mm81x/core.h-57-\ndrivers/net/wireless/morsemicro/mm81x/core.h:58:#define MM81X_CAPS_MAX_FW_VAL (128)\ndrivers/net/wireless/morsemicro/mm81x/core.h-59-\ndrivers/net/wireless/morsemicro/mm81x/core.h-60-/* Max number of interfaces */\ndrivers/net/wireless/morsemicro/mm81x/core.h:61:#define MM81X_MAX_IF (2)\ndrivers/net/wireless/morsemicro/mm81x/core.h-62-\ndrivers/net/wireless/morsemicro/mm81x/core.h=63=enum mm81x_caps_flags {\ndrivers/net/wireless/morsemicro/mm81x/core.h:64:\tMM81X_CAPS_FW_START = 0,\ndrivers/net/wireless/morsemicro/mm81x/core.h:65:\tMM81X_CAPS_2MHZ = MM81X_CAPS_FW_START,\ndrivers/net/wireless/morsemicro/mm81x/core.h:66:\tMM81X_CAPS_4MHZ,\ndrivers/net/wireless/morsemicro/mm81x/core.h:67:\tMM81X_CAPS_8MHZ,\ndrivers/net/wireless/morsemicro/mm81x/core.h:68:\tMM81X_CAPS_16MHZ,\ndrivers/net/wireless/morsemicro/mm81x/core.h:69:\tMM81X_CAPS_SGI,\ndrivers/net/wireless/morsemicro/mm81x/core.h:70:\tMM81X_CAPS_S1G_LONG,\ndrivers/net/wireless/morsemicro/mm81x/core.h:71:\tMM81X_CAPS_TRAVELING_PILOT_ONE_STREAM,\ndrivers/net/wireless/morsemicro/mm81x/core.h:72:\tMM81X_CAPS_TRAVELING_PILOT_TWO_STREAM,\ndrivers/net/wireless/morsemicro/mm81x/core.h:73:\tMM81X_CAPS_MU_BEAMFORMEE,\ndrivers/net/wireless/morsemicro/mm81x/core.h:74:\tMM81X_CAPS_MU_BEAMFORMER,\ndrivers/net/wireless/morsemicro/mm81x/core.h:75:\tMM81X_CAPS_RD_RESPONDER,\ndrivers/net/wireless/morsemicro/mm81x/core.h:76:\tMM81X_CAPS_STA_TYPE_SENSOR,\ndrivers/net/wireless/morsemicro/mm81x/core.h:77:\tMM81X_CAPS_STA_TYPE_NON_SENSOR,\ndrivers/net/wireless/morsemicro/mm81x/core.h:78:\tMM81X_CAPS_GROUP_AID,\ndrivers/net/wireless/morsemicro/mm81x/core.h:79:\tMM81X_CAPS_NON_TIM,\ndrivers/net/wireless/morsemicro/mm81x/core.h:80:\tMM81X_CAPS_TIM_ADE,\ndrivers/net/wireless/morsemicro/mm81x/core.h:81:\tMM81X_CAPS_BAT,\ndrivers/net/wireless/morsemicro/mm81x/core.h:82:\tMM81X_CAPS_DYNAMIC_AID,\ndrivers/net/wireless/morsemicro/mm81x/core.h:83:\tMM81X_CAPS_UPLINK_SYNC,\ndrivers/net/wireless/morsemicro/mm81x/core.h:84:\tMM81X_CAPS_FLOW_CONTROL,\ndrivers/net/wireless/morsemicro/mm81x/core.h:85:\tMM81X_CAPS_AMPDU,\ndrivers/net/wireless/morsemicro/mm81x/core.h:86:\tMM81X_CAPS_AMSDU,\ndrivers/net/wireless/morsemicro/mm81x/core.h:87:\tMM81X_CAPS_1MHZ_CONTROL_RESPONSE_PREAMBLE,\ndrivers/net/wireless/morsemicro/mm81x/core.h:88:\tMM81X_CAPS_PAGE_SLICING,\ndrivers/net/wireless/morsemicro/mm81x/core.h:89:\tMM81X_CAPS_RAW,\ndrivers/net/wireless/morsemicro/mm81x/core.h:90:\tMM81X_CAPS_MCS8,\ndrivers/net/wireless/morsemicro/mm81x/core.h:91:\tMM81X_CAPS_MCS9,\ndrivers/net/wireless/morsemicro/mm81x/core.h:92:\tMM81X_CAPS_ASYMMETRIC_BA_SUPPORT,\ndrivers/net/wireless/morsemicro/mm81x/core.h:93:\tMM81X_CAPS_DAC,\ndrivers/net/wireless/morsemicro/mm81x/core.h:94:\tMM81X_CAPS_CAC,\ndrivers/net/wireless/morsemicro/mm81x/core.h:95:\tMM81X_CAPS_TXOP_SHARING_IMPLICIT_ACK,\ndrivers/net/wireless/morsemicro/mm81x/core.h:96:\tMM81X_CAPS_NDP_PSPOLL,\ndrivers/net/wireless/morsemicro/mm81x/core.h:97:\tMM81X_CAPS_FRAGMENT_BA,\ndrivers/net/wireless/morsemicro/mm81x/core.h:98:\tMM81X_CAPS_OBSS_MITIGATION,\ndrivers/net/wireless/morsemicro/mm81x/core.h:99:\tMM81X_CAPS_TMP_PS_MODE_SWITCH,\ndrivers/net/wireless/morsemicro/mm81x/core.h:100:\tMM81X_CAPS_SECTOR_TRAINING,\ndrivers/net/wireless/morsemicro/mm81x/core.h:101:\tMM81X_CAPS_UNSOLICIT_DYNAMIC_AID,\ndrivers/net/wireless/morsemicro/mm81x/core.h:102:\tMM81X_CAPS_NDP_BEAMFORMING_REPORT,\ndrivers/net/wireless/morsemicro/mm81x/core.h:103:\tMM81X_CAPS_MCS_NEGOTIATION,\ndrivers/net/wireless/morsemicro/mm81x/core.h:104:\tMM81X_CAPS_DUPLICATE_1MHZ,\ndrivers/net/wireless/morsemicro/mm81x/core.h:105:\tMM81X_CAPS_TACK_AS_PSPOLL,\ndrivers/net/wireless/morsemicro/mm81x/core.h:106:\tMM81X_CAPS_PV1,\ndrivers/net/wireless/morsemicro/mm81x/core.h:107:\tMM81X_CAPS_TWT_RESPONDER,\ndrivers/net/wireless/morsemicro/mm81x/core.h:108:\tMM81X_CAPS_TWT_REQUESTER,\ndrivers/net/wireless/morsemicro/mm81x/core.h:109:\tMM81X_CAPS_BDT,\ndrivers/net/wireless/morsemicro/mm81x/core.h:110:\tMM81X_CAPS_TWT_GROUPING,\ndrivers/net/wireless/morsemicro/mm81x/core.h:111:\tMM81X_CAPS_LINK_ADAPTATION_WO_NDP_CMAC,\ndrivers/net/wireless/morsemicro/mm81x/core.h:112:\tMM81X_CAPS_LONG_MPDU,\ndrivers/net/wireless/morsemicro/mm81x/core.h:113:\tMM81X_CAPS_TXOP_SECTORIZATION,\ndrivers/net/wireless/morsemicro/mm81x/core.h:114:\tMM81X_CAPS_GROUP_SECTORIZATION,\ndrivers/net/wireless/morsemicro/mm81x/core.h:115:\tMM81X_CAPS_HTC_VHT,\ndrivers/net/wireless/morsemicro/mm81x/core.h:116:\tMM81X_CAPS_HTC_VHT_MFB,\ndrivers/net/wireless/morsemicro/mm81x/core.h:117:\tMM81X_CAPS_HTC_VHT_MRQ,\ndrivers/net/wireless/morsemicro/mm81x/core.h:118:\tMM81X_CAPS_2SS,\ndrivers/net/wireless/morsemicro/mm81x/core.h:119:\tMM81X_CAPS_3SS,\ndrivers/net/wireless/morsemicro/mm81x/core.h:120:\tMM81X_CAPS_4SS,\ndrivers/net/wireless/morsemicro/mm81x/core.h:121:\tMM81X_CAPS_SU_BEAMFORMEE,\ndrivers/net/wireless/morsemicro/mm81x/core.h:122:\tMM81X_CAPS_SU_BEAMFORMER,\ndrivers/net/wireless/morsemicro/mm81x/core.h:123:\tMM81X_CAPS_RX_STBC,\ndrivers/net/wireless/morsemicro/mm81x/core.h:124:\tMM81X_CAPS_TX_STBC,\ndrivers/net/wireless/morsemicro/mm81x/core.h:125:\tMM81X_CAPS_RX_LDPC,\ndrivers/net/wireless/morsemicro/mm81x/core.h:126:\tMM81X_CAPS_HW_FRAGMENT,\ndrivers/net/wireless/morsemicro/mm81x/core.h-127-\ndrivers/net/wireless/morsemicro/mm81x/core.h:128:\tMM81X_CAPS_FW_END = MM81X_CAPS_MAX_FW_VAL,\ndrivers/net/wireless/morsemicro/mm81x/core.h:129:\tMM81X_CAPS_LAST = MM81X_CAPS_FW_END,\ndrivers/net/wireless/morsemicro/mm81x/core.h-130-};\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=132=struct mm81x_fw_caps {\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-140-\ndrivers/net/wireless/morsemicro/mm81x/core.h:141:#define MM81X_FW_SUPP(MM81X_CAPS, CAPABILITY) \\\ndrivers/net/wireless/morsemicro/mm81x/core.h:142:\tmm81x_caps_supported(MM81X_CAPS, MM81X_CAPS_##CAPABILITY)\ndrivers/net/wireless/morsemicro/mm81x/core.h-143-\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=161=enum mm81x_page_aci {\ndrivers/net/wireless/morsemicro/mm81x/core.h:162:\tMM81X_ACI_BE = 0,\ndrivers/net/wireless/morsemicro/mm81x/core.h:163:\tMM81X_ACI_BK = 1,\ndrivers/net/wireless/morsemicro/mm81x/core.h:164:\tMM81X_ACI_VI = 2,\ndrivers/net/wireless/morsemicro/mm81x/core.h:165:\tMM81X_ACI_VO = 3,\ndrivers/net/wireless/morsemicro/mm81x/core.h-166-};\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=168=enum mm81x_qos_tid_up_index {\ndrivers/net/wireless/morsemicro/mm81x/core.h:169:\tMM81X_QOS_TID_UP_BK = 1,\ndrivers/net/wireless/morsemicro/mm81x/core.h:170:\tMM81X_QOS_TID_UP_XX = 2,\ndrivers/net/wireless/morsemicro/mm81x/core.h:171:\tMM81X_QOS_TID_UP_BE = 0,\ndrivers/net/wireless/morsemicro/mm81x/core.h:172:\tMM81X_QOS_TID_UP_EE = 3,\ndrivers/net/wireless/morsemicro/mm81x/core.h:173:\tMM81X_QOS_TID_UP_CL = 4,\ndrivers/net/wireless/morsemicro/mm81x/core.h:174:\tMM81X_QOS_TID_UP_VI = 5,\ndrivers/net/wireless/morsemicro/mm81x/core.h:175:\tMM81X_QOS_TID_UP_VO = 6,\ndrivers/net/wireless/morsemicro/mm81x/core.h:176:\tMM81X_QOS_TID_UP_NC = 7,\ndrivers/net/wireless/morsemicro/mm81x/core.h-177-\ndrivers/net/wireless/morsemicro/mm81x/core.h:178:\tMM81X_QOS_TID_UP_LOWEST = MM81X_QOS_TID_UP_BK,\ndrivers/net/wireless/morsemicro/mm81x/core.h:179:\tMM81X_QOS_TID_UP_HIGHEST = MM81X_QOS_TID_UP_NC\ndrivers/net/wireless/morsemicro/mm81x/core.h-180-};\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=233=enum mm81x_hw_scan_op {\ndrivers/net/wireless/morsemicro/mm81x/core.h:234:\tMM81X_HW_SCAN_OP_START,\ndrivers/net/wireless/morsemicro/mm81x/core.h:235:\tMM81X_HW_SCAN_OP_STOP,\ndrivers/net/wireless/morsemicro/mm81x/core.h-236-};\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=276=enum mm81x_hif_event_flags {\ndrivers/net/wireless/morsemicro/mm81x/core.h:277:\tMM81X_HIF_EVT_RX_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:278:\tMM81X_HIF_EVT_PAGE_RETURN_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:279:\tMM81X_HIF_EVT_TX_COMMAND_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:280:\tMM81X_HIF_EVT_TX_BEACON_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:281:\tMM81X_HIF_EVT_TX_MGMT_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:282:\tMM81X_HIF_EVT_TX_DATA_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:283:\tMM81X_HIF_EVT_TX_PACKET_FREED_UP_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:284:\tMM81X_HIF_EVT_DATA_TRAFFIC_PAUSE_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:285:\tMM81X_HIF_EVT_DATA_TRAFFIC_RESUME_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:286:\tMM81X_HIF_EVT_UPDATE_HW_CLOCK_REFERENCE,\ndrivers/net/wireless/morsemicro/mm81x/core.h-287-};\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=289=enum mm81x_state_flags {\ndrivers/net/wireless/morsemicro/mm81x/core.h:290:\tMM81X_STATE_CHIP_UNRESPONSIVE,\ndrivers/net/wireless/morsemicro/mm81x/core.h:291:\tMM81X_STATE_DATA_QS_STOPPED,\ndrivers/net/wireless/morsemicro/mm81x/core.h:292:\tMM81X_STATE_DATA_TX_STOPPED,\ndrivers/net/wireless/morsemicro/mm81x/core.h:293:\tMM81X_STATE_REGDOM_SET_BY_USER,\ndrivers/net/wireless/morsemicro/mm81x/core.h:294:\tMM81X_STATE_REGDOM_SET_BY_OTP,\ndrivers/net/wireless/morsemicro/mm81x/core.h:295:\tMM81X_STATE_RELOAD_FW_AFTER_START,\ndrivers/net/wireless/morsemicro/mm81x/core.h:296:\tMM81X_STATE_HOST_TO_CHIP_TX_BLOCKED,\ndrivers/net/wireless/morsemicro/mm81x/core.h:297:\tMM81X_STATE_HOST_TO_CHIP_CMD_BLOCKED,\ndrivers/net/wireless/morsemicro/mm81x/core.h-298-};\ndrivers/net/wireless/morsemicro/mm81x/core.h-299-\ndrivers/net/wireless/morsemicro/mm81x/core.h:300:#define MM81X_COUNTRY_LEN (3)\ndrivers/net/wireless/morsemicro/mm81x/core.h-301-#define INVALID_VIF_INDEX 0xFF\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=303=struct mm81x {\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-317-\tu8 macaddr[ETH_ALEN];\ndrivers/net/wireless/morsemicro/mm81x/core.h:318:\tu8 country[MM81X_COUNTRY_LEN];\ndrivers/net/wireless/morsemicro/mm81x/core.h-319-\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-330-\ndrivers/net/wireless/morsemicro/mm81x/core.h:331:\tstruct ieee80211_vif __rcu *vifs[MM81X_MAX_IF];\ndrivers/net/wireless/morsemicro/mm81x/core.h-332-\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=382=static inline u8 map_mac80211q_2_mm81x_aci(u16 mac80211queue)\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-385-\tcase IEEE80211_AC_VO:\ndrivers/net/wireless/morsemicro/mm81x/core.h:386:\t\treturn MM81X_ACI_VO;\ndrivers/net/wireless/morsemicro/mm81x/core.h-387-\tcase IEEE80211_AC_VI:\ndrivers/net/wireless/morsemicro/mm81x/core.h:388:\t\treturn MM81X_ACI_VI;\ndrivers/net/wireless/morsemicro/mm81x/core.h-389-\tcase IEEE80211_AC_BK:\ndrivers/net/wireless/morsemicro/mm81x/core.h:390:\t\treturn MM81X_ACI_BK;\ndrivers/net/wireless/morsemicro/mm81x/core.h-391-\tdefault:\ndrivers/net/wireless/morsemicro/mm81x/core.h:392:\t\treturn MM81X_ACI_BE;\ndrivers/net/wireless/morsemicro/mm81x/core.h-393-\t}\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=397=dot11_tid_to_ac(enum mm81x_qos_tid_up_index tid)\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-399-\tswitch (tid) {\ndrivers/net/wireless/morsemicro/mm81x/core.h:400:\tcase MM81X_QOS_TID_UP_BK:\ndrivers/net/wireless/morsemicro/mm81x/core.h:401:\tcase MM81X_QOS_TID_UP_XX:\ndrivers/net/wireless/morsemicro/mm81x/core.h:402:\t\treturn MM81X_ACI_BK;\ndrivers/net/wireless/morsemicro/mm81x/core.h:403:\tcase MM81X_QOS_TID_UP_CL:\ndrivers/net/wireless/morsemicro/mm81x/core.h:404:\tcase MM81X_QOS_TID_UP_VI:\ndrivers/net/wireless/morsemicro/mm81x/core.h:405:\t\treturn MM81X_ACI_VI;\ndrivers/net/wireless/morsemicro/mm81x/core.h:406:\tcase MM81X_QOS_TID_UP_VO:\ndrivers/net/wireless/morsemicro/mm81x/core.h:407:\tcase MM81X_QOS_TID_UP_NC:\ndrivers/net/wireless/morsemicro/mm81x/core.h:408:\t\treturn MM81X_ACI_VO;\ndrivers/net/wireless/morsemicro/mm81x/core.h:409:\tcase MM81X_QOS_TID_UP_BE:\ndrivers/net/wireless/morsemicro/mm81x/core.h:410:\tcase MM81X_QOS_TID_UP_EE:\ndrivers/net/wireless/morsemicro/mm81x/core.h-411-\tdefault:\ndrivers/net/wireless/morsemicro/mm81x/core.h:412:\t\treturn MM81X_ACI_BE;\ndrivers/net/wireless/morsemicro/mm81x/core.h-413-\t}\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=416=static inline bool mm81x_is_data_tx_allowed(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/core.h-417-{\ndrivers/net/wireless/morsemicro/mm81x/core.h:418:\treturn !test_bit(MM81X_STATE_DATA_TX_STOPPED, \u0026mors-\u003estate_flags) \u0026\u0026\ndrivers/net/wireless/morsemicro/mm81x/core.h:419:\t !test_bit(MM81X_HIF_EVT_DATA_TRAFFIC_PAUSE_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h-420-\t\t\t \u0026mors-\u003ehif.event_flags);\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=454=void mm81x_core_free(struct mm81x *mors);\ndrivers/net/wireless/morsemicro/mm81x/core.h-455-\ndrivers/net/wireless/morsemicro/mm81x/core.h:456:#endif /* !_MM81X_MM81X_H_ */\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=55=static void mm81x_fw_parse_info(struct mm81x *mors, const u8 *data, int length)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-61-\t\tswitch (le16_to_cpu(tlv-\u003etype)) {\ndrivers/net/wireless/morsemicro/mm81x/fw.c:62:\t\tcase MM81X_FW_INFO_TLV_BCF_ADDR:\ndrivers/net/wireless/morsemicro/mm81x/fw.c-63-\t\t\tmors-\u003ebcf_address = get_unaligned_le32(tlv-\u003eval);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=91=static int mm81x_fw_set_boot_addr(struct mm81x *mors, uint32_t addr)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-96-\tmm81x_claim_bus(mors);\ndrivers/net/wireless/morsemicro/mm81x/fw.c:97:\tstatus = mm81x_reg32_write(mors, MM81X_REG_BOOT_ADDR(mors), addr);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-98-\tmm81x_release_bus(mors);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=299=static void mm81x_fw_clear_aon(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-301-\tint idx;\ndrivers/net/wireless/morsemicro/mm81x/fw.c:302:\tu8 count = MM81X_REG_AON_COUNT(mors);\ndrivers/net/wireless/morsemicro/mm81x/fw.c:303:\tu32 address = MM81X_REG_AON_ADDR(mors);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-304-\ndrivers/net/wireless/morsemicro/mm81x/fw.c-305-\tfor (idx = 0; idx \u003c count; idx++, address += 4) {\ndrivers/net/wireless/morsemicro/mm81x/fw.c:306:\t\tif (mors-\u003ebus_type == MM81X_BUS_TYPE_USB \u0026\u0026 idx == 0)\ndrivers/net/wireless/morsemicro/mm81x/fw.c-307-\t\t\t/* Keep the USB power domain enabled in AON. */\ndrivers/net/wireless/morsemicro/mm81x/fw.c-308-\t\t\tmm81x_reg32_write(mors, address,\ndrivers/net/wireless/morsemicro/mm81x/fw.c:309:\t\t\t\t\t MM81X_REG_AON_USB_RESET(mors));\ndrivers/net/wireless/morsemicro/mm81x/fw.c-310-\t\telse\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=318=static void mm81x_fw_trigger(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-328-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:329:\tif (MM81X_REG_CLK_CTRL(mors))\ndrivers/net/wireless/morsemicro/mm81x/fw.c:330:\t\tmm81x_reg32_write(mors, MM81X_REG_CLK_CTRL(mors),\ndrivers/net/wireless/morsemicro/mm81x/fw.c:331:\t\t\t\t MM81X_REG_CLK_CTRL_VALUE(mors));\ndrivers/net/wireless/morsemicro/mm81x/fw.c-332-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:333:\tmm81x_reg32_write(mors, MM81X_REG_MSI(mors),\ndrivers/net/wireless/morsemicro/mm81x/fw.c:334:\t\t\t MM81X_REG_MSI_HOST_INT(mors));\ndrivers/net/wireless/morsemicro/mm81x/fw.c-335-\tmm81x_release_bus(mors);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=341=static int mm81x_fw_verify_magic(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-343-\tint ret = 0;\ndrivers/net/wireless/morsemicro/mm81x/fw.c:344:\tint magic = ~MM81X_REG_HOST_MAGIC_VALUE(mors);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-345-\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-351-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:352:\tif (magic != MM81X_REG_HOST_MAGIC_VALUE(mors)) {\ndrivers/net/wireless/morsemicro/mm81x/fw.c-353-\t\tdev_err(mors-\u003edev, \"FW magic mismatch 0x%08x:0x%08x\",\ndrivers/net/wireless/morsemicro/mm81x/fw.c:354:\t\t\tMM81X_REG_HOST_MAGIC_VALUE(mors), magic);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-355-\t\tret = -EIO;\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=378=static int mm81x_fw_check_compatibility(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-393-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:394:\tmajor = MM81X_SEMVER_GET_MAJOR(fw_version);\ndrivers/net/wireless/morsemicro/mm81x/fw.c:395:\tminor = MM81X_SEMVER_GET_MINOR(fw_version);\ndrivers/net/wireless/morsemicro/mm81x/fw.c:396:\tpatch = MM81X_SEMVER_GET_PATCH(fw_version);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-397-\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=420=static int mm81x_fw_invalidate_host_ptr(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-425-\tmm81x_claim_bus(mors);\ndrivers/net/wireless/morsemicro/mm81x/fw.c:426:\tret = mm81x_reg32_write(mors, MM81X_REG_HOST_MANIFEST_PTR(mors), 0);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-427-\tmm81x_release_bus(mors);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=431=static int mm81x_fw_get_host_table_ptr(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-439-\t\t\t\tHOST_TABLE_PTR_POLL_TIMEOUT_US, false, mors,\ndrivers/net/wireless/morsemicro/mm81x/fw.c:440:\t\t\t\tMM81X_REG_HOST_MANIFEST_PTR(mors),\ndrivers/net/wireless/morsemicro/mm81x/fw.c-441-\t\t\t\t\u0026mors-\u003ehost_table_ptr);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=546=int mm81x_fw_parse_ext_host_tbl(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-566-\t\tswitch (le16_to_cpu(hdr-\u003etag)) {\ndrivers/net/wireless/morsemicro/mm81x/fw.c:567:\t\tcase MM81X_FW_HOST_TABLE_TAG_S1G_CAPABILITIES:\ndrivers/net/wireless/morsemicro/mm81x/fw.c-568-\t\t\tmm81x_fw_update_capabilities(\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-571-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:572:\t\tcase MM81X_FW_HOST_TABLE_TAG_INSERT_SKB_CHECKSUM:\ndrivers/net/wireless/morsemicro/mm81x/fw.c-573-\t\t\tmm81x_fw_update_validate_skb_checksum(\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-577-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:578:\t\tcase MM81X_FW_HOST_TABLE_TAG_YAPS_TABLE:\ndrivers/net/wireless/morsemicro/mm81x/fw.c-579-\t\t\tmm81x_yaps_hw_read_table(\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=661=static int mm81x_fw_request(struct mm81x *mors, const struct firmware **fw)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-666-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:667:\tfor (ver = MM81X_FW_VER_MAX; ver \u003e= MM81X_FW_VER_MIN; ver--) {\ndrivers/net/wireless/morsemicro/mm81x/fw.c-668-\t\tfw_path = mm81x_core_get_fw_path(mors-\u003echip_id, ver);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-686-\tdev_err(mors-\u003edev, \"no firmware found (tried v%d down to v%d): %d\\n\",\ndrivers/net/wireless/morsemicro/mm81x/fw.c:687:\t\tMM81X_FW_VER_MAX, MM81X_FW_VER_MIN, ret);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-688-\treturn ret;\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=691=int mm81x_fw_init(struct mm81x *mors, bool reset)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-714-\tbcf_path = kasprintf(GFP_KERNEL,\ndrivers/net/wireless/morsemicro/mm81x/fw.c:715:\t\t\t MM81X_FW_DIR\ndrivers/net/wireless/morsemicro/mm81x/fw.c:716:\t\t\t \"/v%u/bcf_boardtype_%04x\" MM81X_FW_EXT,\ndrivers/net/wireless/morsemicro/mm81x/fw.c-717-\t\t\t mors-\u003efw_major, board_id);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.h-5-\ndrivers/net/wireless/morsemicro/mm81x/fw.h:6:#ifndef _MM81X_FW_H_\ndrivers/net/wireless/morsemicro/mm81x/fw.h:7:#define _MM81X_FW_H_\ndrivers/net/wireless/morsemicro/mm81x/fw.h-8-\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.h-15-#define BCF_DATABASE_SIZE (1024)\ndrivers/net/wireless/morsemicro/mm81x/fw.h:16:#define MM81X_FW_DIR \"morsemicro/mm81x\"\ndrivers/net/wireless/morsemicro/mm81x/fw.h:17:#define MM81X_FW_EXT \".bin\"\ndrivers/net/wireless/morsemicro/mm81x/fw.h-18-\ndrivers/net/wireless/morsemicro/mm81x/fw.h:19:#define MM81X_FW_VER_MAX HOST_CMD_SEMVER_MAJOR\ndrivers/net/wireless/morsemicro/mm81x/fw.h:20:#define MM81X_FW_VER_MIN 56\ndrivers/net/wireless/morsemicro/mm81x/fw.h-21-\ndrivers/net/wireless/morsemicro/mm81x/fw.h:22:/* FW_CAPABILITIES_FLAGS_WIDTH = ceil(MM81X_CAPS_MAX_HW_LEN / 32) */\ndrivers/net/wireless/morsemicro/mm81x/fw.h-23-#define FW_CAPABILITIES_FLAGS_WIDTH (4)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.h=66=enum mm81x_fw_info_tlv_type {\ndrivers/net/wireless/morsemicro/mm81x/fw.h:67:\tMM81X_FW_INFO_TLV_BCF_ADDR = 1,\ndrivers/net/wireless/morsemicro/mm81x/fw.h-68-};\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.h=76=enum mm81x_fw_ext_host_tbl_tag {\ndrivers/net/wireless/morsemicro/mm81x/fw.h-77-\t/* The S1G capability tag */\ndrivers/net/wireless/morsemicro/mm81x/fw.h:78:\tMM81X_FW_HOST_TABLE_TAG_S1G_CAPABILITIES = 0,\ndrivers/net/wireless/morsemicro/mm81x/fw.h:79:\tMM81X_FW_HOST_TABLE_TAG_PAGER_BYPASS_TX_STATUS = 1,\ndrivers/net/wireless/morsemicro/mm81x/fw.h:80:\tMM81X_FW_HOST_TABLE_TAG_INSERT_SKB_CHECKSUM = 2,\ndrivers/net/wireless/morsemicro/mm81x/fw.h:81:\tMM81X_FW_HOST_TABLE_TAG_YAPS_TABLE = 3,\ndrivers/net/wireless/morsemicro/mm81x/fw.h:82:\tMM81X_FW_HOST_TABLE_TAG_PAGER_PKT_MEMORY = 4,\ndrivers/net/wireless/morsemicro/mm81x/fw.h:83:\tMM81X_FW_HOST_TABLE_TAG_PAGER_BYPASS_CMD_RESP = 5,\ndrivers/net/wireless/morsemicro/mm81x/fw.h-84-};\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.h=141=int mm81x_fw_parse_ext_host_tbl(struct mm81x *mors);\ndrivers/net/wireless/morsemicro/mm81x/fw.h-142-\ndrivers/net/wireless/morsemicro/mm81x/fw.h:143:#endif /* !_MM81X_FW_H_ */\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h-5-\ndrivers/net/wireless/morsemicro/mm81x/hif.h:6:#ifndef _MM81X_HIF_H_\ndrivers/net/wireless/morsemicro/mm81x/hif.h:7:#define _MM81X_HIF_H_\ndrivers/net/wireless/morsemicro/mm81x/hif.h-8-\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=11=struct mm81x_skbq;\ndrivers/net/wireless/morsemicro/mm81x/hif.h-12-\ndrivers/net/wireless/morsemicro/mm81x/hif.h:13:#define MM81X_HIF_BYPASS_TX_STATUS_IRQ_NUM (15)\ndrivers/net/wireless/morsemicro/mm81x/hif.h:14:#define MM81X_HIF_BYPASS_CMD_RESP_IRQ_NUM (29)\ndrivers/net/wireless/morsemicro/mm81x/hif.h:15:#define MM81X_HIF_IRQ_BYPASS_TX_STATUS_AVAILABLE \\\ndrivers/net/wireless/morsemicro/mm81x/hif.h:16:\tBIT(MM81X_HIF_BYPASS_TX_STATUS_IRQ_NUM)\ndrivers/net/wireless/morsemicro/mm81x/hif.h:17:#define MM81X_HIF_IRQ_BYPASS_CMD_RESP_AVAILABLE \\\ndrivers/net/wireless/morsemicro/mm81x/hif.h:18:\tBIT(MM81X_HIF_BYPASS_CMD_RESP_IRQ_NUM)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-19-\ndrivers/net/wireless/morsemicro/mm81x/hif.h-20-/* Hardware IF interrupt mask. We may use any interrupts in this range */\ndrivers/net/wireless/morsemicro/mm81x/hif.h:21:#define MM81X_HIF_IRQ_MASK_ALL \\\ndrivers/net/wireless/morsemicro/mm81x/hif.h:22:\t(GENMASK(13, 0) | MM81X_HIF_IRQ_BYPASS_TX_STATUS_AVAILABLE | \\\ndrivers/net/wireless/morsemicro/mm81x/hif.h:23:\t MM81X_HIF_IRQ_BYPASS_CMD_RESP_AVAILABLE)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-24-\ndrivers/net/wireless/morsemicro/mm81x/hif.h=25=enum mm81x_hif_flags {\ndrivers/net/wireless/morsemicro/mm81x/hif.h:26:\tMM81X_HIF_FLAGS_DIR_TO_HOST = BIT(0),\ndrivers/net/wireless/morsemicro/mm81x/hif.h:27:\tMM81X_HIF_FLAGS_DIR_TO_CHIP = BIT(1),\ndrivers/net/wireless/morsemicro/mm81x/hif.h:28:\tMM81X_HIF_FLAGS_COMMAND = BIT(2),\ndrivers/net/wireless/morsemicro/mm81x/hif.h:29:\tMM81X_HIF_FLAGS_BEACON = BIT(3),\ndrivers/net/wireless/morsemicro/mm81x/hif.h:30:\tMM81X_HIF_FLAGS_DATA = BIT(4)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-31-};\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=112=static inline int mm81x_hif_get_tx_status_pending_count(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h-116-\ndrivers/net/wireless/morsemicro/mm81x/hif.h:117:#endif /* _MM81X_HIF_H_ */\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.c-54-\ndrivers/net/wireless/morsemicro/mm81x/hw.c:55:#define MM81X_OTP_MAC_ADDR_2_BANK_NUM 27\ndrivers/net/wireless/morsemicro/mm81x/hw.c:56:#define MM81X_OTP_MAC_ADDR_1_BANK_NUM 26\ndrivers/net/wireless/morsemicro/mm81x/hw.c:57:#define MM81X_OTP_MAC_ADDR_1_MASK GENMASK(31, 16)\ndrivers/net/wireless/morsemicro/mm81x/hw.c:58:#define MM81X_OTP_BOARD_TYPE_BANK_NUM 26\ndrivers/net/wireless/morsemicro/mm81x/hw.c:59:#define MM81X_OTP_BOARD_TYPE_MASK GENMASK(15, 0)\ndrivers/net/wireless/morsemicro/mm81x/hw.c-60-\ndrivers/net/wireless/morsemicro/mm81x/hw.c:61:#define MM810X_BOARD_TYPE_MAX_VALUE (MM81X_OTP_BOARD_TYPE_MASK - 1)\ndrivers/net/wireless/morsemicro/mm81x/hw.c-62-\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.c=128=int mm81x_hw_otp_get_board_type(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.c-137-\ndrivers/net/wireless/morsemicro/mm81x/hw.c:138:\tret = mm81x_hw_otp_read(mors, MM81X_OTP_BOARD_TYPE_BANK_NUM, \u0026otp_word,\ndrivers/net/wireless/morsemicro/mm81x/hw.c-139-\t\t\t\t1);\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.c-147-\ndrivers/net/wireless/morsemicro/mm81x/hw.c:148:\tboard_type = otp_word \u0026 MM81X_OTP_BOARD_TYPE_MASK;\ndrivers/net/wireless/morsemicro/mm81x/hw.c-149-\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.c=158=int mm81x_hw_otp_get_mac_addr(struct mm81x *mors)\n--\n\n"
} |
| 16/2 | 2026/09/21 14:24 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 25387 output: 32 thoughts: 45 Thoughts: Okay, let's dive into this. I need to understand how this Morse Micro Wi-Fi module, specifically the MM81x, integrates with the USB subsystem. My immediate thought is to examine `drivers/net/wireless/morsemicro/mm81x/usb.c`. This is the logical place to start – it should reveal the USB driver registration process. I need to see how the system identifies the device, the driver's entry points, and the overall initialization sequence. Specifically, I want to nail down whether this driver is firmware-dependent *before* it starts handling any network traffic. Knowing this will give me a critical understanding of the boot process and potential dependencies. Firmware loading can have implications for power-on sequencing, error handling, and even debugging – all crucial aspects for reliable operation. I need to determine the extent of its dependency on external code to ensure my system is robust. |
| 17/2 | 2026/09/21 14:24 | tool | grepper |
0mError:no matches Args: {
"Expression": "usb_register",
"PathPrefix": "drivers/net/wireless/morsemicro"
}Results: {
"error": "no matches"
} |
| 18/2 | 2026/09/21 14:24 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 25666 output: 46 thoughts: 27 Thoughts: Okay, here's my interpretation of that thought process, assuming I'm a seasoned expert diving into some embedded systems code: **Diving into the mm81x USB Driver** Alright, time to get my hands dirty. I need to get to the core of this driver for that specific Morse Micro wireless chip, the mm81x, specifically its USB interface. So, let's cut to the chase and head straight to the very end of the `drivers/net/wireless/morsemicro/mm81x/usb.c` file. This is usually where you find the end-of-file notes; maybe I can refresh my memory on the important functions and data structures. It's often the quickest way to get a bird's-eye view of how this thing is structured. I'm hoping I can refresh my memory on how this all fits together. |
| 19/2 | 2026/09/21 14:25 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/usb.c",
"FirstLine": 600,
"LineCount": 80
}Results: {
"Contents": " 600:\t\t\t} else if (usb_endpoint_is_bulk_out(ep_desc)) {\n 601:\t\t\t\tif (!musb-\u003eendpoints[MM81X_EP_MEM_WR].addr) {\n 602:\t\t\t\t\tmusb-\u003eendpoints[MM81X_EP_MEM_WR].addr =\n 603:\t\t\t\t\t\tusb_endpoint_num(ep_desc);\n 604:\t\t\t\t\tmusb-\u003eendpoints[MM81X_EP_MEM_WR].size =\n 605:\t\t\t\t\t\tusb_endpoint_maxp(ep_desc);\n 606:\t\t\t\t} else if (!musb-\u003eendpoints[MM81X_EP_REG_WR].addr) {\n 607:\t\t\t\t\tmusb-\u003eendpoints[MM81X_EP_REG_WR].addr =\n 608:\t\t\t\t\t\tusb_endpoint_num(ep_desc);\n 609:\t\t\t\t\tmusb-\u003eendpoints[MM81X_EP_REG_WR].size =\n 610:\t\t\t\t\t\tusb_endpoint_maxp(ep_desc);\n 611:\t\t\t\t}\n 612:\t\t\t} else if (usb_endpoint_is_int_in(ep_desc)) {\n 613:\t\t\t\tmusb-\u003eendpoints[MM81X_EP_INT].addr =\n 614:\t\t\t\t\tusb_endpoint_num(ep_desc);\n 615:\t\t\t\tmusb-\u003eendpoints[MM81X_EP_INT].size =\n 616:\t\t\t\t\tusb_endpoint_maxp(ep_desc);\n 617:\t\t\t}\n 618:\t\t}\n 619:\t\n 620:\t\tdev_dbg(mors-\u003edev, \"\\tMemory Endpoint IN %s detected: %u size %u\",\n 621:\t\t\tmusb-\u003eendpoints[MM81X_EP_MEM_RD].addr ? \"\" : \"not\",\n 622:\t\t\tmusb-\u003eendpoints[MM81X_EP_MEM_RD].addr,\n 623:\t\t\tmusb-\u003eendpoints[MM81X_EP_MEM_RD].size);\n 624:\t\tdev_dbg(mors-\u003edev, \"\\tMemory Endpoint OUT %s detected: %u size %u\",\n 625:\t\t\tmusb-\u003eendpoints[MM81X_EP_MEM_WR].addr ? \"\" : \"not\",\n 626:\t\t\tmusb-\u003eendpoints[MM81X_EP_MEM_WR].addr,\n 627:\t\t\tmusb-\u003eendpoints[MM81X_EP_MEM_WR].size);\n 628:\t\tdev_dbg(mors-\u003edev, \"\\tRegister Endpoint IN %s detected: %u\",\n 629:\t\t\tmusb-\u003eendpoints[MM81X_EP_REG_RD].addr ? \"\" : \"not\",\n 630:\t\t\tmusb-\u003eendpoints[MM81X_EP_REG_RD].addr);\n 631:\t\tdev_dbg(mors-\u003edev, \"\\tRegister Endpoint OUT %s detected: %u\",\n 632:\t\t\tmusb-\u003eendpoints[MM81X_EP_REG_WR].addr ? \"\" : \"not\",\n 633:\t\t\tmusb-\u003eendpoints[MM81X_EP_REG_WR].addr);\n 634:\t\tdev_dbg(mors-\u003edev, \"\\tStats IN endpoint %s detected: %u\",\n 635:\t\t\tmusb-\u003eendpoints[MM81X_EP_INT].addr ? \"\" : \"not\",\n 636:\t\t\tmusb-\u003eendpoints[MM81X_EP_INT].addr);\n 637:\t\n 638:\t\t/* Verify we have an IN and OUT */\n 639:\t\tif (!(musb-\u003eendpoints[MM81X_EP_MEM_RD].addr \u0026\u0026\n 640:\t\t musb-\u003eendpoints[MM81X_EP_MEM_WR].addr))\n 641:\t\t\treturn -ENODEV;\n 642:\t\n 643:\t\t/* Verify the stats MM81X_EP_INT is detected */\n 644:\t\tif (!musb-\u003eendpoints[MM81X_EP_INT].addr)\n 645:\t\t\treturn -ENODEV;\n 646:\t\n 647:\t\t/* Verify minimum interrupt status read */\n 648:\t\tif (musb-\u003eendpoints[MM81X_EP_INT].size \u003c 8)\n 649:\t\t\treturn -ENODEV;\n 650:\t\n 651:\t\tmusb-\u003eendpoints[MM81X_EP_CMD].urb = usb_alloc_urb(0, GFP_KERNEL);\n 652:\t\tif (!musb-\u003eendpoints[MM81X_EP_CMD].urb) {\n 653:\t\t\tret = -ENOMEM;\n 654:\t\t\tgoto err_ep;\n 655:\t\t}\n 656:\t\n 657:\t\tmusb-\u003eendpoints[MM81X_EP_MEM_RD].urb = usb_alloc_urb(0, GFP_KERNEL);\n 658:\t\tif (!musb-\u003eendpoints[MM81X_EP_MEM_RD].urb) {\n 659:\t\t\tret = -ENOMEM;\n 660:\t\t\tgoto err_ep;\n 661:\t\t}\n 662:\t\n 663:\t\tmusb-\u003eendpoints[MM81X_EP_MEM_WR].urb = usb_alloc_urb(0, GFP_KERNEL);\n 664:\t\tif (!musb-\u003eendpoints[MM81X_EP_MEM_WR].urb) {\n 665:\t\t\tret = -ENOMEM;\n 666:\t\t\tgoto err_ep;\n 667:\t\t}\n 668:\t\n 669:\t\tmusb-\u003eendpoints[MM81X_EP_MEM_RD].buffer =\n 670:\t\t\tkmalloc(USB_MAX_TRANSFER_SIZE, GFP_KERNEL);\n 671:\t\tif (!musb-\u003eendpoints[MM81X_EP_MEM_RD].buffer) {\n 672:\t\t\tret = -ENOMEM;\n 673:\t\t\tgoto err_ep;\n 674:\t\t}\n 675:\t\n 676:\t\tmusb-\u003eendpoints[MM81X_EP_MEM_WR].buffer =\n 677:\t\t\tkmalloc(USB_MAX_TRANSFER_SIZE, GFP_KERNEL);\n 678:\t\tif (!musb-\u003eendpoints[MM81X_EP_MEM_WR].buffer) {\n 679:\t\t\tret = -ENOMEM;\n"
} |
| 20/2 | 2026/09/21 14:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 27541 output: 46 thoughts: 12 Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person: **Diving Back into `usb.c`** Alright, so the task at hand involves revisiting the `usb.c` source code. My immediate thought is, "Let's get back to the core of the matter." I need to get a better overview of this file's structure. Understanding the full picture of the `usb.c` file is key. I'll need to re-familiarize myself with the intricate details and how they interact to support the overall USB subsystem. What are the key data structures? How is the interrupt handling implemented? What are the key functions, and what is the typical control flow? I have a feeling there might be a subtle nuance that I'm overlooking, and that can be found in the rest of this file. So, let's jump in. |
| 21/2 | 2026/09/21 14:25 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/usb.c",
"FirstLine": 680,
"LineCount": 80
}Results: {
"Contents": " 680:\t\t\tgoto err_ep;\n 681:\t\t}\n 682:\t\n 683:\t\tmusb-\u003eendpoints[MM81X_EP_CMD].buffer = usb_alloc_coherent(\n 684:\t\t\tmusb-\u003eudev, sizeof(struct mm81x_usb_command), GFP_KERNEL,\n 685:\t\t\t\u0026musb-\u003eendpoints[MM81X_EP_CMD].urb-\u003etransfer_dma);\n 686:\t\n 687:\t\tif (!musb-\u003eendpoints[MM81X_EP_CMD].buffer) {\n 688:\t\t\tret = -ENOMEM;\n 689:\t\t\tgoto err_ep;\n 690:\t\t}\n 691:\t\n 692:\t\t/* Assign command to memory out end point */\n 693:\t\tmusb-\u003eendpoints[MM81X_EP_CMD].addr =\n 694:\t\t\tmusb-\u003eendpoints[MM81X_EP_MEM_WR].addr;\n 695:\t\tmusb-\u003eendpoints[MM81X_EP_CMD].size =\n 696:\t\t\tmusb-\u003eendpoints[MM81X_EP_MEM_WR].size;\n 697:\t\n 698:\t\treturn 0;\n 699:\t\n 700:\terr_ep:\n 701:\t\tif (musb-\u003eendpoints[MM81X_EP_CMD].urb \u0026\u0026\n 702:\t\t musb-\u003eendpoints[MM81X_EP_CMD].buffer)\n 703:\t\t\tusb_free_coherent(\n 704:\t\t\t\tmusb-\u003eudev, sizeof(struct mm81x_usb_command),\n 705:\t\t\t\tmusb-\u003eendpoints[MM81X_EP_CMD].buffer,\n 706:\t\t\t\tmusb-\u003eendpoints[MM81X_EP_CMD].urb-\u003etransfer_dma);\n 707:\t\tusb_free_urb(musb-\u003eendpoints[MM81X_EP_MEM_RD].urb);\n 708:\t\tusb_free_urb(musb-\u003eendpoints[MM81X_EP_CMD].urb);\n 709:\t\tusb_free_urb(musb-\u003eendpoints[MM81X_EP_MEM_WR].urb);\n 710:\t\tkfree(musb-\u003eendpoints[MM81X_EP_MEM_RD].buffer);\n 711:\t\tkfree(musb-\u003eendpoints[MM81X_EP_MEM_WR].buffer);\n 712:\t\n 713:\t\treturn ret;\n 714:\t}\n 715:\t\n 716:\tstatic void mm81x_urb_cleanup(struct mm81x *mors)\n 717:\t{\n 718:\t\tstruct mm81x_usb *musb = (struct mm81x_usb *)mors-\u003edrv_priv;\n 719:\t\tstruct mm81x_usb_endpoint *int_ep = \u0026musb-\u003eendpoints[MM81X_EP_INT];\n 720:\t\tstruct mm81x_usb_endpoint *rd_ep = \u0026musb-\u003eendpoints[MM81X_EP_MEM_RD];\n 721:\t\tstruct mm81x_usb_endpoint *wr_ep = \u0026musb-\u003eendpoints[MM81X_EP_MEM_WR];\n 722:\t\tstruct mm81x_usb_endpoint *cmd_ep = \u0026musb-\u003eendpoints[MM81X_EP_CMD];\n 723:\t\n 724:\t\tusb_kill_urb(rd_ep-\u003eurb);\n 725:\t\tusb_kill_urb(wr_ep-\u003eurb);\n 726:\t\tusb_kill_urb(cmd_ep-\u003eurb);\n 727:\t\n 728:\t\tif (int_ep-\u003eurb)\n 729:\t\t\tusb_free_coherent(musb-\u003eudev, MM81X_EP_INT_BUFFER_SIZE,\n 730:\t\t\t\t\t int_ep-\u003ebuffer, int_ep-\u003eurb-\u003etransfer_dma);\n 731:\t\n 732:\t\tif (cmd_ep-\u003eurb)\n 733:\t\t\tusb_free_coherent(musb-\u003eudev, sizeof(struct mm81x_usb_command),\n 734:\t\t\t\t\t cmd_ep-\u003ebuffer, cmd_ep-\u003eurb-\u003etransfer_dma);\n 735:\t\n 736:\t\tkfree(wr_ep-\u003ebuffer);\n 737:\t\tkfree(rd_ep-\u003ebuffer);\n 738:\t\n 739:\t\tusb_free_urb(int_ep-\u003eurb);\n 740:\t\tusb_free_urb(wr_ep-\u003eurb);\n 741:\t\tusb_free_urb(rd_ep-\u003eurb);\n 742:\t\tusb_free_urb(cmd_ep-\u003eurb);\n 743:\t}\n 744:\t\n 745:\tstatic int mm81x_usb_probe(struct usb_interface *interface,\n 746:\t\t\t\t const struct usb_device_id *id)\n 747:\t{\n 748:\t\tint ret;\n 749:\t\tstruct mm81x *mors;\n 750:\t\tstruct mm81x_usb *musb;\n 751:\t\n 752:\t\tmors = mm81x_core_alloc(sizeof(*musb), \u0026interface-\u003edev);\n 753:\t\tif (!mors)\n 754:\t\t\treturn -ENOMEM;\n 755:\t\n 756:\t\tmors-\u003ebus_ops = \u0026mm81x_usb_ops;\n 757:\t\tmors-\u003ebus_type = MM81X_BUS_TYPE_USB;\n 758:\t\n 759:\t\tmusb = (struct mm81x_usb *)mors-\u003edrv_priv;\n"
} |
| 22/2 | 2026/09/21 14:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 29274 output: 46 thoughts: 15 Thoughts: Okay, here's my attempt at summarizing the thought process, as requested, in the first person and targeted at an expert: **Diving Back into `mm81x_usb_probe`** Alright, let's get back to this `mm81x_usb_probe` function. I remember we were looking at it earlier, so it's time to refresh my memory and maybe dig a little deeper. I need to understand what it's *really* doing – the key initialization steps, any resource allocation, and, of course, how it interacts with the USB subsystem. I'm thinking about the standard probe flow... Is it checking for the device's capabilities, setting up any necessary endpoints, handling power management, and probably registering the driver with the USB core? I'll need to look for any unusual quirks specific to this `mm81x` family – specific register settings, any custom USB descriptors, or anything else that might be outside of the typical USB driver pattern. I also need to check for the error handling – where are the checks and any potential fallback mechanisms? Are there robust error paths, or am I going to find some silent failures that could lead to intermittent issues down the line? It's essential to understand the potential failure scenarios and how the driver deals with them. I'll be keeping an eye out for how this device integrates with the USB stack, how interrupts are handled and whether they're properly synchronized. Let's hope there are no obscure locking strategies. |
| 23/2 | 2026/09/21 14:25 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/usb.c",
"FirstLine": 760,
"LineCount": 80
}Results: {
"Contents": " 760:\t\tmusb-\u003eudev = usb_get_dev(interface_to_usbdev(interface));\n 761:\t\tmusb-\u003einterface = usb_get_intf(interface);\n 762:\t\n 763:\t\tmutex_init(\u0026musb-\u003elock);\n 764:\t\tmutex_init(\u0026musb-\u003ebus_lock);\n 765:\t\tinit_waitqueue_head(\u0026musb-\u003erw_in_wait);\n 766:\t\tusb_set_intfdata(interface, mors);\n 767:\t\n 768:\t\tret = mm81x_usb_detect_endpoints(mors, interface);\n 769:\t\tif (ret \u003c 0)\n 770:\t\t\tgoto err_core_free;\n 771:\t\n 772:\t\tset_bit(MM81X_USB_FLAG_ATTACHED, \u0026musb-\u003eflags);\n 773:\t\n 774:\t\tret = mm81x_core_init(mors);\n 775:\t\tif (ret)\n 776:\t\t\tgoto err_urb_cleanup;\n 777:\t\n 778:\t\tINIT_WORK(\u0026mors-\u003eusb_irq_work, mm81x_usb_irq_work);\n 779:\t\n 780:\t\tret = mm81x_usb_int_enable(mors);\n 781:\t\tif (ret)\n 782:\t\t\tgoto err_core_deinit;\n 783:\t\n 784:\t\tret = mm81x_core_register(mors);\n 785:\t\tif (ret)\n 786:\t\t\tgoto err_usb_int_stop;\n 787:\t\n 788:\t\t/* USB requires remote wakeup functionality for suspend */\n 789:\t\tclear_bit(MM81X_USB_FLAG_SUSPENDED, \u0026musb-\u003eflags);\n 790:\t\tmusb-\u003einterface-\u003eneeds_remote_wakeup = 1;\n 791:\t\tusb_enable_autosuspend(musb-\u003eudev);\n 792:\t\tpm_runtime_set_autosuspend_delay(\u0026musb-\u003eudev-\u003edev,\n 793:\t\t\t\t\t\t PM_RUNTIME_AUTOSUSPEND_DELAY_MS);\n 794:\t\n 795:\t\tusb_autopm_get_interface(interface);\n 796:\t\treturn 0;\n 797:\t\n 798:\terr_usb_int_stop:\n 799:\t\tmm81x_usb_int_stop(mors);\n 800:\terr_core_deinit:\n 801:\t\tmm81x_core_deinit(mors);\n 802:\terr_urb_cleanup:\n 803:\t\tmm81x_urb_cleanup(mors);\n 804:\terr_core_free:\n 805:\t\tmm81x_core_free(mors);\n 806:\t\tusb_put_intf(interface);\n 807:\t\tusb_put_dev(interface_to_usbdev(interface));\n 808:\t\treturn ret;\n 809:\t}\n 810:\t\n 811:\tstatic void mm81x_usb_disconnect(struct usb_interface *interface)\n 812:\t{\n 813:\t\tstruct mm81x *mors = usb_get_intfdata(interface);\n 814:\t\tstruct mm81x_usb *musb = (struct mm81x_usb *)mors-\u003edrv_priv;\n 815:\t\tint minor = interface-\u003eminor;\n 816:\t\tstruct usb_device *udev = interface_to_usbdev(interface);\n 817:\t\n 818:\t\tif (udev-\u003estate == USB_STATE_NOTATTACHED) {\n 819:\t\t\tclear_bit(MM81X_USB_FLAG_ATTACHED, \u0026musb-\u003eflags);\n 820:\t\t\tset_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags);\n 821:\t\t\tdev_dbg(mors-\u003edev, \"USB suddenly unplugged\");\n 822:\t\t}\n 823:\t\n 824:\t\tusb_disable_autosuspend(udev);\n 825:\t\n 826:\t\tif (test_bit(MM81X_USB_FLAG_SUSPENDED, \u0026musb-\u003eflags)) {\n 827:\t\t\tdev_dbg(mors-\u003edev, \"USB was suspended: release locks\");\n 828:\t\t\tmm81x_usb_release_bus(mors);\n 829:\t\t\tmutex_unlock(\u0026musb-\u003elock);\n 830:\t\t}\n 831:\t\n 832:\t\tclear_bit(MM81X_USB_FLAG_SUSPENDED, \u0026musb-\u003eflags);\n 833:\t\n 834:\t\tmm81x_core_unregister(mors);\n 835:\t\tmm81x_usb_int_stop(mors);\n 836:\t\tmm81x_core_deinit(mors);\n 837:\t\tmm81x_urb_cleanup(mors);\n 838:\t\tmm81x_core_free(mors);\n 839:\t\n"
} |
| 24/2 | 2026/09/21 14:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 31008 output: 46 thoughts: 39 Thoughts: Okay, let's break this down. **Diving into USB Driver Registration** Right, so I need to figure out where the USB driver registration happens. My initial thought is to check `module_usb_driver` or `usb_register_driver` within `usb.c`. Good starting points. Now, I'll quickly jump over to those functions and take a look at the code block between lines 840 and 860. That should give me the core logic around the function I'm hunting for, and where it registers with the device. Let's see what's actually going on in that area. |
| 25/2 | 2026/09/21 14:25 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/usb.c",
"FirstLine": 840,
"LineCount": 40
}Results: {
"Contents": " 840:\t\tusb_autopm_put_interface(interface);\n 841:\t\tusb_set_intfdata(interface, NULL);\n 842:\t\tdev_info(\u0026interface-\u003edev, \"USB Morse #%d now disconnected\", minor);\n 843:\t\tusb_put_intf(interface);\n 844:\t\tusb_put_dev(udev);\n 845:\t}\n 846:\t\n 847:\tstatic int mm81x_usb_suspend(struct usb_interface *intf, pm_message_t message)\n 848:\t{\n 849:\t\tstruct mm81x *mors = usb_get_intfdata(intf);\n 850:\t\tstruct mm81x_usb *musb = (struct mm81x_usb *)mors-\u003edrv_priv;\n 851:\t\tstruct mm81x_usb_endpoint *int_ep = \u0026musb-\u003eendpoints[MM81X_EP_INT];\n 852:\t\tstruct mm81x_usb_endpoint *rd_ep = \u0026musb-\u003eendpoints[MM81X_EP_MEM_RD];\n 853:\t\tstruct mm81x_usb_endpoint *wr_ep = \u0026musb-\u003eendpoints[MM81X_EP_MEM_WR];\n 854:\t\tstruct mm81x_usb_endpoint *cmd_ep = \u0026musb-\u003eendpoints[MM81X_EP_CMD];\n 855:\t\n 856:\t\tif (!test_bit(MM81X_USB_FLAG_ATTACHED, \u0026musb-\u003eflags))\n 857:\t\t\treturn -ENODEV;\n 858:\t\n 859:\t\tusb_kill_urb(int_ep-\u003eurb);\n 860:\t\tusb_kill_urb(rd_ep-\u003eurb);\n 861:\t\tusb_kill_urb(wr_ep-\u003eurb);\n 862:\t\tusb_kill_urb(cmd_ep-\u003eurb);\n 863:\t\n 864:\t\t/* Locking the bus. No USB communication after this point */\n 865:\t\tmm81x_usb_claim_bus(mors);\n 866:\t\tmutex_lock(\u0026musb-\u003elock);\n 867:\t\n 868:\t\tset_bit(MM81X_USB_FLAG_SUSPENDED, \u0026musb-\u003eflags);\n 869:\t\treturn 0;\n 870:\t}\n 871:\t\n 872:\tstatic int mm81x_usb_resume(struct usb_interface *intf)\n 873:\t{\n 874:\t\tstruct mm81x *mors = usb_get_intfdata(intf);\n 875:\t\tstruct mm81x_usb *musb = (struct mm81x_usb *)mors-\u003edrv_priv;\n 876:\t\tint ret;\n 877:\t\tstruct mm81x_usb_endpoint *int_ep = \u0026musb-\u003eendpoints[MM81X_EP_INT];\n 878:\t\n 879:\t\tif (!test_bit(MM81X_USB_FLAG_ATTACHED, \u0026musb-\u003eflags))\n"
} |
| 26/2 | 2026/09/21 14:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 32037 output: 46 thoughts: 21 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Diving Deeper into usb.c** Alright, let's get down to brass tacks. I'm taking another look at `usb.c`, specifically lines 880 to 920. That's a pretty specific range, so I'm likely focusing on something particular there. I'm probably troubleshooting something, or perhaps I'm doing a deeper dive on a function call in that region. I need to understand this block of code inside and out. Let's see what's really happening in that section. |
| 27/2 | 2026/09/21 14:25 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/usb.c",
"FirstLine": 880,
"LineCount": 40
}Results: {
"Contents": " 880:\t\t\treturn -ENODEV;\n 881:\t\n 882:\t\tret = usb_submit_urb(int_ep-\u003eurb, GFP_KERNEL);\n 883:\t\tif (ret)\n 884:\t\t\tdev_err(mors-\u003edev, \"Couldn't submit urb. Error number %d\", ret);\n 885:\t\n 886:\t\tmm81x_usb_release_bus(mors);\n 887:\t\tmutex_unlock(\u0026musb-\u003elock);\n 888:\t\n 889:\t\tclear_bit(MM81X_USB_FLAG_SUSPENDED, \u0026musb-\u003eflags);\n 890:\t\treturn 0;\n 891:\t}\n 892:\t\n 893:\tstatic int mm81x_usb_reset_resume(struct usb_interface *intf)\n 894:\t{\n 895:\t\tstruct mm81x *mors = usb_get_intfdata(intf);\n 896:\t\tstruct mm81x_usb *musb = (struct mm81x_usb *)mors-\u003edrv_priv;\n 897:\t\tint ret;\n 898:\t\tstruct mm81x_usb_endpoint *int_ep = \u0026musb-\u003eendpoints[MM81X_EP_INT];\n 899:\t\n 900:\t\tif (!test_bit(MM81X_USB_FLAG_ATTACHED, \u0026musb-\u003eflags))\n 901:\t\t\treturn -ENODEV;\n 902:\t\n 903:\t\tret = usb_submit_urb(int_ep-\u003eurb, GFP_KERNEL);\n 904:\t\tif (ret)\n 905:\t\t\tdev_err(mors-\u003edev, \"Couldn't submit urb. Error number %d\", ret);\n 906:\t\n 907:\t\tmm81x_usb_release_bus(mors);\n 908:\t\tmutex_unlock(\u0026musb-\u003elock);\n 909:\t\n 910:\t\tclear_bit(MM81X_USB_FLAG_SUSPENDED, \u0026musb-\u003eflags);\n 911:\t\n 912:\t\treturn 0;\n 913:\t}\n 914:\t\n 915:\tstatic int mm81x_usb_pre_reset(struct usb_interface *intf)\n 916:\t{\n 917:\t\treturn 0;\n 918:\t}\n 919:\t\n"
} |
| 28/2 | 2026/09/21 14:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 32886 output: 46 thoughts: 19 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Diving into `usb.c` for Context** Okay, time to get my hands dirty. Let's pull up lines 920-950 of `usb.c`. I'm going to start there, as that section is usually relevant. My spider-sense is tingling that there is something interesting there. I'm focusing on that specific range to pinpoint the likely area of the code responsible for the behavior I'm seeing. I will start by assessing the code's general purpose, looking for anything that might be related to the issue at hand. |
| 29/2 | 2026/09/21 14:25 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/usb.c",
"FirstLine": 920,
"LineCount": 40
}Results: {
"Contents": " 920:\tstatic int mm81x_usb_post_reset(struct usb_interface *intf)\n 921:\t{\n 922:\t\treturn 0;\n 923:\t}\n 924:\t\n 925:\tstatic struct usb_driver mm81x_usb_driver = {\n 926:\t\t.name = \"mm81x_usb\",\n 927:\t\t.probe = mm81x_usb_probe,\n 928:\t\t.disconnect = mm81x_usb_disconnect,\n 929:\t\t.suspend = mm81x_usb_suspend,\n 930:\t\t.resume = mm81x_usb_resume,\n 931:\t\t.reset_resume = mm81x_usb_reset_resume,\n 932:\t\t.pre_reset = mm81x_usb_pre_reset,\n 933:\t\t.post_reset = mm81x_usb_post_reset,\n 934:\t\t.id_table = mm81x_usb_table,\n 935:\t\t.supports_autosuspend = 1,\n 936:\t\t.soft_unbind = 1,\n 937:\t};\n 938:\t\n 939:\tmodule_usb_driver(mm81x_usb_driver);\n 940:\t\n 941:\tMODULE_AUTHOR(\"Morse Micro\");\n 942:\tMODULE_DESCRIPTION(\"Driver support for Morse Micro MM81X USB devices\");\n 943:\tMODULE_LICENSE(\"Dual BSD/GPL\");\n"
} |
| 30/2 | 2026/09/21 14:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 33503 output: 45 thoughts: 232 Thoughts: **Tracing the Fuzzing Path** Okay, so I need to figure out if `mm81x_yaps_hw_read_pkts` is even touched during fuzzing. I'm going to start by tracing the call stack. Hold on, before I dive into the fuzzing specifics, let's back up a bit and examine the initialization path. I should first check `mm81x_core_register` and `mm81x_core_init` to understand the setup. I need to understand the entry points. Right, let's look at what's happening during the probe function. Specifically, inside `mm81x_usb_probe`, I see the calls to `mm81x_core_init`, `INIT_WORK`, `mm81x_usb_int_enable`, and `mm81x_core_register`. Makes sense; that’s where the core initialization and registration happen. Alright, now it is time to check `mm81x_core_init` and `mm81x_core_register` in `core.c`. This is where the real low-level details should be. I'll need to see how these functions set up the hardware, allocate resources, and handle interrupts. This should give me a solid foundation for tracing the path to `mm81x_yaps_hw_read_pkts`. I'm starting to put the pieces together. |
| 31/2 | 2026/09/21 14:25 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/core.c",
"FirstLine": 60,
"LineCount": 70
}Results: {
"Contents": " 60:\t\n 61:\tstruct mm81x *mm81x_core_alloc(size_t priv_size, struct device *dev)\n 62:\t{\n 63:\t\treturn mm81x_mac_alloc(priv_size, dev);\n 64:\t}\n 65:\tEXPORT_SYMBOL_GPL(mm81x_core_alloc);\n 66:\t\n 67:\tint mm81x_core_init(struct mm81x *mors)\n 68:\t{\n 69:\t\tint ret;\n 70:\t\n 71:\t\tset_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags);\n 72:\t\tset_bit(MM81X_STATE_RELOAD_FW_AFTER_START, \u0026mors-\u003estate_flags);\n 73:\t\n 74:\t\tmm81x_core_init_mac_addr(mors);\n 75:\t\n 76:\t\tret = mm81x_core_attach_regs(mors);\n 77:\t\tif (ret)\n 78:\t\t\treturn ret;\n 79:\t\n 80:\t\tmors-\u003echip_wq = create_singlethread_workqueue(\"chip_wq\");\n 81:\t\tif (!mors-\u003echip_wq)\n 82:\t\t\treturn -ENOMEM;\n 83:\t\n 84:\t\tmors-\u003enet_wq = create_singlethread_workqueue(\"net_wq\");\n 85:\t\tif (!mors-\u003enet_wq) {\n 86:\t\t\tret = -ENOMEM;\n 87:\t\t\tgoto err_chip_wq;\n 88:\t\t}\n 89:\t\n 90:\t\tret = mm81x_hif_init(mors);\n 91:\t\tif (ret)\n 92:\t\t\tgoto err_wqs;\n 93:\t\n 94:\t\treturn 0;\n 95:\t\n 96:\terr_wqs:\n 97:\t\tflush_workqueue(mors-\u003enet_wq);\n 98:\t\tdestroy_workqueue(mors-\u003enet_wq);\n 99:\t\n 100:\terr_chip_wq:\n 101:\t\tflush_workqueue(mors-\u003echip_wq);\n 102:\t\tdestroy_workqueue(mors-\u003echip_wq);\n 103:\t\n 104:\t\treturn ret;\n 105:\t}\n 106:\tEXPORT_SYMBOL_GPL(mm81x_core_init);\n 107:\t\n 108:\tint mm81x_core_register(struct mm81x *mors)\n 109:\t{\n 110:\t\treturn mm81x_mac_register(mors);\n 111:\t}\n 112:\tEXPORT_SYMBOL_GPL(mm81x_core_register);\n 113:\t\n 114:\tvoid mm81x_core_unregister(struct mm81x *mors)\n 115:\t{\n 116:\t\tmm81x_mac_unregister(mors);\n 117:\t}\n 118:\tEXPORT_SYMBOL_GPL(mm81x_core_unregister);\n 119:\t\n 120:\tvoid mm81x_core_deinit(struct mm81x *mors)\n 121:\t{\n 122:\t\tmm81x_hif_finish(mors);\n 123:\t\tflush_workqueue(mors-\u003enet_wq);\n 124:\t\tdestroy_workqueue(mors-\u003enet_wq);\n 125:\t\tflush_workqueue(mors-\u003echip_wq);\n 126:\t\tdestroy_workqueue(mors-\u003echip_wq);\n 127:\t}\n 128:\tEXPORT_SYMBOL_GPL(mm81x_core_deinit);\n 129:\t\n"
} |
| 32/2 | 2026/09/21 14:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 35117 output: 42 thoughts: 22 Thoughts: Okay, let's dive in. **Analyzing the `mm81x_mac_register` Function** Right, so I'm looking at `mm81x_mac_register` within `mac.c`. I immediately want to understand what's happening here. Given the naming convention, it's pretty clear this is where the MAC (Media Access Controller) registers are being handled. The function's name suggests a registration process, which means this probably deals with setting up or initializing the MAC hardware. I need to figure out what data is being passed in, what memory locations are being accessed, and the overall goal of this registration. Is it establishing a base address? Enabling interrupts? Setting up DMA channels? Knowing the broader context of the system architecture will definitely help clarify this, so I'll need to remember to look for its place within the larger system. Time to dig into the code! |
| 33/2 | 2026/09/21 14:25 | tool | grepper |
0mArgs:{
"Expression": "mm81x_mac_register",
"PathPrefix": "drivers/net/wireless/morsemicro/mm81x"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/core.c=108=int mm81x_core_register(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/core.c-109-{\ndrivers/net/wireless/morsemicro/mm81x/core.c:110:\treturn mm81x_mac_register(mors);\ndrivers/net/wireless/morsemicro/mm81x/core.c-111-}\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c=2355=static void mm81x_mac_stale_tx_status_timer_init(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2360-\ndrivers/net/wireless/morsemicro/mm81x/mac.c:2361:int mm81x_mac_register(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2362-{\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.h=51=struct mm81x *mm81x_mac_alloc(size_t priv_size, struct device *dev);\ndrivers/net/wireless/morsemicro/mm81x/mac.h:52:int mm81x_mac_register(struct mm81x *mors);\ndrivers/net/wireless/morsemicro/mm81x/mac.h-53-void mm81x_mac_free(struct mm81x *mors);\n"
} |
| 34/2 | 2026/09/21 14:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 35800 output: 47 thoughts: 20 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience and written in the first person: **Diving into `mm81x_mac_register`** Okay, let's pull up the `mm81x_mac_register` function definition in `mac.c`. I need to understand how the MAC is initialized and integrated into the system. Knowing the register setup is key here. I'm assuming, given the naming, that this function is specific to the mm81x series. I'll need to immediately look for any associated platform or device tree bindings that define the register map base addresses, interrupt lines, and perhaps any clock configurations passed to this function. I'm also interested to understand what data structures, specific to that platform, are getting set up. I'll look for any mutexes or spinlocks it's using to protect shared resources, any DMA channel allocations, and also what initialization steps are performed on the MAC hardware itself. Are they setting up the PHY interface? Enabling interrupts? Configuring the Ethernet MAC address from either a defined setting or potentially reading from a flash. And finally, what's its relationship with the network stack. I'll need to ascertain if it's registering a net device, and if so, what network configuration variables it's using. |
| 35/2 | 2026/09/21 14:25 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/mac.c",
"FirstLine": 2360,
"LineCount": 40
}Results: {
"Contents": "2360:\t\n2361:\tint mm81x_mac_register(struct mm81x *mors)\n2362:\t{\n2363:\t\tint ret;\n2364:\t\tstruct ieee80211_hw *hw = mors-\u003ehw;\n2365:\t\n2366:\t\tmors-\u003etx_power_mbm = INT_MAX;\n2367:\t\tmors-\u003etx_max_power_mbm = INT_MAX;\n2368:\t\tmors-\u003erts_threshold = IEEE80211_MAX_RTS_THRESHOLD;\n2369:\t\n2370:\t\tret = mm81x_ps_init(mors);\n2371:\t\tif (ret)\n2372:\t\t\treturn ret;\n2373:\t\n2374:\t\tmm81x_mac_config_hw(mors);\n2375:\t\tmm81x_mac_hw_scan_init(mors);\n2376:\t\tmm81x_mac_stale_tx_status_timer_init(mors);\n2377:\t\n2378:\t\tret = ieee80211_register_hw(hw);\n2379:\t\tif (ret) {\n2380:\t\t\tdev_err(mors-\u003edev, \"ieee80211_register_hw failed %d\", ret);\n2381:\t\t\tmm81x_mac_unregister(mors);\n2382:\t\t\treturn ret;\n2383:\t\t}\n2384:\t\n2385:\t\tmm81x_rc_init(mors);\n2386:\t\n2387:\t\t/*\n2388:\t\t * At this stage, we know bus and pager system interrupts are enabled.\n2389:\t\t * Trigger the receive workqueue to drain any incoming chip-to-host\n2390:\t\t * pending packets been pushed in the period between the firmware\n2391:\t\t * initialization and interrupts being enabled.\n2392:\t\t */\n2393:\t\tset_bit(MM81X_HIF_EVT_RX_PEND, \u0026mors-\u003ehif.event_flags);\n2394:\t\tqueue_work(mors-\u003echip_wq, \u0026mors-\u003ehif_work);\n2395:\t\n2396:\t\treturn ret;\n2397:\t}\n2398:\t\n2399:\tvoid mm81x_mac_unregister(struct mm81x *mors)\n"
} |
| 36/2 | 2026/09/21 14:25 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 36799 output: 38 thoughts: 80 Thoughts: Here's my take on those snippets, as if I'm thinking it: **Decoding a Hardware Event Handling Sequence** Alright, let's break this down. *Interesting*, I see a bit being set: `set_bit(MM81X_HIF_EVT_RX_PEND, &mors->hif.event_flags);`. It looks like we're signaling the reception of a pending event, likely related to the hardware interface (HIF) in this `mors` structure, specifically the `RX_PEND` event type. Seems straightforward enough – a flag is raised to indicate something new has arrived from the hardware. Then, immediately following, we queue some work: `queue_work(mors->chip_wq, &mors->hif_work);`. Clearly this is a workqueue. This suggests a deferral strategy, avoiding blocking the main thread, good practice. Now, I want to know, and the next logical step, is what's this `mors->hif_work` actually *do*? I need to follow the execution path; I'll need to dig into the definition of `mors->hif_work` to understand the actual event handling logic. This is where the rubber meets the road. What's the function that's being scheduled and how does it react to that flag that was just set? Let's go see what's happening. |
| 37/2 | 2026/09/21 14:26 | tool | grepper |
0mArgs:{
"Expression": "hif_work",
"PathPrefix": "drivers/net/wireless/morsemicro/mm81x"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/core.h=303=struct mm81x {\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-356-\tstruct workqueue_struct *chip_wq;\ndrivers/net/wireless/morsemicro/mm81x/core.h:357:\tstruct work_struct hif_work;\ndrivers/net/wireless/morsemicro/mm81x/core.h-358-\tstruct work_struct usb_irq_work;\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c=1960=static void mm81x_mac_flush_queues(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-1967-\ndrivers/net/wireless/morsemicro/mm81x/mac.c:1968:\tflush_work(\u0026mors-\u003ehif_work);\ndrivers/net/wireless/morsemicro/mm81x/mac.c-1969-\tflush_work(\u0026mors-\u003etx_stale_work);\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c=2107=static int mm81x_mac_restart(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2122-\tmdelay(MM81X_HW_RESTART_DELAY_MS);\ndrivers/net/wireless/morsemicro/mm81x/mac.c:2123:\tflush_work(\u0026mors-\u003ehif_work);\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2124-\tflush_work(\u0026mors-\u003etx_stale_work);\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c=2361=int mm81x_mac_register(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2393-\tset_bit(MM81X_HIF_EVT_RX_PEND, \u0026mors-\u003ehif.event_flags);\ndrivers/net/wireless/morsemicro/mm81x/mac.c:2394:\tqueue_work(mors-\u003echip_wq, \u0026mors-\u003ehif_work);\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2395-\n--\ndrivers/net/wireless/morsemicro/mm81x/skbq.c=566=static int mm81x_skbq_tx(struct mm81x_skbq *mq, struct sk_buff *skb, u8 channel)\n--\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-599-\t\t\t\t\u0026mors-\u003ehif.event_flags);\ndrivers/net/wireless/morsemicro/mm81x/skbq.c:600:\t\t\tqueue_work(mors-\u003echip_wq, \u0026mors-\u003ehif_work);\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-601-\t\t}\n--\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-604-\t\tset_bit(MM81X_HIF_EVT_TX_MGMT_PEND, \u0026mors-\u003ehif.event_flags);\ndrivers/net/wireless/morsemicro/mm81x/skbq.c:605:\t\tqueue_work(mors-\u003echip_wq, \u0026mors-\u003ehif_work);\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-606-\t\tbreak;\n--\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-608-\t\tset_bit(MM81X_HIF_EVT_TX_BEACON_PEND, \u0026mors-\u003ehif.event_flags);\ndrivers/net/wireless/morsemicro/mm81x/skbq.c:609:\t\tqueue_work(mors-\u003echip_wq, \u0026mors-\u003ehif_work);\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-610-\t\tbreak;\n--\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-612-\t\tset_bit(MM81X_HIF_EVT_TX_COMMAND_PEND, \u0026mors-\u003ehif.event_flags);\ndrivers/net/wireless/morsemicro/mm81x/skbq.c:613:\t\tqueue_work(mors-\u003echip_wq, \u0026mors-\u003ehif_work);\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-614-\t\tbreak;\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c=103=static int mm81x_yaps_irq_handler(struct mm81x *mors, u32 status)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-113-\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:114:\tqueue_work(mors-\u003echip_wq, \u0026mors-\u003ehif_work);\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-115-\treturn 0;\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c=443=void mm81x_yaps_work(struct work_struct *work)\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-444-{\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:445:\tstruct mm81x *mors = container_of(work, struct mm81x, hif_work);\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-446-\tunsigned long *flags = \u0026mors-\u003ehif.event_flags;\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-536-\tif ((*flags) \u0026 ~(1 \u003c\u003c MM81X_HIF_EVT_TX_DATA_PEND))\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:537:\t\tqueue_work(mors-\u003echip_wq, \u0026mors-\u003ehif_work);\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-538-\t/*\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-542-\telse if (!yaps-\u003echip_queue_full.is_full \u0026\u0026 *flags)\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:543:\t\tqueue_work(mors-\u003echip_wq, \u0026mors-\u003ehif_work);\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-544-}\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c=584=static void mm81x_yaps_tx_q_full_timer(struct timer_list *t)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-588-\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:589:\tqueue_work(yaps-\u003emors-\u003echip_wq, \u0026yaps-\u003emors-\u003ehif_work);\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-590-}\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c=603=int mm81x_yaps_init(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-647-\tmm81x_yaps_q_chip_full_timer_init(yaps);\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:648:\tINIT_WORK(\u0026mors-\u003ehif_work, mm81x_yaps_work);\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-649-\tINIT_WORK(\u0026mors-\u003etx_stale_work, mm81x_yaps_stale_tx_work);\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c=655=void mm81x_yaps_finish(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-676-\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:677:\tcancel_work_sync(\u0026mors-\u003ehif_work);\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-678-\tcancel_work_sync(\u0026mors-\u003etx_stale_work);\n"
} |
| 38/2 | 2026/09/21 14:26 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 39526 output: 47 thoughts: 79 Thoughts: Here's my analysis of what's going on, thinking like a kernel developer: **Examining the YAPS Work Queue** Okay, so I see they're initializing a work structure, `mors->hif_work`, using `INIT_WORK`. The second argument, `mm81x_yaps_work`, is the work function itself. Right, that's standard. Let's dig into that `mm81x_yaps_work` function within `yaps.c`. I expect to find the meat of the processing there. It looks like `mm81x_yaps_work` is going to be the entry point for handling data received via the YAPS interface, and I’m betting it's going to call a dedicated handler function, perhaps dealing with framing or buffering data. Let's see if my hunch is correct. I’m especially interested in how it interacts with the lower layers and what kind of interrupt context it operates in. I have a feeling the `mm81x_yaps_rx_handler(yaps)` will be called from there and that's going to be the next piece of code I need to really understand. |
| 39/2 | 2026/09/21 14:26 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/yaps.c",
"FirstLine": 443,
"LineCount": 60
}Results: {
"Contents": " 443:\tvoid mm81x_yaps_work(struct work_struct *work)\n 444:\t{\n 445:\t\tstruct mm81x *mors = container_of(work, struct mm81x, hif_work);\n 446:\t\tunsigned long *flags = \u0026mors-\u003ehif.event_flags;\n 447:\t\tstruct mm81x_yaps *yaps = \u0026mors-\u003ehif.u.yaps;\n 448:\t\n 449:\t\tif (test_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags))\n 450:\t\t\treturn;\n 451:\t\n 452:\t\tif (!*flags)\n 453:\t\t\treturn;\n 454:\t\n 455:\t\t/* Disable power save in case it is running */\n 456:\t\tmm81x_ps_disable(mors);\n 457:\t\tmm81x_claim_bus(mors);\n 458:\t\n 459:\t\t/*\n 460:\t\t * Handle any populated RX pages from chip first to\n 461:\t\t * avoid dropping pkts due to full on-chip buffers.\n 462:\t\t * Check if all pages were removed, set event flags if not.\n 463:\t\t */\n 464:\t\tif (test_and_clear_bit(MM81X_HIF_EVT_RX_PEND, flags)) {\n 465:\t\t\tif (mm81x_yaps_rx_handler(yaps))\n 466:\t\t\t\tset_bit(MM81X_HIF_EVT_RX_PEND, flags);\n 467:\t\t}\n 468:\t\n 469:\t\t/* TX any commands before considering data */\n 470:\t\tif (test_and_clear_bit(MM81X_HIF_EVT_TX_COMMAND_PEND, flags)) {\n 471:\t\t\tif (mm81x_yaps_tx_cmd_handler(yaps))\n 472:\t\t\t\tset_bit(MM81X_HIF_EVT_TX_COMMAND_PEND, flags);\n 473:\t\t}\n 474:\t\n 475:\t\t/* TX beacons before considering mgmt/data */\n 476:\t\tif (test_and_clear_bit(MM81X_HIF_EVT_TX_BEACON_PEND, flags)) {\n 477:\t\t\tif (mm81x_yaps_tx_beacon_handler(yaps))\n 478:\t\t\t\tset_bit(MM81X_HIF_EVT_TX_BEACON_PEND, flags);\n 479:\t\t}\n 480:\t\n 481:\t\t/* TX mgmt before considering data */\n 482:\t\tif (test_and_clear_bit(MM81X_HIF_EVT_TX_MGMT_PEND, flags)) {\n 483:\t\t\tif (mm81x_yaps_tx_mgmt_handler(yaps))\n 484:\t\t\t\tset_bit(MM81X_HIF_EVT_TX_MGMT_PEND, flags);\n 485:\t\t}\n 486:\t\n 487:\t\t/* Pause TX data Qs */\n 488:\t\tif (test_and_clear_bit(MM81X_HIF_EVT_DATA_TRAFFIC_PAUSE_PEND, flags)) {\n 489:\t\t\ttest_and_clear_bit(MM81X_HIF_EVT_DATA_TRAFFIC_RESUME_PEND,\n 490:\t\t\t\t\t flags);\n 491:\t\t\tmm81x_skbq_data_traffic_pause(mors);\n 492:\t\t}\n 493:\t\n 494:\t\t/* Resume TX data Qs */\n 495:\t\tif (test_and_clear_bit(MM81X_HIF_EVT_DATA_TRAFFIC_RESUME_PEND, flags))\n 496:\t\t\tmm81x_skbq_data_traffic_resume(mors);\n 497:\t\n 498:\t\t/* Handle chip queue status */\n 499:\t\tif (test_and_clear_bit(MM81X_HIF_EVT_TX_PACKET_FREED_UP_PEND, flags))\n 500:\t\t\tyaps-\u003echip_queue_full.is_full = false;\n 501:\t\n 502:\t\t/* Check to see if the queue is full or\n"
} |
| 40/2 | 2026/09/21 14:26 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 41064 output: 48 thoughts: 88 Thoughts: **Debugging a Potentially Unresponsive Chip** Okay, here we go, diving into this code. Line 449 is jumping out at me: `if (test_bit(MM81X_STATE_CHIP_UNRESPONSIVE, &mors->state_flags)) return;`. My initial reaction is, "Wait a minute!" This is checking for a chip unresponsive state and returning if that bit is set. The *real* question is, when and *how* does that `MM81X_STATE_CHIP_UNRESPONSIVE` flag *get cleared*? That's the critical piece of the puzzle here. I need to trace the lifecycle of that flag to understand the full picture. Time to launch a search for `MM81X_STATE_CHIP_UNRESPONSIVE` and see where it's being set, cleared, and used. Knowing the context of its use will allow me to track the path of how the chip state is updated. |
| 41/2 | 2026/09/21 14:26 | tool | grepper |
0mArgs:{
"Expression": "MM81X_STATE_CHIP_UNRESPONSIVE",
"PathPrefix": "drivers/net/wireless/morsemicro/mm81x"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/core.c=67=int mm81x_core_init(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/core.c-70-\ndrivers/net/wireless/morsemicro/mm81x/core.c:71:\tset_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags);\ndrivers/net/wireless/morsemicro/mm81x/core.c-72-\tset_bit(MM81X_STATE_RELOAD_FW_AFTER_START, \u0026mors-\u003estate_flags);\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=289=enum mm81x_state_flags {\ndrivers/net/wireless/morsemicro/mm81x/core.h:290:\tMM81X_STATE_CHIP_UNRESPONSIVE,\ndrivers/net/wireless/morsemicro/mm81x/core.h-291-\tMM81X_STATE_DATA_QS_STOPPED,\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c=2107=static int mm81x_mac_restart(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2159-\tclear_bit(MM81X_STATE_DATA_QS_STOPPED, \u0026mors-\u003estate_flags);\ndrivers/net/wireless/morsemicro/mm81x/mac.c:2160:\tclear_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags);\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2161-\tclear_bit(MM81X_STATE_RELOAD_FW_AFTER_START, \u0026mors-\u003estate_flags);\n--\ndrivers/net/wireless/morsemicro/mm81x/skbq.c=955=int mm81x_skbq_skb_tx(struct mm81x_skbq *mq, struct sk_buff **skb_orig,\n--\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-964-\ndrivers/net/wireless/morsemicro/mm81x/skbq.c:965:\tif (test_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags)) {\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-966-\t\tdev_kfree_skb_any(skb);\n--\ndrivers/net/wireless/morsemicro/mm81x/usb.c=109=static void mm81x_usb_int_handler(struct urb *urb)\n--\ndrivers/net/wireless/morsemicro/mm81x/usb.c-120-\t\t\tclear_bit(MM81X_USB_FLAG_ATTACHED, \u0026musb-\u003eflags);\ndrivers/net/wireless/morsemicro/mm81x/usb.c:121:\t\t\tset_bit(MM81X_STATE_CHIP_UNRESPONSIVE,\ndrivers/net/wireless/morsemicro/mm81x/usb.c-122-\t\t\t\t\u0026mors-\u003estate_flags);\n--\ndrivers/net/wireless/morsemicro/mm81x/usb.c=811=static void mm81x_usb_disconnect(struct usb_interface *interface)\n--\ndrivers/net/wireless/morsemicro/mm81x/usb.c-819-\t\tclear_bit(MM81X_USB_FLAG_ATTACHED, \u0026musb-\u003eflags);\ndrivers/net/wireless/morsemicro/mm81x/usb.c:820:\t\tset_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags);\ndrivers/net/wireless/morsemicro/mm81x/usb.c-821-\t\tdev_dbg(mors-\u003edev, \"USB suddenly unplugged\");\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c=443=void mm81x_yaps_work(struct work_struct *work)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-448-\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:449:\tif (test_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags))\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-450-\t\treturn;\n"
} |
| 42/2 | 2026/09/21 14:26 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 42610 output: 42 thoughts: 48 Thoughts: Here's my summary, as though I'm thinking through this myself: **Investigating the `MM81X_STATE_CHIP_UNRESPONSIVE` Flag** Okay, so I see that the `MM81X_STATE_CHIP_UNRESPONSIVE` flag is explicitly cleared within the `mm81x_mac_restart` function. That's a good starting point. My next immediate thought is to trace the execution path. I need to understand *why* this restart is happening, because if it's constantly triggered, it's indicative of a problem. Therefore, my immediate next step is clear: I need to identify *every* single place in the code where `mm81x_mac_restart` is called. That call stack is going to be crucial in narrowing down the root cause of this "chip unresponsive" behavior. I need to see the contexts in which this restart is triggered to understand the environmental triggers and data involved. Let's dig in and find all those callers. |
| 43/2 | 2026/09/21 14:26 | tool | grepper |
0mArgs:{
"Expression": "mm81x_mac_restart",
"PathPrefix": "drivers/net/wireless/morsemicro/mm81x"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/mac.c=2071=static u32 mm81x_get_expected_throughput(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2090-\ndrivers/net/wireless/morsemicro/mm81x/mac.c:2091:static void mm81x_mac_restart_cleanup_iter(void *data, u8 *mac,\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2092-\t\t\t\t\t struct ieee80211_vif *vif)\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2097-\ndrivers/net/wireless/morsemicro/mm81x/mac.c:2098:static void mm81x_mac_restart_cleanup(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2099-{\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2101-\t\t\t\t\t IEEE80211_IFACE_ITER_NORMAL,\ndrivers/net/wireless/morsemicro/mm81x/mac.c:2102:\t\t\t\t\t mm81x_mac_restart_cleanup_iter,\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2103-\t\t\t\t\t NULL);\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2106-\ndrivers/net/wireless/morsemicro/mm81x/mac.c:2107:static int mm81x_mac_restart(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2108-{\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2137-\ndrivers/net/wireless/morsemicro/mm81x/mac.c:2138:\tmm81x_mac_restart_cleanup(mors);\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2139-\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c=2170=static int mm81x_mac_ops_add_interface(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2180-\ndrivers/net/wireless/morsemicro/mm81x/mac.c:2181:\t\tret = mm81x_mac_restart(mors);\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2182-\t\tif (ret) {\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c=2261=static void mm81x_reg_notifier(struct wiphy *wiphy,\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2272-\ndrivers/net/wireless/morsemicro/mm81x/mac.c:2273:\tret = mm81x_mac_restart(mors);\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2274-\tif (ret)\n"
} |
| 44/2 | 2026/09/21 14:26 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 43796 output: 47 thoughts: 68 Thoughts: Here's my thought process, as if I were analyzing this code: **Diving into the mm81x MAC Operations** Okay, so `mm81x_mac_ops_add_interface` and `mm81x_reg_notifier` both trigger `mm81x_mac_restart`. That's interesting. It suggests that interface additions and registering a notifier – both potentially significant events for the MAC – necessitate a full restart. I need to understand why. What's the core functionality or process that requires this? The next step is obvious: I have to examine the `mm81x_mac_restart` function itself. I need to see *exactly* what's involved in this "restart." Is it a complete reset, a reconfiguration, or something more nuanced? What's the context in which this restart happens? Knowing that will be key to understanding the performance and stability implications of these calls. Time to dig into that function's code. |
| 45/2 | 2026/09/21 14:26 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/mac.c",
"FirstLine": 2107,
"LineCount": 60
}Results: {
"Contents": "2107:\tstatic int mm81x_mac_restart(struct mm81x *mors)\n2108:\t{\n2109:\t\tint ret;\n2110:\t\tu32 chip_id;\n2111:\t\n2112:\t\tmors-\u003estarted = false;\n2113:\t\tmm81x_ps_disable(mors);\n2114:\t\tmm81x_bus_set_irq(mors, false);\n2115:\t\tmm81x_hw_irq_clear(mors);\n2116:\t\tieee80211_stop_queues(mors-\u003ehw);\n2117:\t\n2118:\t\tset_bit(MM81X_STATE_DATA_TX_STOPPED, \u0026mors-\u003estate_flags);\n2119:\t\tset_bit(MM81X_STATE_DATA_QS_STOPPED, \u0026mors-\u003estate_flags);\n2120:\t\n2121:\t\t/* Allow time for in-transit tx/rx packets to settle */\n2122:\t\tmdelay(MM81X_HW_RESTART_DELAY_MS);\n2123:\t\tflush_work(\u0026mors-\u003ehif_work);\n2124:\t\tflush_work(\u0026mors-\u003etx_stale_work);\n2125:\t\tmm81x_hif_clear_events(mors);\n2126:\t\tmm81x_hif_flush_tx_data(mors);\n2127:\t\tmm81x_hif_flush_cmds(mors);\n2128:\t\n2129:\t\tmm81x_claim_bus(mors);\n2130:\t\tret = mm81x_reg32_read(mors, MM81X_REG_CHIP_ID(mors), \u0026chip_id);\n2131:\t\tmm81x_release_bus(mors);\n2132:\t\n2133:\t\tif (ret \u003c 0) {\n2134:\t\t\tdev_err(mors-\u003edev, \"Failed to access HW: %d\", ret);\n2135:\t\t\tgoto exit;\n2136:\t\t}\n2137:\t\n2138:\t\tmm81x_mac_restart_cleanup(mors);\n2139:\t\n2140:\t\tret = mm81x_fw_init(mors, true);\n2141:\t\tif (ret \u003c 0) {\n2142:\t\t\tdev_err(mors-\u003edev, \"Failed to init firmware: %d\", ret);\n2143:\t\t\tgoto exit;\n2144:\t\t}\n2145:\t\n2146:\t\tmm81x_hw_irq_enable(mors, MM81X_INT_HW_STOP_NOTIFICATION_NUM, true);\n2147:\t\n2148:\t\tret = mm81x_fw_parse_ext_host_tbl(mors);\n2149:\t\tif (ret) {\n2150:\t\t\tdev_err(mors-\u003edev, \"failed to parse extended host table: %d\",\n2151:\t\t\t\tret);\n2152:\t\t\tgoto exit;\n2153:\t\t}\n2154:\t\n2155:\t\tmm81x_mac_caps_init(mors);\n2156:\t\n2157:\t\tmm81x_bus_set_irq(mors, true);\n2158:\t\tclear_bit(MM81X_STATE_DATA_TX_STOPPED, \u0026mors-\u003estate_flags);\n2159:\t\tclear_bit(MM81X_STATE_DATA_QS_STOPPED, \u0026mors-\u003estate_flags);\n2160:\t\tclear_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags);\n2161:\t\tclear_bit(MM81X_STATE_RELOAD_FW_AFTER_START, \u0026mors-\u003estate_flags);\n2162:\t\tmm81x_mac_check_fw_disabled_chans(mors-\u003ehw);\n2163:\t\tieee80211_restart_hw(mors-\u003ehw);\n2164:\t\n2165:\texit:\n2166:\t\tmm81x_ps_enable(mors);\n"
} |
| 46/2 | 2026/09/21 14:26 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 45236 output: 36 thoughts: 139 Thoughts: **Firmware Investigation** Okay, hold on a second. I need to dive into this `mm81x_fw_init(mors, true)` function call. The core question is: can we leverage syzkaller or USB emulation to either supply the firmware directly, or at the very least, trigger a probing action for it? Thinking about syzkaller's USB capabilities, I remember seeing the `syz_usb_connect` system call and the USB Raw Gadget setup – could those be the key? The crucial point is this: can a USB device, in an emulated environment, convincingly mimic a firmware loading process, or is the kernel making a `request_firmware` call? That's the route I'll need to understand. Let's see... what are the relevant functions? I need to check `request_firmware`, `firmware_request_nowarn`, and `request_firmware_direct`. Right, let's head straight to the source code. Let's look at `drivers/net/wireless/morsemicro/mm81x/fw.c`. That's where I need to start. |
| 47/2 | 2026/09/21 14:26 | tool | grepper |
0mArgs:{
"Expression": "firmware",
"PathPrefix": "drivers/net/wireless/morsemicro/mm81x"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/command.c=146=int mm81x_cmd_resp_process(struct mm81x *mors, struct sk_buff *skb)\n--\ndrivers/net/wireless/morsemicro/mm81x/command.c-182-\t * the response may be from the retry or from the original command\ndrivers/net/wireless/morsemicro/mm81x/command.c:183:\t * (late response) but not from both because the firmware will silently\ndrivers/net/wireless/morsemicro/mm81x/command.c-184-\t * drop a retry if it received the initial request. So a mismatched\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=303=struct mm81x {\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-319-\ndrivers/net/wireless/morsemicro/mm81x/core.h:320:\t/* Mask of type @enum host_table_firmware_flags */\ndrivers/net/wireless/morsemicro/mm81x/core.h-321-\tu32 fw_flags;\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-5-#include \u003clinux/kernel.h\u003e\ndrivers/net/wireless/morsemicro/mm81x/fw.c:6:#include \u003clinux/firmware.h\u003e\ndrivers/net/wireless/morsemicro/mm81x/fw.c-7-#include \u003clinux/slab.h\u003e\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-18-/*\ndrivers/net/wireless/morsemicro/mm81x/fw.c:19: * Maximum wait time (microseconds) for firmware to boot (for host table\ndrivers/net/wireless/morsemicro/mm81x/fw.c-20- * pointer to be available)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=91=static int mm81x_fw_set_boot_addr(struct mm81x *mors, uint32_t addr)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-101-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:102:static int mm81x_fw_load_fw(struct mm81x *mors, const struct firmware *fw)\ndrivers/net/wireless/morsemicro/mm81x/fw.c-103-{\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-124-\t\t\t\t\tehdr.e_shstrndx)) {\ndrivers/net/wireless/morsemicro/mm81x/fw.c:125:\t\tdev_err(mors-\u003edev, \"Invalid firmware. Missing string table\");\ndrivers/net/wireless/morsemicro/mm81x/fw.c-126-\t\treturn -ENOENT;\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-171-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:172:\t\t/* This is the firmware info. Parse it */\ndrivers/net/wireless/morsemicro/mm81x/fw.c-173-\t\tif (!strncmp(sh_strs + shdr.sh_name, \".fw_info\",\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=186=static int __mm81x_fw_load_bcf(struct mm81x *mors, unsigned int addr,\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-208-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:209:static int mm81x_fw_load_bcf(struct mm81x *mors, const struct firmware *bcf,\ndrivers/net/wireless/morsemicro/mm81x/fw.c-210-\t\t\t unsigned int bcf_address)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=378=static int mm81x_fw_check_compatibility(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-397-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:398:\t/* Firmware on device must match the firmware file we requested */\ndrivers/net/wireless/morsemicro/mm81x/fw.c-399-\tif (ret == 0 \u0026\u0026 major != mors-\u003efw_major) {\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=546=int mm81x_fw_parse_ext_host_tbl(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-598-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:599:static int __mm81x_fw_flash(struct mm81x *mors, const struct firmware *fw,\ndrivers/net/wireless/morsemicro/mm81x/fw.c:600:\t\t\t const struct firmware *bcf, bool reset)\ndrivers/net/wireless/morsemicro/mm81x/fw.c-601-{\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-609-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:610:\tmm81x_hw_pre_firmware_ndr_hook(mors);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-611-\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-624-\tmm81x_fw_trigger(mors);\ndrivers/net/wireless/morsemicro/mm81x/fw.c:625:\tmm81x_hw_post_firmware_ndr_hook(mors);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-626-\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-637-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:638:static int mm81x_fw_flash(struct mm81x *mors, const struct firmware *fw,\ndrivers/net/wireless/morsemicro/mm81x/fw.c:639:\t\t\t const struct firmware *bcf, bool reset)\ndrivers/net/wireless/morsemicro/mm81x/fw.c-640-{\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-654-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:655:static uint32_t binary_crc(const struct firmware *fw)\ndrivers/net/wireless/morsemicro/mm81x/fw.c-656-{\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-660-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:661:static int mm81x_fw_request(struct mm81x *mors, const struct firmware **fw)\ndrivers/net/wireless/morsemicro/mm81x/fw.c-662-{\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-671-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:672:\t\tret = firmware_request_nowarn(fw, fw_path, mors-\u003edev);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-673-\t\tif (!ret) {\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-675-\t\t\t\tmors-\u003edev,\ndrivers/net/wireless/morsemicro/mm81x/fw.c:676:\t\t\t\t\"Loaded firmware from %s, size %zu, crc32 0x%08x\\n\",\ndrivers/net/wireless/morsemicro/mm81x/fw.c-677-\t\t\t\tfw_path, (*fw)-\u003esize, binary_crc(*fw));\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-685-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:686:\tdev_err(mors-\u003edev, \"no firmware found (tried v%d down to v%d): %d\\n\",\ndrivers/net/wireless/morsemicro/mm81x/fw.c-687-\t\tMM81X_FW_VER_MAX, MM81X_FW_VER_MIN, ret);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=691=int mm81x_fw_init(struct mm81x *mors, bool reset)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-695-\tchar *bcf_path = NULL;\ndrivers/net/wireless/morsemicro/mm81x/fw.c:696:\tconst struct firmware *fw = NULL;\ndrivers/net/wireless/morsemicro/mm81x/fw.c:697:\tconst struct firmware *bcf = NULL;\ndrivers/net/wireless/morsemicro/mm81x/fw.c-698-\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-722-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:723:\tret = request_firmware(\u0026bcf, bcf_path, mors-\u003edev);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-724-\tif (ret) {\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-734-\tif (ret) {\ndrivers/net/wireless/morsemicro/mm81x/fw.c:735:\t\tdev_err(mors-\u003edev, \"failed to flash firmware: %d\", ret);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-736-\t\tgoto out;\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-741-out:\ndrivers/net/wireless/morsemicro/mm81x/fw.c:742:\trelease_firmware(fw);\ndrivers/net/wireless/morsemicro/mm81x/fw.c:743:\trelease_firmware(bcf);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-744-\tkfree(bcf_path);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-746-\tif (ret)\ndrivers/net/wireless/morsemicro/mm81x/fw.c:747:\t\tdev_err(mors-\u003edev, \"failed to init firmware: %d\", ret);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-748-\telse\ndrivers/net/wireless/morsemicro/mm81x/fw.c:749:\t\tdev_dbg(mors-\u003edev, \"firmware initialised\");\ndrivers/net/wireless/morsemicro/mm81x/fw.c-750-\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.h-8-\ndrivers/net/wireless/morsemicro/mm81x/fw.h:9:#include \u003clinux/firmware.h\u003e\ndrivers/net/wireless/morsemicro/mm81x/fw.h-10-#include \u003clinux/completion.h\u003e\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.h=93=struct ext_host_tbl_s1g_caps {\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.h-96-\t/*\ndrivers/net/wireless/morsemicro/mm81x/fw.h:97:\t * The minimum A-MPDU start spacing required by firmware.\ndrivers/net/wireless/morsemicro/mm81x/fw.h-98-\t * Value | Description\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.c-4- */\ndrivers/net/wireless/morsemicro/mm81x/hw.c:5:#include \u003clinux/firmware.h\u003e\ndrivers/net/wireless/morsemicro/mm81x/hw.c-6-#include \u003clinux/delay.h\u003e\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.c=303=int mm81x_hw_digital_reset(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.c-333-\ndrivers/net/wireless/morsemicro/mm81x/hw.c:334:void mm81x_hw_pre_firmware_ndr_hook(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/hw.c-335-{\ndrivers/net/wireless/morsemicro/mm81x/hw.c:336:\t/* We need disable bursting for firmware download/init procedure */\ndrivers/net/wireless/morsemicro/mm81x/hw.c-337-\tmm81x_bus_config_burst_mode(mors, false);\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.c-339-\ndrivers/net/wireless/morsemicro/mm81x/hw.c:340:void mm81x_hw_post_firmware_ndr_hook(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/hw.c-341-{\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.h-89-\ndrivers/net/wireless/morsemicro/mm81x/hw.h:90:enum host_table_firmware_flags {\ndrivers/net/wireless/morsemicro/mm81x/hw.h-91-\tMM81X_FW_FLAGS_SUPPORT_S1G = BIT(0),\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.h=140=int mm81x_hw_digital_reset(struct mm81x *mors);\ndrivers/net/wireless/morsemicro/mm81x/hw.h:141:void mm81x_hw_pre_firmware_ndr_hook(struct mm81x *mors);\ndrivers/net/wireless/morsemicro/mm81x/hw.h:142:void mm81x_hw_post_firmware_ndr_hook(struct mm81x *mors);\ndrivers/net/wireless/morsemicro/mm81x/hw.h-143-\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-20- * the command does not exceed page/MTU size. This will be far greater than\ndrivers/net/wireless/morsemicro/mm81x/mac.c:21: * the number of filters supported by the firmware.\ndrivers/net/wireless/morsemicro/mm81x/mac.c-22- */\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c=2107=static int mm81x_mac_restart(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2141-\tif (ret \u003c 0) {\ndrivers/net/wireless/morsemicro/mm81x/mac.c:2142:\t\tdev_err(mors-\u003edev, \"Failed to init firmware: %d\", ret);\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2143-\t\tgoto exit;\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c=2361=int mm81x_mac_register(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2389-\t * Trigger the receive workqueue to drain any incoming chip-to-host\ndrivers/net/wireless/morsemicro/mm81x/mac.c:2390:\t * pending packets been pushed in the period between the firmware\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2391-\t * initialization and interrupts being enabled.\n--\ndrivers/net/wireless/morsemicro/mm81x/skbq.c=34=struct mm81x_tx_status_priv {\n--\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-36-\t * Time (jiffies) at which this packet has spent too long the pending\ndrivers/net/wireless/morsemicro/mm81x/skbq.c:37:\t * queue, waiting for status notification from the firmware, and\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-38-\t * should be considered lost.\n--\ndrivers/net/wireless/morsemicro/mm81x/skbq.c=634=void mm81x_skbq_tx_complete(struct mm81x_skbq *mq, struct sk_buff_head *skbq)\n--\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-652-\t\t/*\ndrivers/net/wireless/morsemicro/mm81x/skbq.c:653:\t\t * If firmware doesn't give status on beacons just free\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-654-\t\t * them, otherwise queue and wait for response.\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c=98=struct mm81x_yaps_hw_aux_data {\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-131-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:132:\t/* DMA target buffer in firmware endian */\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-133-\tstruct mm81x_yaps_hw_status_regs hw_status_regs;\n"
} |
| 48/2 | 2026/09/21 14:26 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 50382 output: 43 thoughts: 382 Thoughts: **My Analysis of the USB Driver Initialization** Okay, let's break down this `mm81x_usb_probe` function. I see the usual suspects for a USB driver initialization: 1. We start with the core allocation: `mors = mm81x_core_alloc`. Allocating memory for our `musb` structure. 2. Next, we detect endpoints with `mm81x_usb_detect_endpoints`. Nothing out of the ordinary so far. 3. We're setting the `MM81X_USB_FLAG_ATTACHED` bit. Makes sense, we're attached. 4. Then, core initialization with `mm81x_core_init`. 5. Initializing the work queue with `INIT_WORK`. 6. Enabling the USB interrupt with `mm81x_usb_int_enable`. 7. Finally, registration with `mm81x_core_register`. Now, within the registration, we have `mm81x_mac_register`, which looks important, as this then calls `ieee80211_register_hw`. Okay, this is where the hardware abstraction is happening. The key observation here is that firmware *isn't* loaded in this initial probe function. That's a critical point to note. So, when does the firmware load then? Looks like `mm81x_fw_init` is called in `mm81x_mac_restart`! Ah, so `mm81x_mac_restart` is linked to interface events, more specifically `mm81x_mac_ops_add_interface`! Wait, this brings up another thought. How is `yaps` initialized? Where is `mm81x_yaps_init` called? Let's search the codebase for that function. This is key, to follow the whole setup flow! |
| 49/2 | 2026/09/21 14:26 | tool | grepper |
0mArgs:{
"Expression": "mm81x_yaps_init",
"PathPrefix": "drivers/net/wireless/morsemicro/mm81x"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/yaps.c=118=const struct mm81x_hif_ops mm81x_yaps_ops = {\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:119:\t.init = mm81x_yaps_init,\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-120-\t.flush_tx_data = mm81x_yaps_flush_tx_data,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c=598=static void mm81x_yaps_q_chip_full_timer_finish(struct mm81x_yaps *yaps)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-602-\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:603:int mm81x_yaps_init(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-604-{\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.h=59=struct mm81x_yaps_ops {\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.h-66-\ndrivers/net/wireless/morsemicro/mm81x/yaps.h:67:int mm81x_yaps_init(struct mm81x *mors);\ndrivers/net/wireless/morsemicro/mm81x/yaps.h-68-void mm81x_yaps_show(struct mm81x_yaps *yaps, struct seq_file *file);\n"
} |
| 50/2 | 2026/09/21 14:26 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 51685 output: 42 thoughts: 19 Thoughts: Here's my thought process, as if I were considering this question: **Tracing the `.init` Call in `mm81x_hif_ops`** Okay, so I need to figure out where the `.init` function within `mm81x_hif_ops` is actually invoked. This is crucial for understanding the driver's initialization sequence and potential interaction with the hardware. My first instinct is to dig into the broader code base. Where is `mm81x_hif_ops` itself *defined* and *used*? I'll start by searching for its declaration, likely in a header file related to the mm81x driver. Once I locate the definition, I'll then trace through its usage. I'll look for places where `mm81x_hif_ops` is assigned to a function pointer or structure member. That's likely going to point me toward the initial hook-up location. From there, it's a matter of tracing the execution path. I'll be looking for a function that calls `.init` directly. I need to understand if this `.init` is part of a larger initialization routine, such as a probe function, or if it is invoked by some other function. I'll be particularly interested in whether this `.init` is called early, during driver load, or later, perhaps when a specific hardware component is brought online. If I'm dealing with a device driver model (like the Linux kernel's), I'll pay close attention to the probe function (likely named something like `mm81x_probe`, `mm81x_init`, etc.), and then trace back the call chain to see the probe function being called by the system. And of course, I'll need to double check the code for any potential conditional initialization (such as based on platform specific configurations, device-tree bindings, etc.), that would affect whether the `.init` function is actually called. I'm assuming that the developers would have done a decent job of making it discoverable. I also should look for any error handling. What happens if `.init` fails? Does the driver handle it gracefully? Are there any specific error codes returned that I should be aware of? Are there any references to it using debugging macros? That could provide critical hints. |
| 51/2 | 2026/09/21 14:27 | tool | grepper |
0mArgs:{
"Expression": "-\u003einit\\(|hif_init",
"PathPrefix": "drivers/net/wireless/morsemicro/mm81x"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/core.c=67=int mm81x_core_init(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/core.c-89-\ndrivers/net/wireless/morsemicro/mm81x/core.c:90:\tret = mm81x_hif_init(mors);\ndrivers/net/wireless/morsemicro/mm81x/core.c-91-\tif (ret)\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=49=static inline void mm81x_hif_clear_events(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h-53-\ndrivers/net/wireless/morsemicro/mm81x/hif.h:54:static inline int mm81x_hif_init(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-55-{\ndrivers/net/wireless/morsemicro/mm81x/hif.h:56:\treturn mors-\u003ehif.ops-\u003einit(mors);\ndrivers/net/wireless/morsemicro/mm81x/hif.h-57-}\n"
} |
| 52/2 | 2026/09/21 14:27 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 52590 output: 47 thoughts: 18 Thoughts: Okay, let's dive into this `mm81x_yaps_init` function. I'm keen to understand its role. I'm imagining it's the initialization routine for the YAPS (Yet Another Peripheral System) subsystem, and I'm guessing "mm81x" probably refers to the specific memory management unit or a similar architectural component within this system. I want to figure out its responsibilities: what's it setting up? Is it configuring registers, allocating memory, enabling clocks, or handling interrupt vectors? Does it have any dependencies on other initialization routines? Knowing this will give me a better understanding of the overall system bringup and how the YAPS module integrates. This is the starting point for really digging into the code. |
| 53/2 | 2026/09/21 14:27 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/yaps.c",
"FirstLine": 603,
"LineCount": 50
}Results: {
"Contents": " 603:\tint mm81x_yaps_init(struct mm81x *mors)\n 604:\t{\n 605:\t\tint i, ret;\n 606:\t\tstruct mm81x_yaps *yaps;\n 607:\t\n 608:\t\tret = mm81x_yaps_hw_init(mors);\n 609:\t\tif (ret) {\n 610:\t\t\tdev_err(mors-\u003edev, \"mm81x_yaps_hw_init failed %d\", ret);\n 611:\t\t\treturn ret;\n 612:\t\t}\n 613:\t\n 614:\t\tyaps = \u0026mors-\u003ehif.u.yaps;\n 615:\t\tyaps-\u003emors = mors;\n 616:\t\n 617:\t\tmm81x_claim_bus(mors);\n 618:\t\n 619:\t\tret = mm81x_yaps_alloc_pkt_buffers(yaps);\n 620:\t\tif (ret) {\n 621:\t\t\tdev_err(mors-\u003edev, \"Failed to allocate YAPS packet buffers: %d\",\n 622:\t\t\t\tret);\n 623:\t\t\tmm81x_yaps_hw_finish(mors);\n 624:\t\t\tmm81x_release_bus(mors);\n 625:\t\t\treturn ret;\n 626:\t\t}\n 627:\t\n 628:\t\t/* YAPS is bi-directional */\n 629:\t\tmm81x_skbq_init(mors, \u0026yaps-\u003edata_rx_q,\n 630:\t\t\t\tMM81X_HIF_FLAGS_DATA | MM81X_HIF_FLAGS_DIR_TO_HOST);\n 631:\t\tmm81x_skbq_init(mors, \u0026yaps-\u003ebeacon_q,\n 632:\t\t\t\tMM81X_HIF_FLAGS_DATA | MM81X_HIF_FLAGS_DIR_TO_HOST);\n 633:\t\tmm81x_skbq_init(mors, \u0026yaps-\u003emgmt_q,\n 634:\t\t\t\tMM81X_HIF_FLAGS_DATA | MM81X_HIF_FLAGS_DIR_TO_HOST);\n 635:\t\n 636:\t\tfor (i = 0; i \u003c ARRAY_SIZE(yaps-\u003edata_tx_qs); i++) {\n 637:\t\t\tmm81x_skbq_init(mors, \u0026yaps-\u003edata_tx_qs[i],\n 638:\t\t\t\t\tMM81X_HIF_FLAGS_DATA |\n 639:\t\t\t\t\t\tMM81X_HIF_FLAGS_DIR_TO_CHIP);\n 640:\t\t}\n 641:\t\n 642:\t\tmm81x_skbq_init(mors, \u0026yaps-\u003ecmd_q,\n 643:\t\t\t\tMM81X_HIF_FLAGS_COMMAND | MM81X_HIF_FLAGS_DIR_TO_CHIP);\n 644:\t\tmm81x_skbq_init(mors, \u0026yaps-\u003ecmd_resp_q,\n 645:\t\t\t\tMM81X_HIF_FLAGS_COMMAND | MM81X_HIF_FLAGS_DIR_TO_HOST);\n 646:\t\n 647:\t\tmm81x_yaps_q_chip_full_timer_init(yaps);\n 648:\t\tINIT_WORK(\u0026mors-\u003ehif_work, mm81x_yaps_work);\n 649:\t\tINIT_WORK(\u0026mors-\u003etx_stale_work, mm81x_yaps_stale_tx_work);\n 650:\t\tmm81x_release_bus(mors);\n 651:\t\tmm81x_hw_enable_stop_notifications(mors, true);\n 652:\t\treturn 0;\n"
} |
| 54/2 | 2026/09/21 14:27 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 53823 output: 38 thoughts: 31 Thoughts: Okay, let's break this down. **Investigating the Assignment of `mors->hif.ops`** Alright, I need to understand the data flow here. My immediate question is: *How* is `mors->hif.ops` getting its value? I'm going to jump right into the code and start tracing the assignments. Specifically, I'm going to zero in on `mors->hif.ops` and see where, when, and how it's being set. This is a pretty standard debugging approach; just follow the trail and see where it leads. I need to understand this to then reason about its implications. Let's start with a direct lookup of that member in the codebase... |
| 55/2 | 2026/09/21 14:27 | tool | grepper |
0mArgs:{
"Expression": "hif\\.ops",
"PathPrefix": "drivers/net/wireless/morsemicro/mm81x"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/core.c=11=static int mm81x_core_attach_regs(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/core.c-26-\t\tmors-\u003eregs = \u0026mm8108_regs;\ndrivers/net/wireless/morsemicro/mm81x/core.c:27:\t\tmors-\u003ehif.ops = \u0026mm81x_yaps_ops;\ndrivers/net/wireless/morsemicro/mm81x/core.c-28-\t\tbreak;\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=54=static inline int mm81x_hif_init(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-55-{\ndrivers/net/wireless/morsemicro/mm81x/hif.h:56:\treturn mors-\u003ehif.ops-\u003einit(mors);\ndrivers/net/wireless/morsemicro/mm81x/hif.h-57-}\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=59=static inline void mm81x_hif_flush_tx_data(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-60-{\ndrivers/net/wireless/morsemicro/mm81x/hif.h:61:\tmors-\u003ehif.ops-\u003eflush_tx_data(mors);\ndrivers/net/wireless/morsemicro/mm81x/hif.h-62-}\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=64=static inline void mm81x_hif_flush_cmds(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-65-{\ndrivers/net/wireless/morsemicro/mm81x/hif.h:66:\tmors-\u003ehif.ops-\u003eflush_cmds(mors);\ndrivers/net/wireless/morsemicro/mm81x/hif.h-67-}\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=69=static inline void mm81x_hif_finish(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-70-{\ndrivers/net/wireless/morsemicro/mm81x/hif.h:71:\tmors-\u003ehif.ops-\u003efinish(mors);\ndrivers/net/wireless/morsemicro/mm81x/hif.h-72-}\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=74=static inline void mm81x_hif_skbq_get_tx_qs(struct mm81x *mors,\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h-76-{\ndrivers/net/wireless/morsemicro/mm81x/hif.h:77:\tmors-\u003ehif.ops-\u003eskbq_get_tx_qs(mors, qs, num_qs);\ndrivers/net/wireless/morsemicro/mm81x/hif.h-78-}\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=80=static inline struct mm81x_skbq *mm81x_hif_get_tx_cmd_queue(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-81-{\ndrivers/net/wireless/morsemicro/mm81x/hif.h:82:\treturn mors-\u003ehif.ops-\u003eget_tx_cmd_queue(mors);\ndrivers/net/wireless/morsemicro/mm81x/hif.h-83-}\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=86=mm81x_hif_get_tx_beacon_queue(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-87-{\ndrivers/net/wireless/morsemicro/mm81x/hif.h:88:\treturn mors-\u003ehif.ops-\u003eget_tx_beacon_queue(mors);\ndrivers/net/wireless/morsemicro/mm81x/hif.h-89-}\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=91=static inline struct mm81x_skbq *mm81x_hif_get_tx_mgmt_queue(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-92-{\ndrivers/net/wireless/morsemicro/mm81x/hif.h:93:\treturn mors-\u003ehif.ops-\u003eget_tx_mgmt_queue(mors);\ndrivers/net/wireless/morsemicro/mm81x/hif.h-94-}\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=96=static inline struct mm81x_skbq *mm81x_hif_get_tx_data_queue(struct mm81x *mors,\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h-98-{\ndrivers/net/wireless/morsemicro/mm81x/hif.h:99:\treturn mors-\u003ehif.ops-\u003eget_tx_data_queue(mors, aci);\ndrivers/net/wireless/morsemicro/mm81x/hif.h-100-}\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=102=static inline int mm81x_hif_handle_irq(struct mm81x *mors, u32 status)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-103-{\ndrivers/net/wireless/morsemicro/mm81x/hif.h:104:\treturn mors-\u003ehif.ops-\u003ehandle_irq(mors, status);\ndrivers/net/wireless/morsemicro/mm81x/hif.h-105-}\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=107=static inline int mm81x_hif_get_tx_buffered_count(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-108-{\ndrivers/net/wireless/morsemicro/mm81x/hif.h:109:\treturn mors-\u003ehif.ops-\u003eget_tx_buffered_count(mors);\ndrivers/net/wireless/morsemicro/mm81x/hif.h-110-}\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=112=static inline int mm81x_hif_get_tx_status_pending_count(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-113-{\ndrivers/net/wireless/morsemicro/mm81x/hif.h:114:\treturn mors-\u003ehif.ops-\u003eget_tx_status_pending_count(mors);\ndrivers/net/wireless/morsemicro/mm81x/hif.h-115-}\n"
} |
| 56/2 | 2026/09/21 14:27 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 55983 output: 45 thoughts: 57 Thoughts: **Investigating the `mm81x_yaps_ops` Structure** Okay, so I'm digging into this `mm81x_yaps_ops` structure. My first thought is, where exactly is the `yaps->ops` member assigned? I need to trace this back to its initialization. Right, a quick scan suggests the place to look is `drivers/net/wireless/morsemicro/mm81x/yaps_hw.c`. Let's jump over there and see what we can find. It's a pretty standard approach: figure out the structure's origin point. |
| 57/2 | 2026/09/21 14:27 | tool | grepper |
0mArgs:{
"Expression": "mm81x_yaps_hw_ops",
"PathPrefix": "drivers/net/wireless/morsemicro/mm81x"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/yaps_hw.c=566=static int mm81x_yaps_hw_update_status(struct mm81x_yaps *yaps)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-643-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:644:static const struct mm81x_yaps_ops mm81x_yaps_hw_ops = {\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-645-\t.write_pkts = mm81x_yaps_hw_write_pkts,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c=650=int mm81x_yaps_hw_init(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-683-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:684:\tyaps-\u003eops = \u0026mm81x_yaps_hw_ops;\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-685-\treturn ret;\n"
} |
| 58/2 | 2026/09/21 14:27 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 56572 output: 49 thoughts: 104 Thoughts: **Digging into the YAPS Hardware Initialization** Okay, so I see that `yaps->ops` is being assigned a pointer to `mm81x_yaps_hw_ops` within `mm81x_yaps_hw_init`. That's the key initialization step! And from what I see here, `mm81x_yaps_hw_ops.read_pkts` is assigned to `mm81x_yaps_hw_read_pkts`. Right, right. Now, I need to confirm that this is where the `yaps` hardware is really initialized. Let me go take a look at the `mm81x_yaps_hw_init` function in `yaps_hw.c` to be sure. It's time to confirm these assumptions and ensure this is the proper code path. |
| 59/2 | 2026/09/21 14:27 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/yaps_hw.c",
"FirstLine": 650,
"LineCount": 45
}Results: {
"Contents": " 650:\tint mm81x_yaps_hw_init(struct mm81x *mors)\n 651:\t{\n 652:\t\tint ret = 0;\n 653:\t\tstruct mm81x_yaps *yaps = NULL;\n 654:\t\tint aux_data_len = sizeof(struct mm81x_yaps_hw_aux_data);\n 655:\t\tint alignment = mm81x_bus_get_alignment(mors);\n 656:\t\n 657:\t\tyaps = \u0026mors-\u003ehif.u.yaps;\n 658:\t\tyaps-\u003eaux_data = kzalloc(aux_data_len, GFP_KERNEL);\n 659:\t\tif (!yaps-\u003eaux_data) {\n 660:\t\t\tret = -ENOMEM;\n 661:\t\t\tgoto err_exit;\n 662:\t\t}\n 663:\t\n 664:\t\tyaps-\u003eaux_data-\u003eto_chip_buffer =\n 665:\t\t\tkzalloc(YAPS_HW_WINDOW_SIZE_BYTES + alignment - 1, GFP_KERNEL);\n 666:\t\tif (!yaps-\u003eaux_data-\u003eto_chip_buffer) {\n 667:\t\t\tret = -ENOMEM;\n 668:\t\t\tgoto err_exit;\n 669:\t\t}\n 670:\t\n 671:\t\tyaps-\u003eaux_data-\u003efrom_chip_buffer =\n 672:\t\t\tkzalloc(YAPS_HW_WINDOW_SIZE_BYTES + alignment - 1, GFP_KERNEL);\n 673:\t\tif (!yaps-\u003eaux_data-\u003efrom_chip_buffer) {\n 674:\t\t\tret = -ENOMEM;\n 675:\t\t\tgoto err_exit;\n 676:\t\t}\n 677:\t\n 678:\t\tif (!IS_ALIGNED((uintptr_t)\u0026yaps-\u003eaux_data-\u003estatus_regs, alignment)) {\n 679:\t\t\tdev_warn(mors-\u003edev,\n 680:\t\t\t\t \"Status registers are not aligned to %d bytes\",\n 681:\t\t\t\t alignment);\n 682:\t\t}\n 683:\t\n 684:\t\tyaps-\u003eops = \u0026mm81x_yaps_hw_ops;\n 685:\t\treturn ret;\n 686:\t\n 687:\terr_exit:\n 688:\t\tmm81x_yaps_hw_finish(mors);\n 689:\t\treturn ret;\n 690:\t}\n 691:\t\n 692:\tvoid mm81x_yaps_hw_finish(struct mm81x *mors)\n 693:\t{\n 694:\t\tstruct mm81x_yaps *yaps;\n"
} |
| 60/2 | 2026/09/21 14:27 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 57638 output: 44 thoughts: 61 Thoughts: Here's my take on that code snippet: **Diving into `mm81x_core_attach_regs`** Alright, time to understand the flow of `mm81x_core_attach_regs`. I need to figure out where the `mm8108_regs` struct or, more likely, how `mors->regs` is getting initialized. This usually means tracking down where the memory for that structure is allocated and populated with the register offsets. Let's start by scrutinizing `core.c`, specifically the first forty lines, to see if I can find the answer. It's usually either a statically defined struct, allocated with `kmalloc` or similar, or potentially mapped from an external memory region. Gotta trace it back to the source! |
| 61/2 | 2026/09/21 14:27 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/core.c",
"FirstLine": 1,
"LineCount": 40
}Results: {
"Contents": " 1:\t// SPDX-License-Identifier: GPL-2.0-only\n 2:\t/*\n 3:\t * Copyright (c) 2017-2026 Morse Micro\n 4:\t */\n 5:\t#include \u003clinux/module.h\u003e\n 6:\t#include \"core.h\"\n 7:\t#include \"bus.h\"\n 8:\t#include \"hif.h\"\n 9:\t#include \"mac.h\"\n 10:\t\n 11:\tstatic int mm81x_core_attach_regs(struct mm81x *mors)\n 12:\t{\n 13:\t\tint ret = 0;\n 14:\t\n 15:\t\tmm81x_claim_bus(mors);\n 16:\t\tret = mm81x_reg32_read(mors, MM8108_REG_CHIP_ID, \u0026mors-\u003echip_id);\n 17:\t\tmm81x_release_bus(mors);\n 18:\t\n 19:\t\tif (ret \u003c 0) {\n 20:\t\t\tdev_err(mors-\u003edev, \"failed to read chip id %d\", ret);\n 21:\t\t\treturn ret;\n 22:\t\t}\n 23:\t\n 24:\t\tswitch (mors-\u003echip_id) {\n 25:\t\tcase (CHIP_ID_MM8108):\n 26:\t\t\tmors-\u003eregs = \u0026mm8108_regs;\n 27:\t\t\tmors-\u003ehif.ops = \u0026mm81x_yaps_ops;\n 28:\t\t\tbreak;\n 29:\t\tdefault:\n 30:\t\t\treturn -ENODEV;\n 31:\t\t}\n 32:\t\n 33:\t\treturn ret;\n 34:\t}\n 35:\t\n 36:\tstatic void mm81x_core_init_mac_addr(struct mm81x *mors)\n 37:\t{\n 38:\t\tint ret = mm81x_hw_otp_get_mac_addr(mors);\n 39:\t\n 40:\t\tif (ret || !is_valid_ether_addr(mors-\u003emacaddr))\n"
} |
| 62/2 | 2026/09/21 14:27 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 58482 output: 47 thoughts: 613 Thoughts: **Analyzing the mm81x Chip Unresponsive State** Okay, let's take a look at this `mm81x_yaps_work` function. Hmm, it seems to immediately return if the `MM81X_STATE_CHIP_UNRESPONSIVE` bit is set. That's a good starting point, but I need to understand the lifecycle of this flag. When is it *cleared*? That's the crucial question here. Time to do some digging. Let's see...I've already grepped for where this flag is set, cleared, or tested. Okay, so it's set in `core.c` during initialization, and also in `usb.c`, and tested (as we already know) in `yaps.c`. Critically, I see it's cleared in `mac.c` in `mm81x_mac_restart`. Ah, interesting. So it's initially set during the core initialization, and then *only* cleared within `mm81x_mac_restart`. This implies `mm81x_mac_restart` is critical to bring the chip back to a responsive state. Now, I need to know under what circumstances `mm81x_mac_restart` is called. Let's trace that call. Okay, `mm81x_mac_ops_add_interface` looks promising. There, if `MM81X_STATE_RELOAD_FW_AFTER_START` is set, `mm81x_mac_restart` is called. Need to check further around line 2170 in `mac.c`! This is how the chip is potentially "revived". I'll investigate the conditions of that flag being set! |
| 63/2 | 2026/09/21 14:27 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/mac.c",
"FirstLine": 2168,
"LineCount": 50
}Results: {
"Contents": "2168:\t}\n2169:\t\n2170:\tstatic int mm81x_mac_ops_add_interface(struct ieee80211_hw *hw,\n2171:\t\t\t\t\t struct ieee80211_vif *vif)\n2172:\t{\n2173:\t\tint ret = 0;\n2174:\t\tstruct mm81x *mors = hw-\u003epriv;\n2175:\t\tstruct mm81x_vif *mors_vif = (struct mm81x_vif *)vif-\u003edrv_priv;\n2176:\t\n2177:\t\tif (test_bit(MM81X_STATE_RELOAD_FW_AFTER_START, \u0026mors-\u003estate_flags)) {\n2178:\t\t\tdev_info(mors-\u003edev, \"Restarting chip with regdom: %s\",\n2179:\t\t\t\t mors-\u003ecountry);\n2180:\t\n2181:\t\t\tret = mm81x_mac_restart(mors);\n2182:\t\t\tif (ret) {\n2183:\t\t\t\tdev_err(mors-\u003edev, \"Failed to restart chip\");\n2184:\t\t\t\treturn ret;\n2185:\t\t\t}\n2186:\t\n2187:\t\t\t/*\n2188:\t\t\t * mac_restart will trigger ieee80211_hw_restart and\n2189:\t\t\t * add_interface will re-enter. just exit here instead.\n2190:\t\t\t */\n2191:\t\t\treturn 0;\n2192:\t\t}\n2193:\t\n2194:\t\tvif-\u003edriver_flags |= IEEE80211_VIF_BEACON_FILTER;\n2195:\t\tmors_vif-\u003emors = mors;\n2196:\t\n2197:\t\tret = mm81x_cmd_add_if(mors, \u0026mors_vif-\u003eid, vif-\u003eaddr, vif-\u003etype);\n2198:\t\tif (ret) {\n2199:\t\t\tdev_err(mors-\u003edev, \"mm81x_cmd_add_if failed %d\", ret);\n2200:\t\t\treturn ret;\n2201:\t\t}\n2202:\t\n2203:\t\tif (mors_vif-\u003eid \u003e= ARRAY_SIZE(mors-\u003evifs)) {\n2204:\t\t\tdev_err(mors-\u003edev, \"vif_id is too large %u\", mors_vif-\u003eid);\n2205:\t\t\tret = -EOPNOTSUPP;\n2206:\t\t\treturn ret;\n2207:\t\t}\n2208:\t\n2209:\t\tif (mors_vif-\u003eid != (mors_vif-\u003eid \u0026 MM81X_TX_CONF_FLAGS_VIF_ID_MASK)) {\n2210:\t\t\tdev_err(mors-\u003edev, \"invalid vif_id %u\", mors_vif-\u003eid);\n2211:\t\t\tret = -EOPNOTSUPP;\n2212:\t\t\treturn ret;\n2213:\t\t}\n2214:\t\n2215:\t\trcu_assign_pointer(mors-\u003evifs[mors_vif-\u003eid], vif);\n2216:\t\n2217:\t\tif (vif-\u003etype == NL80211_IFTYPE_AP)\n"
} |
| 64/2 | 2026/09/21 14:27 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 60392 output: 46 thoughts: 129 Thoughts: **Analyzing the MAC Restart Process** Okay, here we go. I'm looking at this `mm81x_mac_restart` function and immediately something jumps out at me: `mm81x_fw_init`. Wait a second! What is `mm81x_fw_init` actually *doing*? I can see it's called with a `true` argument, which likely means some form of initialization, but I need to dig deeper. This looks like a critical step, especially since a failure leads to an error and immediate exit. Right, time to go track down the source code for `mm81x_fw_init`. Let's see... it's probably in the `drivers/net/wireless/morsemicro/mm81x/fw.c` file. I need to understand what this firmware initialization is doing before I can properly assess the restart process and determine what error scenarios might be triggered by a failure. This could involve loading firmware, verifying its integrity, perhaps some hardware configuration... I need to read the code to be sure. This function is likely where any real issues will be. |
| 65/2 | 2026/09/21 14:27 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/fw.c",
"FirstLine": 690,
"LineCount": 60
}Results: {
"Contents": " 690:\t\n 691:\tint mm81x_fw_init(struct mm81x *mors, bool reset)\n 692:\t{\n 693:\t\tint ret;\n 694:\t\tint board_id;\n 695:\t\tchar *bcf_path = NULL;\n 696:\t\tconst struct firmware *fw = NULL;\n 697:\t\tconst struct firmware *bcf = NULL;\n 698:\t\n 699:\t\tboard_id = mm81x_hw_otp_get_board_type(mors);\n 700:\t\n 701:\t\tif (!mm81x_hw_otp_valid_board_type(board_id)) {\n 702:\t\t\tdev_err(mors-\u003edev,\n 703:\t\t\t\t\"OTP not set, unable to determine BCF to use\");\n 704:\t\t\tret = -EINVAL;\n 705:\t\t\tgoto out;\n 706:\t\t}\n 707:\t\n 708:\t\tdev_dbg(mors-\u003edev, \"Using board type 0x%04x from OTP\", board_id);\n 709:\t\n 710:\t\tret = mm81x_fw_request(mors, \u0026fw);\n 711:\t\tif (ret)\n 712:\t\t\tgoto out;\n 713:\t\n 714:\t\tbcf_path = kasprintf(GFP_KERNEL,\n 715:\t\t\t\t MM81X_FW_DIR\n 716:\t\t\t\t \"/v%u/bcf_boardtype_%04x\" MM81X_FW_EXT,\n 717:\t\t\t\t mors-\u003efw_major, board_id);\n 718:\t\tif (!bcf_path) {\n 719:\t\t\tret = -ENOMEM;\n 720:\t\t\tgoto out;\n 721:\t\t}\n 722:\t\n 723:\t\tret = request_firmware(\u0026bcf, bcf_path, mors-\u003edev);\n 724:\t\tif (ret) {\n 725:\t\t\tif (ret == -ENOENT)\n 726:\t\t\t\tdev_err(mors-\u003edev, \"BCF %s not found\\n\", bcf_path);\n 727:\t\t\tgoto out;\n 728:\t\t}\n 729:\t\n 730:\t\tdev_info(mors-\u003edev, \"Loaded BCF from %s, size %zu, crc32 0x%08x\\n\",\n 731:\t\t\t bcf_path, bcf-\u003esize, binary_crc(bcf));\n 732:\t\n 733:\t\tret = mm81x_fw_flash(mors, fw, bcf, reset);\n 734:\t\tif (ret) {\n 735:\t\t\tdev_err(mors-\u003edev, \"failed to flash firmware: %d\", ret);\n 736:\t\t\tgoto out;\n 737:\t\t}\n 738:\t\n 739:\t\tret = mm81x_fw_get_flags(mors);\n 740:\t\n 741:\tout:\n 742:\t\trelease_firmware(fw);\n 743:\t\trelease_firmware(bcf);\n 744:\t\tkfree(bcf_path);\n 745:\t\n 746:\t\tif (ret)\n 747:\t\t\tdev_err(mors-\u003edev, \"failed to init firmware: %d\", ret);\n 748:\t\telse\n 749:\t\t\tdev_dbg(mors-\u003edev, \"firmware initialised\");\n"
} |
| 66/2 | 2026/09/21 14:27 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 61743 output: 46 thoughts: 745 Thoughts: **My Analysis of Syzkaller Fuzzing Reachability for mm81x Firmware** Okay, first things first, is `request_firmware` even going to work in a syzkaller fuzzing environment? That's the core question. Does syzkaller even *have* the firmware files for `morsemicro/mm81x/v56/bcf_boardtype_...`? Usually, those external firmware files are a no-go. But then, hold on... what if `mm81x_yaps_hw_read_pkts` *is* called elsewhere, perhaps independently of `request_firmware`? Is `request_firmware` the *only* entry point to the code? What if there's a userland mechanism to load the firmware, or maybe syzkaller has a firmware loader that I'm not aware of? Or... is the firmware simply *not* present? Need to rule out all possibilities. Right, time to consult the syzkaller reachability rules. I need to be *absolutely* sure about this. Let's dig into Sections 1, 2, and 3. * **Section 1: Reachability is Paramount.** It's all about what's actually *executable* in standard virtualized environments. If the code is structurally unreachable, it's a no-go, assertions or fancy logic be damned. * **Section 2: The Negative Criteria (When to Return `WorthFuzzing=false`).** This is the list of *exclusions*: non-kernel changes, unreachable hardware (specific PCIe, SmartNIC, or GPU drivers), and unreachable execution paths (like driver teardown callbacks that depend on hot-unplug or architecture-specific code). * **Section 3: The Positive Criteria (When to Return `WorthFuzzing=true`).** This is what *does* get fuzzed: code that *is* reachable and executable, including core subsystems, refactorings, runtime assertions, and importantly, "Reachable Drivers and Protocols" including virtual buses. Okay, let's zoom in on that list... "Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.)" *USB gadget*! This is a USB wireless driver we are working on! And I *know* there's `CONFIG_MM81X_USB`! *Wait*... can `mm81x_usb_probe` actually probe via USB gadget/Raw Gadget? I have to look at `mm81x_usb_table` in `usb.c` and confirm that the USB Gadget is a path! |
| 67/2 | 2026/09/21 14:27 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/usb.c",
"FirstLine": 520,
"LineCount": 40
}Results: {
"Contents": " 520:\t\n 521:\tstatic int mm81x_usb_reg32_write(struct mm81x *mors, u32 address, u32 val)\n 522:\t{\n 523:\t\tint ret = 0;\n 524:\t\tstruct mm81x_usb *musb = (struct mm81x_usb *)mors-\u003edrv_priv;\n 525:\t\t__le32 val_le = cpu_to_le32(val);\n 526:\t\n 527:\t\tret = mm81x_usb_mem_write(musb, address, (u8 *)\u0026val_le, sizeof(val_le));\n 528:\t\tif (ret == sizeof(val_le))\n 529:\t\t\treturn 0;\n 530:\t\n 531:\t\tdev_err(mors-\u003edev, \"usb reg32 write failed %d\", ret);\n 532:\t\treturn ret;\n 533:\t}\n 534:\t\n 535:\tstatic void mm81x_usb_bus_enable(struct mm81x *mors, bool enable)\n 536:\t{\n 537:\t\tstruct mm81x_usb *musb = (struct mm81x_usb *)mors-\u003edrv_priv;\n 538:\t\n 539:\t\tif (enable)\n 540:\t\t\tusb_autopm_get_interface(musb-\u003einterface);\n 541:\t\telse\n 542:\t\t\tusb_autopm_put_interface(musb-\u003einterface);\n 543:\t}\n 544:\t\n 545:\tstatic void mm81x_usb_claim_bus(struct mm81x *mors)\n 546:\t{\n 547:\t\tstruct mm81x_usb *musb = (struct mm81x_usb *)mors-\u003edrv_priv;\n 548:\t\n 549:\t\tmutex_lock(\u0026musb-\u003ebus_lock);\n 550:\t}\n 551:\t\n 552:\tstatic void mm81x_usb_release_bus(struct mm81x *mors)\n 553:\t{\n 554:\t\tstruct mm81x_usb *musb = (struct mm81x_usb *)mors-\u003edrv_priv;\n 555:\t\n 556:\t\tmutex_unlock(\u0026musb-\u003ebus_lock);\n 557:\t}\n 558:\t\n 559:\tstatic void mm81x_usb_set_irq(struct mm81x *mors, bool enable)\n"
} |
| 68/2 | 2026/09/21 14:27 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 63795 output: 42 thoughts: 17 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Analyzing the USB Device Table** Okay, let's dive in. My immediate focus is on the `mm81x_usb_table`. I need to understand its structure and contents. This table is *critical* for the device's USB enumeration and driver binding. I'm expecting to see entries detailing the supported USB vendor and product IDs, device classes, subclasses, protocols, and, of course, the corresponding driver functions or data structures. I'm assuming it uses a standard approach for matching devices, but I need to quickly ascertain the level of configurability this table provides. I'll be looking for any hints on how the system handles different device types, particularly if there's any clever handling of composite devices or quirks. My aim is to grasp the core device identification logic and how the system selects the appropriate driver for a connected USB device, or at least how to quickly find the appropriate function calls within the codebase. |
| 69/2 | 2026/09/21 14:27 | tool | grepper |
0mArgs:{
"Expression": "mm81x_usb_table",
"PathPrefix": "drivers/net/wireless/morsemicro/mm81x"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/usb.c=81=struct mm81x_usb_command {\n--\ndrivers/net/wireless/morsemicro/mm81x/usb.c-86-\ndrivers/net/wireless/morsemicro/mm81x/usb.c:87:static const struct usb_device_id mm81x_usb_table[] = {\ndrivers/net/wireless/morsemicro/mm81x/usb.c-88-\t{ USB_DEVICE(MM81X_VENDOR_ID, MM81X_MM810X_PRODUCT_ID) },\n--\ndrivers/net/wireless/morsemicro/mm81x/usb.c-91-\ndrivers/net/wireless/morsemicro/mm81x/usb.c:92:MODULE_DEVICE_TABLE(usb, mm81x_usb_table);\ndrivers/net/wireless/morsemicro/mm81x/usb.c-93-\n--\ndrivers/net/wireless/morsemicro/mm81x/usb.c=925=static struct usb_driver mm81x_usb_driver = {\n--\ndrivers/net/wireless/morsemicro/mm81x/usb.c-933-\t.post_reset = mm81x_usb_post_reset,\ndrivers/net/wireless/morsemicro/mm81x/usb.c:934:\t.id_table = mm81x_usb_table,\ndrivers/net/wireless/morsemicro/mm81x/usb.c-935-\t.supports_autosuspend = 1,\n"
} |
| 70/2 | 2026/09/21 14:27 | llm | patch-evaluator-compressor |
1mModel:gemini-3.8-flash Args: null Results: null Reply: ### Analysis Summary
#### 1. Approaches Tried and Results
- **Patch Under Review**:
- Commit `0ffa363bb947a4fc8b8cbb1ffa89fbf41b792e59` modifying `drivers/net/wireless/morsemicro/mm81x/yaps_hw.c` inside `mm81x_yaps_hw_read_pkts`.
- Added a boundary check:
```c
if (bytes_remaining < (int)sizeof(delim))
break;
```
prevents reading past the aligned DMA chip buffer when insufficient bytes remain for reading `delim` (4 bytes).
- **Driver Architecture & Bus Support**:
- Inspected `drivers/net/wireless/morsemicro/mm81x/`:
- Bus drivers: `usb.c` (`CONFIG_MM81X_USB`) and `sdio.c` (`CONFIG_MM81X_SDIO`).
- Core logic: `core.c`, `mac.c`, `yaps.c`, `yaps_hw.c`, `fw.c`, etc. (`CONFIG_MM81X`).
- Evaluated reachability via virtual buses:
- `mm81x_usb.c` registers standard USB driver `mm81x_usb_driver` (`MM81X_VENDOR_ID` 0x325b, `MM81X_MM810X_PRODUCT_ID` 0x8100).
- Can be probed via standard USB emulation / Raw Gadget in QEMU / syzkaller.
- **Call Chain to Modified Function (`mm81x_yaps_hw_read_pkts`)**:
- `mm81x_yaps_hw_ops.read_pkts = mm81x_yaps_hw_read_pkts`
- Called via `mm81x_yaps_read_pkts()` in `yaps.c` -> invoked by `mm81x_yaps_rx_handler()`
- Scheduled in `mm81x_yaps_work()` (workqueue handler for `mors->hif_work`), triggered when `MM81X_HIF_EVT_RX_PEND` flag is set on `mors->hif.event_flags`.
- `mors->hif_work` is queued in:
- `mm81x_mac_register()`: immediately sets `MM81X_HIF_EVT_RX_PEND` and queues `hif_work`.
- `mm81x_yaps_irq_handler()` on hardware interrupt.
- `mm81x_skbq_tx()`, `mm81x_yaps_work()`, `mm81x_yaps_tx_q_full_timer()`.
- **State Flags & Execution Guard Investigation**:
- In `mm81x_yaps_work()`:
```c
if (test_bit(MM81X_STATE_CHIP_UNRESPONSIVE, &mors->state_flags))
return;
```
- Traced flag `MM81X_STATE_CHIP_UNRESPONSIVE`:
- Set during `mm81x_core_init()` and on USB disconnect / URB error.
- Cleared in `mm81x_mac_restart()`.
- Traced callers of `mm81x_mac_restart()`:
- Called from `mm81x_mac_ops_add_interface()` (mac80211 callback triggered by user space / nl80211 creating an interface).
- Called from `mm81x_reg_notifier()`.
- Note in `mm81x_mac_restart()`:
- Reads `MM81X_REG_CHIP_ID(mors)` via USB register read (`mm81x_dm_read` / URBs).
- Calls `mm81x_fw_init()` which requests firmware via `request_firmware()`.
- Calls `mm81x_fw_parse_ext_host_tbl()`.
- Clears `MM81X_STATE_CHIP_UNRESPONSIVE`.
- Re-enables interrupts and calls `ieee80211_restart_hw()`.
#### 2. Current Hypotheses & Reachability Evaluation
- **Reachability Assessment**:
- The driver is a USB wireless network driver (`CONFIG_MM81X_USB`).
- USB devices are emulated by syzkaller using USB Raw Gadget / syz_usb pseudo-syscalls.
- The patch modifies packet deserialization logic (`mm81x_yaps_hw_read_pkts`) in `yaps_hw.c`, fixing an out-of-bounds read when remaining bytes in the buffer are less than 4 (`sizeof(delim)`).
- Reachability via USB emulation:
- USB device enumeration probes `mm81x_usb_probe()`.
- Interface creation via standard `nl80211` (`RTM_NEWLINK` or `NL80211_CMD_NEW_INTERFACE`) invokes `mm81x_mac_ops_add_interface()`.
- In fuzzing environments with Raw Gadget / USB emulation providing responses, `mm81x_yaps_hw_read_pkts` is executed upon receiving RX packets / interrupts.
- Therefore, this is reachable driver code on virtualizable USB bus.
- **WorthFuzzing Decision**:
- `WorthFuzzing = true`
- Addresses memory safety / out-of-bounds read in packet parser for incoming device data.
#### 3. Key Files, Functions, and Structs
- **Files**:
- `drivers/net/wireless/morsemicro/mm81x/yaps_hw.c` (modified file)
- `drivers/net/wireless/morsemicro/mm81x/yaps.c`
- `drivers/net/wireless/morsemicro/mm81x/mac.c`
- `drivers/net/wireless/morsemicro/mm81x/usb.c`
- `drivers/net/wireless/morsemicro/mm81x/Kconfig`
- **Functions**:
- `mm81x_yaps_hw_read_pkts` (modified function)
- `mm81x_yaps_rx_handler`
- `mm81x_yaps_work`
- `mm81x_mac_restart`
- `mm81x_usb_probe`
- **Kconfig Options Needed**:
- `MM81X`
- `MM81X_USB`
- Dependencies: `MAC80211`, `USB`, `NETDEVICES`, `WLAN`
#### 4. Watchouts / Pitfalls
- `mm81x_yaps_hw_read_pkts` is static, registered in `mm81x_yaps_hw_ops.read_pkts`. FocusSymbols should include `mm81x_yaps_hw_read_pkts` (or direct caller `mm81x_yaps_rx_handler` / `mm81x_yaps_work`). Avoid ubiquitous functions like workqueue runners or general USB core functions.
- Do not loop on further file reads; reachability and configuration requirements are sufficiently established. Next step is to invoke `set-results`.Tokens: input: 47330 output: 1740 thoughts: 0 |
| 71/2 | 2026/09/21 14:29 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 21601 output: 46 thoughts: 0 |
| 72/2 | 2026/09/21 14:29 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/usb.c",
"FirstLine": 850,
"LineCount": 80
}Results: {
"Contents": " 850:\t\tstruct mm81x_usb *musb = (struct mm81x_usb *)mors-\u003edrv_priv;\n 851:\t\tstruct mm81x_usb_endpoint *int_ep = \u0026musb-\u003eendpoints[MM81X_EP_INT];\n 852:\t\tstruct mm81x_usb_endpoint *rd_ep = \u0026musb-\u003eendpoints[MM81X_EP_MEM_RD];\n 853:\t\tstruct mm81x_usb_endpoint *wr_ep = \u0026musb-\u003eendpoints[MM81X_EP_MEM_WR];\n 854:\t\tstruct mm81x_usb_endpoint *cmd_ep = \u0026musb-\u003eendpoints[MM81X_EP_CMD];\n 855:\t\n 856:\t\tif (!test_bit(MM81X_USB_FLAG_ATTACHED, \u0026musb-\u003eflags))\n 857:\t\t\treturn -ENODEV;\n 858:\t\n 859:\t\tusb_kill_urb(int_ep-\u003eurb);\n 860:\t\tusb_kill_urb(rd_ep-\u003eurb);\n 861:\t\tusb_kill_urb(wr_ep-\u003eurb);\n 862:\t\tusb_kill_urb(cmd_ep-\u003eurb);\n 863:\t\n 864:\t\t/* Locking the bus. No USB communication after this point */\n 865:\t\tmm81x_usb_claim_bus(mors);\n 866:\t\tmutex_lock(\u0026musb-\u003elock);\n 867:\t\n 868:\t\tset_bit(MM81X_USB_FLAG_SUSPENDED, \u0026musb-\u003eflags);\n 869:\t\treturn 0;\n 870:\t}\n 871:\t\n 872:\tstatic int mm81x_usb_resume(struct usb_interface *intf)\n 873:\t{\n 874:\t\tstruct mm81x *mors = usb_get_intfdata(intf);\n 875:\t\tstruct mm81x_usb *musb = (struct mm81x_usb *)mors-\u003edrv_priv;\n 876:\t\tint ret;\n 877:\t\tstruct mm81x_usb_endpoint *int_ep = \u0026musb-\u003eendpoints[MM81X_EP_INT];\n 878:\t\n 879:\t\tif (!test_bit(MM81X_USB_FLAG_ATTACHED, \u0026musb-\u003eflags))\n 880:\t\t\treturn -ENODEV;\n 881:\t\n 882:\t\tret = usb_submit_urb(int_ep-\u003eurb, GFP_KERNEL);\n 883:\t\tif (ret)\n 884:\t\t\tdev_err(mors-\u003edev, \"Couldn't submit urb. Error number %d\", ret);\n 885:\t\n 886:\t\tmm81x_usb_release_bus(mors);\n 887:\t\tmutex_unlock(\u0026musb-\u003elock);\n 888:\t\n 889:\t\tclear_bit(MM81X_USB_FLAG_SUSPENDED, \u0026musb-\u003eflags);\n 890:\t\treturn 0;\n 891:\t}\n 892:\t\n 893:\tstatic int mm81x_usb_reset_resume(struct usb_interface *intf)\n 894:\t{\n 895:\t\tstruct mm81x *mors = usb_get_intfdata(intf);\n 896:\t\tstruct mm81x_usb *musb = (struct mm81x_usb *)mors-\u003edrv_priv;\n 897:\t\tint ret;\n 898:\t\tstruct mm81x_usb_endpoint *int_ep = \u0026musb-\u003eendpoints[MM81X_EP_INT];\n 899:\t\n 900:\t\tif (!test_bit(MM81X_USB_FLAG_ATTACHED, \u0026musb-\u003eflags))\n 901:\t\t\treturn -ENODEV;\n 902:\t\n 903:\t\tret = usb_submit_urb(int_ep-\u003eurb, GFP_KERNEL);\n 904:\t\tif (ret)\n 905:\t\t\tdev_err(mors-\u003edev, \"Couldn't submit urb. Error number %d\", ret);\n 906:\t\n 907:\t\tmm81x_usb_release_bus(mors);\n 908:\t\tmutex_unlock(\u0026musb-\u003elock);\n 909:\t\n 910:\t\tclear_bit(MM81X_USB_FLAG_SUSPENDED, \u0026musb-\u003eflags);\n 911:\t\n 912:\t\treturn 0;\n 913:\t}\n 914:\t\n 915:\tstatic int mm81x_usb_pre_reset(struct usb_interface *intf)\n 916:\t{\n 917:\t\treturn 0;\n 918:\t}\n 919:\t\n 920:\tstatic int mm81x_usb_post_reset(struct usb_interface *intf)\n 921:\t{\n 922:\t\treturn 0;\n 923:\t}\n 924:\t\n 925:\tstatic struct usb_driver mm81x_usb_driver = {\n 926:\t\t.name = \"mm81x_usb\",\n 927:\t\t.probe = mm81x_usb_probe,\n 928:\t\t.disconnect = mm81x_usb_disconnect,\n 929:\t\t.suspend = mm81x_usb_suspend,\n"
} |
| 73/2 | 2026/09/21 14:29 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 23076 output: 43 thoughts: 20 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience: **Diving into the mm81x Kconfig** Alright, before I go any further down this path, I need to get the definitive truth from the source. Forget guesswork, it's time to crack open the Kconfig for mm81x. I need the hard facts on configuration options, the exact names and meanings, and especially the dependencies. I can't afford to waste time chasing shadows or making assumptions about what's enabled, disabled, or conditionally compiled. Knowing these dependencies is absolutely critical – what other features *must* be set, or *cannot* be set, for mm81x to behave as expected? I need to build a mental model of the mm81x configuration space, and that model needs to be dead accurate. So, Kconfig it is. Let's see what's what. |
| 74/2 | 2026/09/21 14:29 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/Kconfig",
"FirstLine": 1,
"LineCount": 40
}Results: {
"Contents": " 1:\t# SPDX-License-Identifier: GPL-2.0\n 2:\t\n 3:\tconfig MM81X\n 4:\t\ttristate \"Morse Micro MM81x wireless devices\" if COMPILE_TEST\n 5:\t\tdepends on MAC80211\n 6:\t\tselect FW_LOADER\n 7:\t\tselect CRC7\n 8:\t\thelp\n 9:\t\t This module adds support for wireless devices based\n 10:\t\t on Morse Micro MM81xx chipsets.\n 11:\t\n 12:\tconfig MM81X_USB\n 13:\t\ttristate \"Morse Micro MM81x USB support\"\n 14:\t\tdepends on MAC80211 \u0026\u0026 USB\n 15:\t\tselect MM81X\n 16:\t\thelp\n 17:\t\t This module adds support for the USB interface of\n 18:\t\t devices using the Morse Micro MM81x chipset.\n 19:\t\n 20:\tconfig MM81X_SDIO\n 21:\t\ttristate \"Morse Micro MM81x SDIO support\"\n 22:\t\tdepends on MAC80211 \u0026\u0026 MMC\n 23:\t\tselect MM81X\n 24:\t\thelp\n 25:\t\t This module adds support for the SDIO interface of\n 26:\t\t devices using the Morse Micro MM81x chipset.\n"
} |
| 75/2 | 2026/09/21 14:29 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 23682 output: 29 thoughts: 23 Thoughts: Here's my thought process, as it went: **Examining the Kernel Configuration** Okay, I need to figure out how this wireless module is configured within the kernel build system. The logical first step is to dive into the configuration files. Given the path "drivers/net/wireless/morsemicro/Kconfig", I'm going to start by taking a look at `drivers/net/wireless/morsemicro/Kconfig`. That's where I'd expect the specific configuration options for this particular driver to reside. However, it's possible that the configuration might be defined at a higher level, potentially using `source` directives to include the parent's `Kconfig` files. So, if the morsemicro file doesn't give me everything I need, my next move will be to check its parent's Kconfig file, or any parent Kconfig files, to understand how this module fits into the broader wireless network configuration. I need to understand what controls its inclusion and dependency. This is all about tracing dependencies and understanding how this driver interacts with the overall kernel configuration. |
| 76/2 | 2026/09/21 14:29 | tool | grepper |
0mArgs:{
"Expression": "MM81X",
"PathPrefix": "drivers/net/wireless"
}Results: {
"Output": "\nFull output is too long, showing 500 out of 2202 lines.\nUse more precise expression if possible.\n\ndrivers/net/wireless/morsemicro/Makefile-1-# SPDX-License-Identifier: GPL-2.0\ndrivers/net/wireless/morsemicro/Makefile:2:obj-$(CONFIG_MM81X) += mm81x/\n--\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-2-\ndrivers/net/wireless/morsemicro/mm81x/Kconfig:3:config MM81X\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-4-\ttristate \"Morse Micro MM81x wireless devices\" if COMPILE_TEST\n--\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-11-\ndrivers/net/wireless/morsemicro/mm81x/Kconfig:12:config MM81X_USB\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-13-\ttristate \"Morse Micro MM81x USB support\"\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-14-\tdepends on MAC80211 \u0026\u0026 USB\ndrivers/net/wireless/morsemicro/mm81x/Kconfig:15:\tselect MM81X\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-16-\thelp\n--\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-19-\ndrivers/net/wireless/morsemicro/mm81x/Kconfig:20:config MM81X_SDIO\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-21-\ttristate \"Morse Micro MM81x SDIO support\"\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-22-\tdepends on MAC80211 \u0026\u0026 MMC\ndrivers/net/wireless/morsemicro/mm81x/Kconfig:23:\tselect MM81X\ndrivers/net/wireless/morsemicro/mm81x/Kconfig-24-\thelp\n--\ndrivers/net/wireless/morsemicro/mm81x/Makefile-2-\ndrivers/net/wireless/morsemicro/mm81x/Makefile:3:obj-$(CONFIG_MM81X) += mm81x_core.o\ndrivers/net/wireless/morsemicro/mm81x/Makefile-4-\n--\ndrivers/net/wireless/morsemicro/mm81x/Makefile=15=mm81x_core-y += mmrc.o\ndrivers/net/wireless/morsemicro/mm81x/Makefile-16-\ndrivers/net/wireless/morsemicro/mm81x/Makefile:17:obj-$(CONFIG_MM81X_USB) += mm81x_usb.o\ndrivers/net/wireless/morsemicro/mm81x/Makefile-18-mm81x_usb-y += usb.o\ndrivers/net/wireless/morsemicro/mm81x/Makefile-19-\ndrivers/net/wireless/morsemicro/mm81x/Makefile:20:obj-$(CONFIG_MM81X_SDIO) += mm81x_sdio.o\ndrivers/net/wireless/morsemicro/mm81x/Makefile-21-mm81x_sdio-y += sdio.o\n--\ndrivers/net/wireless/morsemicro/mm81x/bus.h-5-\ndrivers/net/wireless/morsemicro/mm81x/bus.h:6:#ifndef _MM81X_BUS_H_\ndrivers/net/wireless/morsemicro/mm81x/bus.h:7:#define _MM81X_BUS_H_\ndrivers/net/wireless/morsemicro/mm81x/bus.h-8-\n--\ndrivers/net/wireless/morsemicro/mm81x/bus.h=12=enum mm81x_bus_type {\ndrivers/net/wireless/morsemicro/mm81x/bus.h:13:\tMM81X_BUS_TYPE_USB,\ndrivers/net/wireless/morsemicro/mm81x/bus.h:14:\tMM81X_BUS_TYPE_SDIO,\ndrivers/net/wireless/morsemicro/mm81x/bus.h-15-};\n--\ndrivers/net/wireless/morsemicro/mm81x/bus.h=17=struct mm81x_bus_ops {\n--\ndrivers/net/wireless/morsemicro/mm81x/bus.h-34- */\ndrivers/net/wireless/morsemicro/mm81x/bus.h:35:#define MM81X_BUS_DEFAULT_BULK_ALIGNMENT (2)\ndrivers/net/wireless/morsemicro/mm81x/bus.h-36-\n--\ndrivers/net/wireless/morsemicro/mm81x/bus.h=94=static inline unsigned int mm81x_bus_get_alignment(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/bus.h-98-\ndrivers/net/wireless/morsemicro/mm81x/bus.h:99:#endif /* !_MM81X_BUS_H_ */\n--\ndrivers/net/wireless/morsemicro/mm81x/command.c=33=static int mm81x_cmd_tx(struct mm81x *mors, struct host_cmd_resp *resp,\n--\ndrivers/net/wireless/morsemicro/mm81x/command.c-84-\t\tret = mm81x_skbq_skb_tx(cmd_q, \u0026skb, NULL,\ndrivers/net/wireless/morsemicro/mm81x/command.c:85:\t\t\t\t\tMM81X_SKB_CHAN_COMMAND);\ndrivers/net/wireless/morsemicro/mm81x/command.c-86-\t\tmutex_unlock(\u0026mors-\u003ecmd_lock);\n--\ndrivers/net/wireless/morsemicro/mm81x/command.c=324=int mm81x_cmd_hw_scan(struct mm81x *mors, struct mm81x_hw_scan_params *params,\n--\ndrivers/net/wireless/morsemicro/mm81x/command.c-343-\t\tflags = HOST_CMD_HW_SCAN_FLAGS_STORE;\ndrivers/net/wireless/morsemicro/mm81x/command.c:344:\telse if (params-\u003eoperation == MM81X_HW_SCAN_OP_START)\ndrivers/net/wireless/morsemicro/mm81x/command.c-345-\t\tflags |= HOST_CMD_HW_SCAN_FLAGS_START;\ndrivers/net/wireless/morsemicro/mm81x/command.c:346:\telse if (params-\u003eoperation == MM81X_HW_SCAN_OP_STOP)\ndrivers/net/wireless/morsemicro/mm81x/command.c-347-\t\tflags |= HOST_CMD_HW_SCAN_FLAGS_ABORT;\n--\ndrivers/net/wireless/morsemicro/mm81x/command.c-350-\ndrivers/net/wireless/morsemicro/mm81x/command.c:351:\tif (params-\u003eoperation == MM81X_HW_SCAN_OP_START) {\ndrivers/net/wireless/morsemicro/mm81x/command.c-352-\t\treq-\u003edwell_time_ms = cpu_to_le32(params-\u003edwell_time_ms);\n--\ndrivers/net/wireless/morsemicro/mm81x/command.h-5-\ndrivers/net/wireless/morsemicro/mm81x/command.h:6:#ifndef _MM81X_COMMAND_H_\ndrivers/net/wireless/morsemicro/mm81x/command.h:7:#define _MM81X_COMMAND_H_\ndrivers/net/wireless/morsemicro/mm81x/command.h-8-\n--\ndrivers/net/wireless/morsemicro/mm81x/command.h=21=enum mm81x_cmd_return_code {\ndrivers/net/wireless/morsemicro/mm81x/command.h:22:\tMM81X_RET_SUCCESS = 0,\ndrivers/net/wireless/morsemicro/mm81x/command.h:23:\tMM81X_RET_EPERM = -1,\ndrivers/net/wireless/morsemicro/mm81x/command.h:24:\tMM81X_RET_ENOMEM = -12,\ndrivers/net/wireless/morsemicro/mm81x/command.h:25:\tMM81X_RET_CMD_NOT_HANDLED = -32757,\ndrivers/net/wireless/morsemicro/mm81x/command.h-26-};\n--\ndrivers/net/wireless/morsemicro/mm81x/command.h=81=int mm81x_cmd_get_disabled_channels(\n--\ndrivers/net/wireless/morsemicro/mm81x/command.h-84-\ndrivers/net/wireless/morsemicro/mm81x/command.h:85:#endif /* !_MM81X_COMMAND_H_ */\n--\ndrivers/net/wireless/morsemicro/mm81x/command_defs.h-4- */\ndrivers/net/wireless/morsemicro/mm81x/command_defs.h:5:#ifndef _MM81X_COMMAND_DEFS_H_\ndrivers/net/wireless/morsemicro/mm81x/command_defs.h:6:#define _MM81X_COMMAND_DEFS_H_\ndrivers/net/wireless/morsemicro/mm81x/command_defs.h-7-\n--\ndrivers/net/wireless/morsemicro/mm81x/core.c=44=char *mm81x_core_get_fw_path(u32 chip_id, u32 fw_ver)\n--\ndrivers/net/wireless/morsemicro/mm81x/core.c-55-\ndrivers/net/wireless/morsemicro/mm81x/core.c:56:\treturn kasprintf(GFP_KERNEL, MM81X_FW_DIR \"/v%u/%s\" MM81X_FW_EXT,\ndrivers/net/wireless/morsemicro/mm81x/core.c-57-\t\t\t fw_ver, fw_base);\n--\ndrivers/net/wireless/morsemicro/mm81x/core.c=67=int mm81x_core_init(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/core.c-70-\ndrivers/net/wireless/morsemicro/mm81x/core.c:71:\tset_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags);\ndrivers/net/wireless/morsemicro/mm81x/core.c:72:\tset_bit(MM81X_STATE_RELOAD_FW_AFTER_START, \u0026mors-\u003estate_flags);\ndrivers/net/wireless/morsemicro/mm81x/core.c-73-\n--\ndrivers/net/wireless/morsemicro/mm81x/core.c=136=MODULE_AUTHOR(\"Morse Micro\");\ndrivers/net/wireless/morsemicro/mm81x/core.c:137:MODULE_DESCRIPTION(\"Driver support for Morse Micro MM81X core\");\ndrivers/net/wireless/morsemicro/mm81x/core.c-138-MODULE_LICENSE(\"Dual BSD/GPL\");\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-5-\ndrivers/net/wireless/morsemicro/mm81x/core.h:6:#ifndef _MM81X_CORE_H_\ndrivers/net/wireless/morsemicro/mm81x/core.h:7:#define _MM81X_CORE_H_\ndrivers/net/wireless/morsemicro/mm81x/core.h-8-\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-24-\ndrivers/net/wireless/morsemicro/mm81x/core.h:25:#define MM81X_DRIVER_SEMVER_MAJOR 56\ndrivers/net/wireless/morsemicro/mm81x/core.h:26:#define MM81X_DRIVER_SEMVER_MINOR 3\ndrivers/net/wireless/morsemicro/mm81x/core.h:27:#define MM81X_DRIVER_SEMVER_PATCH 0\ndrivers/net/wireless/morsemicro/mm81x/core.h-28-\ndrivers/net/wireless/morsemicro/mm81x/core.h:29:#define MM81X_SEMVER_GET_MAJOR(x) (((x) \u003e\u003e 22) \u0026 0x3FF)\ndrivers/net/wireless/morsemicro/mm81x/core.h:30:#define MM81X_SEMVER_GET_MINOR(x) (((x) \u003e\u003e 10) \u0026 0xFFF)\ndrivers/net/wireless/morsemicro/mm81x/core.h:31:#define MM81X_SEMVER_GET_PATCH(x) ((x) \u0026 0x3FF)\ndrivers/net/wireless/morsemicro/mm81x/core.h-32-\ndrivers/net/wireless/morsemicro/mm81x/core.h:33:#define DRV_VERSION __stringify(MM81X_VERSION)\ndrivers/net/wireless/morsemicro/mm81x/core.h-34-\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=56=struct mm81x_hif_ops;\ndrivers/net/wireless/morsemicro/mm81x/core.h-57-\ndrivers/net/wireless/morsemicro/mm81x/core.h:58:#define MM81X_CAPS_MAX_FW_VAL (128)\ndrivers/net/wireless/morsemicro/mm81x/core.h-59-\ndrivers/net/wireless/morsemicro/mm81x/core.h-60-/* Max number of interfaces */\ndrivers/net/wireless/morsemicro/mm81x/core.h:61:#define MM81X_MAX_IF (2)\ndrivers/net/wireless/morsemicro/mm81x/core.h-62-\ndrivers/net/wireless/morsemicro/mm81x/core.h=63=enum mm81x_caps_flags {\ndrivers/net/wireless/morsemicro/mm81x/core.h:64:\tMM81X_CAPS_FW_START = 0,\ndrivers/net/wireless/morsemicro/mm81x/core.h:65:\tMM81X_CAPS_2MHZ = MM81X_CAPS_FW_START,\ndrivers/net/wireless/morsemicro/mm81x/core.h:66:\tMM81X_CAPS_4MHZ,\ndrivers/net/wireless/morsemicro/mm81x/core.h:67:\tMM81X_CAPS_8MHZ,\ndrivers/net/wireless/morsemicro/mm81x/core.h:68:\tMM81X_CAPS_16MHZ,\ndrivers/net/wireless/morsemicro/mm81x/core.h:69:\tMM81X_CAPS_SGI,\ndrivers/net/wireless/morsemicro/mm81x/core.h:70:\tMM81X_CAPS_S1G_LONG,\ndrivers/net/wireless/morsemicro/mm81x/core.h:71:\tMM81X_CAPS_TRAVELING_PILOT_ONE_STREAM,\ndrivers/net/wireless/morsemicro/mm81x/core.h:72:\tMM81X_CAPS_TRAVELING_PILOT_TWO_STREAM,\ndrivers/net/wireless/morsemicro/mm81x/core.h:73:\tMM81X_CAPS_MU_BEAMFORMEE,\ndrivers/net/wireless/morsemicro/mm81x/core.h:74:\tMM81X_CAPS_MU_BEAMFORMER,\ndrivers/net/wireless/morsemicro/mm81x/core.h:75:\tMM81X_CAPS_RD_RESPONDER,\ndrivers/net/wireless/morsemicro/mm81x/core.h:76:\tMM81X_CAPS_STA_TYPE_SENSOR,\ndrivers/net/wireless/morsemicro/mm81x/core.h:77:\tMM81X_CAPS_STA_TYPE_NON_SENSOR,\ndrivers/net/wireless/morsemicro/mm81x/core.h:78:\tMM81X_CAPS_GROUP_AID,\ndrivers/net/wireless/morsemicro/mm81x/core.h:79:\tMM81X_CAPS_NON_TIM,\ndrivers/net/wireless/morsemicro/mm81x/core.h:80:\tMM81X_CAPS_TIM_ADE,\ndrivers/net/wireless/morsemicro/mm81x/core.h:81:\tMM81X_CAPS_BAT,\ndrivers/net/wireless/morsemicro/mm81x/core.h:82:\tMM81X_CAPS_DYNAMIC_AID,\ndrivers/net/wireless/morsemicro/mm81x/core.h:83:\tMM81X_CAPS_UPLINK_SYNC,\ndrivers/net/wireless/morsemicro/mm81x/core.h:84:\tMM81X_CAPS_FLOW_CONTROL,\ndrivers/net/wireless/morsemicro/mm81x/core.h:85:\tMM81X_CAPS_AMPDU,\ndrivers/net/wireless/morsemicro/mm81x/core.h:86:\tMM81X_CAPS_AMSDU,\ndrivers/net/wireless/morsemicro/mm81x/core.h:87:\tMM81X_CAPS_1MHZ_CONTROL_RESPONSE_PREAMBLE,\ndrivers/net/wireless/morsemicro/mm81x/core.h:88:\tMM81X_CAPS_PAGE_SLICING,\ndrivers/net/wireless/morsemicro/mm81x/core.h:89:\tMM81X_CAPS_RAW,\ndrivers/net/wireless/morsemicro/mm81x/core.h:90:\tMM81X_CAPS_MCS8,\ndrivers/net/wireless/morsemicro/mm81x/core.h:91:\tMM81X_CAPS_MCS9,\ndrivers/net/wireless/morsemicro/mm81x/core.h:92:\tMM81X_CAPS_ASYMMETRIC_BA_SUPPORT,\ndrivers/net/wireless/morsemicro/mm81x/core.h:93:\tMM81X_CAPS_DAC,\ndrivers/net/wireless/morsemicro/mm81x/core.h:94:\tMM81X_CAPS_CAC,\ndrivers/net/wireless/morsemicro/mm81x/core.h:95:\tMM81X_CAPS_TXOP_SHARING_IMPLICIT_ACK,\ndrivers/net/wireless/morsemicro/mm81x/core.h:96:\tMM81X_CAPS_NDP_PSPOLL,\ndrivers/net/wireless/morsemicro/mm81x/core.h:97:\tMM81X_CAPS_FRAGMENT_BA,\ndrivers/net/wireless/morsemicro/mm81x/core.h:98:\tMM81X_CAPS_OBSS_MITIGATION,\ndrivers/net/wireless/morsemicro/mm81x/core.h:99:\tMM81X_CAPS_TMP_PS_MODE_SWITCH,\ndrivers/net/wireless/morsemicro/mm81x/core.h:100:\tMM81X_CAPS_SECTOR_TRAINING,\ndrivers/net/wireless/morsemicro/mm81x/core.h:101:\tMM81X_CAPS_UNSOLICIT_DYNAMIC_AID,\ndrivers/net/wireless/morsemicro/mm81x/core.h:102:\tMM81X_CAPS_NDP_BEAMFORMING_REPORT,\ndrivers/net/wireless/morsemicro/mm81x/core.h:103:\tMM81X_CAPS_MCS_NEGOTIATION,\ndrivers/net/wireless/morsemicro/mm81x/core.h:104:\tMM81X_CAPS_DUPLICATE_1MHZ,\ndrivers/net/wireless/morsemicro/mm81x/core.h:105:\tMM81X_CAPS_TACK_AS_PSPOLL,\ndrivers/net/wireless/morsemicro/mm81x/core.h:106:\tMM81X_CAPS_PV1,\ndrivers/net/wireless/morsemicro/mm81x/core.h:107:\tMM81X_CAPS_TWT_RESPONDER,\ndrivers/net/wireless/morsemicro/mm81x/core.h:108:\tMM81X_CAPS_TWT_REQUESTER,\ndrivers/net/wireless/morsemicro/mm81x/core.h:109:\tMM81X_CAPS_BDT,\ndrivers/net/wireless/morsemicro/mm81x/core.h:110:\tMM81X_CAPS_TWT_GROUPING,\ndrivers/net/wireless/morsemicro/mm81x/core.h:111:\tMM81X_CAPS_LINK_ADAPTATION_WO_NDP_CMAC,\ndrivers/net/wireless/morsemicro/mm81x/core.h:112:\tMM81X_CAPS_LONG_MPDU,\ndrivers/net/wireless/morsemicro/mm81x/core.h:113:\tMM81X_CAPS_TXOP_SECTORIZATION,\ndrivers/net/wireless/morsemicro/mm81x/core.h:114:\tMM81X_CAPS_GROUP_SECTORIZATION,\ndrivers/net/wireless/morsemicro/mm81x/core.h:115:\tMM81X_CAPS_HTC_VHT,\ndrivers/net/wireless/morsemicro/mm81x/core.h:116:\tMM81X_CAPS_HTC_VHT_MFB,\ndrivers/net/wireless/morsemicro/mm81x/core.h:117:\tMM81X_CAPS_HTC_VHT_MRQ,\ndrivers/net/wireless/morsemicro/mm81x/core.h:118:\tMM81X_CAPS_2SS,\ndrivers/net/wireless/morsemicro/mm81x/core.h:119:\tMM81X_CAPS_3SS,\ndrivers/net/wireless/morsemicro/mm81x/core.h:120:\tMM81X_CAPS_4SS,\ndrivers/net/wireless/morsemicro/mm81x/core.h:121:\tMM81X_CAPS_SU_BEAMFORMEE,\ndrivers/net/wireless/morsemicro/mm81x/core.h:122:\tMM81X_CAPS_SU_BEAMFORMER,\ndrivers/net/wireless/morsemicro/mm81x/core.h:123:\tMM81X_CAPS_RX_STBC,\ndrivers/net/wireless/morsemicro/mm81x/core.h:124:\tMM81X_CAPS_TX_STBC,\ndrivers/net/wireless/morsemicro/mm81x/core.h:125:\tMM81X_CAPS_RX_LDPC,\ndrivers/net/wireless/morsemicro/mm81x/core.h:126:\tMM81X_CAPS_HW_FRAGMENT,\ndrivers/net/wireless/morsemicro/mm81x/core.h-127-\ndrivers/net/wireless/morsemicro/mm81x/core.h:128:\tMM81X_CAPS_FW_END = MM81X_CAPS_MAX_FW_VAL,\ndrivers/net/wireless/morsemicro/mm81x/core.h:129:\tMM81X_CAPS_LAST = MM81X_CAPS_FW_END,\ndrivers/net/wireless/morsemicro/mm81x/core.h-130-};\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=132=struct mm81x_fw_caps {\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-140-\ndrivers/net/wireless/morsemicro/mm81x/core.h:141:#define MM81X_FW_SUPP(MM81X_CAPS, CAPABILITY) \\\ndrivers/net/wireless/morsemicro/mm81x/core.h:142:\tmm81x_caps_supported(MM81X_CAPS, MM81X_CAPS_##CAPABILITY)\ndrivers/net/wireless/morsemicro/mm81x/core.h-143-\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=161=enum mm81x_page_aci {\ndrivers/net/wireless/morsemicro/mm81x/core.h:162:\tMM81X_ACI_BE = 0,\ndrivers/net/wireless/morsemicro/mm81x/core.h:163:\tMM81X_ACI_BK = 1,\ndrivers/net/wireless/morsemicro/mm81x/core.h:164:\tMM81X_ACI_VI = 2,\ndrivers/net/wireless/morsemicro/mm81x/core.h:165:\tMM81X_ACI_VO = 3,\ndrivers/net/wireless/morsemicro/mm81x/core.h-166-};\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=168=enum mm81x_qos_tid_up_index {\ndrivers/net/wireless/morsemicro/mm81x/core.h:169:\tMM81X_QOS_TID_UP_BK = 1,\ndrivers/net/wireless/morsemicro/mm81x/core.h:170:\tMM81X_QOS_TID_UP_XX = 2,\ndrivers/net/wireless/morsemicro/mm81x/core.h:171:\tMM81X_QOS_TID_UP_BE = 0,\ndrivers/net/wireless/morsemicro/mm81x/core.h:172:\tMM81X_QOS_TID_UP_EE = 3,\ndrivers/net/wireless/morsemicro/mm81x/core.h:173:\tMM81X_QOS_TID_UP_CL = 4,\ndrivers/net/wireless/morsemicro/mm81x/core.h:174:\tMM81X_QOS_TID_UP_VI = 5,\ndrivers/net/wireless/morsemicro/mm81x/core.h:175:\tMM81X_QOS_TID_UP_VO = 6,\ndrivers/net/wireless/morsemicro/mm81x/core.h:176:\tMM81X_QOS_TID_UP_NC = 7,\ndrivers/net/wireless/morsemicro/mm81x/core.h-177-\ndrivers/net/wireless/morsemicro/mm81x/core.h:178:\tMM81X_QOS_TID_UP_LOWEST = MM81X_QOS_TID_UP_BK,\ndrivers/net/wireless/morsemicro/mm81x/core.h:179:\tMM81X_QOS_TID_UP_HIGHEST = MM81X_QOS_TID_UP_NC\ndrivers/net/wireless/morsemicro/mm81x/core.h-180-};\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=233=enum mm81x_hw_scan_op {\ndrivers/net/wireless/morsemicro/mm81x/core.h:234:\tMM81X_HW_SCAN_OP_START,\ndrivers/net/wireless/morsemicro/mm81x/core.h:235:\tMM81X_HW_SCAN_OP_STOP,\ndrivers/net/wireless/morsemicro/mm81x/core.h-236-};\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=276=enum mm81x_hif_event_flags {\ndrivers/net/wireless/morsemicro/mm81x/core.h:277:\tMM81X_HIF_EVT_RX_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:278:\tMM81X_HIF_EVT_PAGE_RETURN_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:279:\tMM81X_HIF_EVT_TX_COMMAND_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:280:\tMM81X_HIF_EVT_TX_BEACON_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:281:\tMM81X_HIF_EVT_TX_MGMT_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:282:\tMM81X_HIF_EVT_TX_DATA_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:283:\tMM81X_HIF_EVT_TX_PACKET_FREED_UP_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:284:\tMM81X_HIF_EVT_DATA_TRAFFIC_PAUSE_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:285:\tMM81X_HIF_EVT_DATA_TRAFFIC_RESUME_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h:286:\tMM81X_HIF_EVT_UPDATE_HW_CLOCK_REFERENCE,\ndrivers/net/wireless/morsemicro/mm81x/core.h-287-};\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=289=enum mm81x_state_flags {\ndrivers/net/wireless/morsemicro/mm81x/core.h:290:\tMM81X_STATE_CHIP_UNRESPONSIVE,\ndrivers/net/wireless/morsemicro/mm81x/core.h:291:\tMM81X_STATE_DATA_QS_STOPPED,\ndrivers/net/wireless/morsemicro/mm81x/core.h:292:\tMM81X_STATE_DATA_TX_STOPPED,\ndrivers/net/wireless/morsemicro/mm81x/core.h:293:\tMM81X_STATE_REGDOM_SET_BY_USER,\ndrivers/net/wireless/morsemicro/mm81x/core.h:294:\tMM81X_STATE_REGDOM_SET_BY_OTP,\ndrivers/net/wireless/morsemicro/mm81x/core.h:295:\tMM81X_STATE_RELOAD_FW_AFTER_START,\ndrivers/net/wireless/morsemicro/mm81x/core.h:296:\tMM81X_STATE_HOST_TO_CHIP_TX_BLOCKED,\ndrivers/net/wireless/morsemicro/mm81x/core.h:297:\tMM81X_STATE_HOST_TO_CHIP_CMD_BLOCKED,\ndrivers/net/wireless/morsemicro/mm81x/core.h-298-};\ndrivers/net/wireless/morsemicro/mm81x/core.h-299-\ndrivers/net/wireless/morsemicro/mm81x/core.h:300:#define MM81X_COUNTRY_LEN (3)\ndrivers/net/wireless/morsemicro/mm81x/core.h-301-#define INVALID_VIF_INDEX 0xFF\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=303=struct mm81x {\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-317-\tu8 macaddr[ETH_ALEN];\ndrivers/net/wireless/morsemicro/mm81x/core.h:318:\tu8 country[MM81X_COUNTRY_LEN];\ndrivers/net/wireless/morsemicro/mm81x/core.h-319-\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-330-\ndrivers/net/wireless/morsemicro/mm81x/core.h:331:\tstruct ieee80211_vif __rcu *vifs[MM81X_MAX_IF];\ndrivers/net/wireless/morsemicro/mm81x/core.h-332-\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=382=static inline u8 map_mac80211q_2_mm81x_aci(u16 mac80211queue)\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-385-\tcase IEEE80211_AC_VO:\ndrivers/net/wireless/morsemicro/mm81x/core.h:386:\t\treturn MM81X_ACI_VO;\ndrivers/net/wireless/morsemicro/mm81x/core.h-387-\tcase IEEE80211_AC_VI:\ndrivers/net/wireless/morsemicro/mm81x/core.h:388:\t\treturn MM81X_ACI_VI;\ndrivers/net/wireless/morsemicro/mm81x/core.h-389-\tcase IEEE80211_AC_BK:\ndrivers/net/wireless/morsemicro/mm81x/core.h:390:\t\treturn MM81X_ACI_BK;\ndrivers/net/wireless/morsemicro/mm81x/core.h-391-\tdefault:\ndrivers/net/wireless/morsemicro/mm81x/core.h:392:\t\treturn MM81X_ACI_BE;\ndrivers/net/wireless/morsemicro/mm81x/core.h-393-\t}\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=397=dot11_tid_to_ac(enum mm81x_qos_tid_up_index tid)\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h-399-\tswitch (tid) {\ndrivers/net/wireless/morsemicro/mm81x/core.h:400:\tcase MM81X_QOS_TID_UP_BK:\ndrivers/net/wireless/morsemicro/mm81x/core.h:401:\tcase MM81X_QOS_TID_UP_XX:\ndrivers/net/wireless/morsemicro/mm81x/core.h:402:\t\treturn MM81X_ACI_BK;\ndrivers/net/wireless/morsemicro/mm81x/core.h:403:\tcase MM81X_QOS_TID_UP_CL:\ndrivers/net/wireless/morsemicro/mm81x/core.h:404:\tcase MM81X_QOS_TID_UP_VI:\ndrivers/net/wireless/morsemicro/mm81x/core.h:405:\t\treturn MM81X_ACI_VI;\ndrivers/net/wireless/morsemicro/mm81x/core.h:406:\tcase MM81X_QOS_TID_UP_VO:\ndrivers/net/wireless/morsemicro/mm81x/core.h:407:\tcase MM81X_QOS_TID_UP_NC:\ndrivers/net/wireless/morsemicro/mm81x/core.h:408:\t\treturn MM81X_ACI_VO;\ndrivers/net/wireless/morsemicro/mm81x/core.h:409:\tcase MM81X_QOS_TID_UP_BE:\ndrivers/net/wireless/morsemicro/mm81x/core.h:410:\tcase MM81X_QOS_TID_UP_EE:\ndrivers/net/wireless/morsemicro/mm81x/core.h-411-\tdefault:\ndrivers/net/wireless/morsemicro/mm81x/core.h:412:\t\treturn MM81X_ACI_BE;\ndrivers/net/wireless/morsemicro/mm81x/core.h-413-\t}\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=416=static inline bool mm81x_is_data_tx_allowed(struct mm81x *mors)\ndrivers/net/wireless/morsemicro/mm81x/core.h-417-{\ndrivers/net/wireless/morsemicro/mm81x/core.h:418:\treturn !test_bit(MM81X_STATE_DATA_TX_STOPPED, \u0026mors-\u003estate_flags) \u0026\u0026\ndrivers/net/wireless/morsemicro/mm81x/core.h:419:\t !test_bit(MM81X_HIF_EVT_DATA_TRAFFIC_PAUSE_PEND,\ndrivers/net/wireless/morsemicro/mm81x/core.h-420-\t\t\t \u0026mors-\u003ehif.event_flags);\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=454=void mm81x_core_free(struct mm81x *mors);\ndrivers/net/wireless/morsemicro/mm81x/core.h-455-\ndrivers/net/wireless/morsemicro/mm81x/core.h:456:#endif /* !_MM81X_MM81X_H_ */\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=55=static void mm81x_fw_parse_info(struct mm81x *mors, const u8 *data, int length)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-61-\t\tswitch (le16_to_cpu(tlv-\u003etype)) {\ndrivers/net/wireless/morsemicro/mm81x/fw.c:62:\t\tcase MM81X_FW_INFO_TLV_BCF_ADDR:\ndrivers/net/wireless/morsemicro/mm81x/fw.c-63-\t\t\tmors-\u003ebcf_address = get_unaligned_le32(tlv-\u003eval);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=91=static int mm81x_fw_set_boot_addr(struct mm81x *mors, uint32_t addr)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-96-\tmm81x_claim_bus(mors);\ndrivers/net/wireless/morsemicro/mm81x/fw.c:97:\tstatus = mm81x_reg32_write(mors, MM81X_REG_BOOT_ADDR(mors), addr);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-98-\tmm81x_release_bus(mors);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=299=static void mm81x_fw_clear_aon(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-301-\tint idx;\ndrivers/net/wireless/morsemicro/mm81x/fw.c:302:\tu8 count = MM81X_REG_AON_COUNT(mors);\ndrivers/net/wireless/morsemicro/mm81x/fw.c:303:\tu32 address = MM81X_REG_AON_ADDR(mors);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-304-\ndrivers/net/wireless/morsemicro/mm81x/fw.c-305-\tfor (idx = 0; idx \u003c count; idx++, address += 4) {\ndrivers/net/wireless/morsemicro/mm81x/fw.c:306:\t\tif (mors-\u003ebus_type == MM81X_BUS_TYPE_USB \u0026\u0026 idx == 0)\ndrivers/net/wireless/morsemicro/mm81x/fw.c-307-\t\t\t/* Keep the USB power domain enabled in AON. */\ndrivers/net/wireless/morsemicro/mm81x/fw.c-308-\t\t\tmm81x_reg32_write(mors, address,\ndrivers/net/wireless/morsemicro/mm81x/fw.c:309:\t\t\t\t\t MM81X_REG_AON_USB_RESET(mors));\ndrivers/net/wireless/morsemicro/mm81x/fw.c-310-\t\telse\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=318=static void mm81x_fw_trigger(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-328-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:329:\tif (MM81X_REG_CLK_CTRL(mors))\ndrivers/net/wireless/morsemicro/mm81x/fw.c:330:\t\tmm81x_reg32_write(mors, MM81X_REG_CLK_CTRL(mors),\ndrivers/net/wireless/morsemicro/mm81x/fw.c:331:\t\t\t\t MM81X_REG_CLK_CTRL_VALUE(mors));\ndrivers/net/wireless/morsemicro/mm81x/fw.c-332-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:333:\tmm81x_reg32_write(mors, MM81X_REG_MSI(mors),\ndrivers/net/wireless/morsemicro/mm81x/fw.c:334:\t\t\t MM81X_REG_MSI_HOST_INT(mors));\ndrivers/net/wireless/morsemicro/mm81x/fw.c-335-\tmm81x_release_bus(mors);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=341=static int mm81x_fw_verify_magic(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-343-\tint ret = 0;\ndrivers/net/wireless/morsemicro/mm81x/fw.c:344:\tint magic = ~MM81X_REG_HOST_MAGIC_VALUE(mors);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-345-\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-351-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:352:\tif (magic != MM81X_REG_HOST_MAGIC_VALUE(mors)) {\ndrivers/net/wireless/morsemicro/mm81x/fw.c-353-\t\tdev_err(mors-\u003edev, \"FW magic mismatch 0x%08x:0x%08x\",\ndrivers/net/wireless/morsemicro/mm81x/fw.c:354:\t\t\tMM81X_REG_HOST_MAGIC_VALUE(mors), magic);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-355-\t\tret = -EIO;\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=378=static int mm81x_fw_check_compatibility(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-393-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:394:\tmajor = MM81X_SEMVER_GET_MAJOR(fw_version);\ndrivers/net/wireless/morsemicro/mm81x/fw.c:395:\tminor = MM81X_SEMVER_GET_MINOR(fw_version);\ndrivers/net/wireless/morsemicro/mm81x/fw.c:396:\tpatch = MM81X_SEMVER_GET_PATCH(fw_version);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-397-\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=420=static int mm81x_fw_invalidate_host_ptr(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-425-\tmm81x_claim_bus(mors);\ndrivers/net/wireless/morsemicro/mm81x/fw.c:426:\tret = mm81x_reg32_write(mors, MM81X_REG_HOST_MANIFEST_PTR(mors), 0);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-427-\tmm81x_release_bus(mors);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=431=static int mm81x_fw_get_host_table_ptr(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-439-\t\t\t\tHOST_TABLE_PTR_POLL_TIMEOUT_US, false, mors,\ndrivers/net/wireless/morsemicro/mm81x/fw.c:440:\t\t\t\tMM81X_REG_HOST_MANIFEST_PTR(mors),\ndrivers/net/wireless/morsemicro/mm81x/fw.c-441-\t\t\t\t\u0026mors-\u003ehost_table_ptr);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=546=int mm81x_fw_parse_ext_host_tbl(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-566-\t\tswitch (le16_to_cpu(hdr-\u003etag)) {\ndrivers/net/wireless/morsemicro/mm81x/fw.c:567:\t\tcase MM81X_FW_HOST_TABLE_TAG_S1G_CAPABILITIES:\ndrivers/net/wireless/morsemicro/mm81x/fw.c-568-\t\t\tmm81x_fw_update_capabilities(\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-571-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:572:\t\tcase MM81X_FW_HOST_TABLE_TAG_INSERT_SKB_CHECKSUM:\ndrivers/net/wireless/morsemicro/mm81x/fw.c-573-\t\t\tmm81x_fw_update_validate_skb_checksum(\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-577-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:578:\t\tcase MM81X_FW_HOST_TABLE_TAG_YAPS_TABLE:\ndrivers/net/wireless/morsemicro/mm81x/fw.c-579-\t\t\tmm81x_yaps_hw_read_table(\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=661=static int mm81x_fw_request(struct mm81x *mors, const struct firmware **fw)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-666-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:667:\tfor (ver = MM81X_FW_VER_MAX; ver \u003e= MM81X_FW_VER_MIN; ver--) {\ndrivers/net/wireless/morsemicro/mm81x/fw.c-668-\t\tfw_path = mm81x_core_get_fw_path(mors-\u003echip_id, ver);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-686-\tdev_err(mors-\u003edev, \"no firmware found (tried v%d down to v%d): %d\\n\",\ndrivers/net/wireless/morsemicro/mm81x/fw.c:687:\t\tMM81X_FW_VER_MAX, MM81X_FW_VER_MIN, ret);\ndrivers/net/wireless/morsemicro/mm81x/fw.c-688-\treturn ret;\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=691=int mm81x_fw_init(struct mm81x *mors, bool reset)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-714-\tbcf_path = kasprintf(GFP_KERNEL,\ndrivers/net/wireless/morsemicro/mm81x/fw.c:715:\t\t\t MM81X_FW_DIR\ndrivers/net/wireless/morsemicro/mm81x/fw.c:716:\t\t\t \"/v%u/bcf_boardtype_%04x\" MM81X_FW_EXT,\ndrivers/net/wireless/morsemicro/mm81x/fw.c-717-\t\t\t mors-\u003efw_major, board_id);\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.h-5-\ndrivers/net/wireless/morsemicro/mm81x/fw.h:6:#ifndef _MM81X_FW_H_\ndrivers/net/wireless/morsemicro/mm81x/fw.h:7:#define _MM81X_FW_H_\ndrivers/net/wireless/morsemicro/mm81x/fw.h-8-\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.h-15-#define BCF_DATABASE_SIZE (1024)\ndrivers/net/wireless/morsemicro/mm81x/fw.h:16:#define MM81X_FW_DIR \"morsemicro/mm81x\"\ndrivers/net/wireless/morsemicro/mm81x/fw.h:17:#define MM81X_FW_EXT \".bin\"\ndrivers/net/wireless/morsemicro/mm81x/fw.h-18-\ndrivers/net/wireless/morsemicro/mm81x/fw.h:19:#define MM81X_FW_VER_MAX HOST_CMD_SEMVER_MAJOR\ndrivers/net/wireless/morsemicro/mm81x/fw.h:20:#define MM81X_FW_VER_MIN 56\ndrivers/net/wireless/morsemicro/mm81x/fw.h-21-\ndrivers/net/wireless/morsemicro/mm81x/fw.h:22:/* FW_CAPABILITIES_FLAGS_WIDTH = ceil(MM81X_CAPS_MAX_HW_LEN / 32) */\ndrivers/net/wireless/morsemicro/mm81x/fw.h-23-#define FW_CAPABILITIES_FLAGS_WIDTH (4)\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.h=66=enum mm81x_fw_info_tlv_type {\ndrivers/net/wireless/morsemicro/mm81x/fw.h:67:\tMM81X_FW_INFO_TLV_BCF_ADDR = 1,\ndrivers/net/wireless/morsemicro/mm81x/fw.h-68-};\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.h=76=enum mm81x_fw_ext_host_tbl_tag {\ndrivers/net/wireless/morsemicro/mm81x/fw.h-77-\t/* The S1G capability tag */\ndrivers/net/wireless/morsemicro/mm81x/fw.h:78:\tMM81X_FW_HOST_TABLE_TAG_S1G_CAPABILITIES = 0,\ndrivers/net/wireless/morsemicro/mm81x/fw.h:79:\tMM81X_FW_HOST_TABLE_TAG_PAGER_BYPASS_TX_STATUS = 1,\ndrivers/net/wireless/morsemicro/mm81x/fw.h:80:\tMM81X_FW_HOST_TABLE_TAG_INSERT_SKB_CHECKSUM = 2,\ndrivers/net/wireless/morsemicro/mm81x/fw.h:81:\tMM81X_FW_HOST_TABLE_TAG_YAPS_TABLE = 3,\ndrivers/net/wireless/morsemicro/mm81x/fw.h:82:\tMM81X_FW_HOST_TABLE_TAG_PAGER_PKT_MEMORY = 4,\ndrivers/net/wireless/morsemicro/mm81x/fw.h:83:\tMM81X_FW_HOST_TABLE_TAG_PAGER_BYPASS_CMD_RESP = 5,\ndrivers/net/wireless/morsemicro/mm81x/fw.h-84-};\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.h=141=int mm81x_fw_parse_ext_host_tbl(struct mm81x *mors);\ndrivers/net/wireless/morsemicro/mm81x/fw.h-142-\ndrivers/net/wireless/morsemicro/mm81x/fw.h:143:#endif /* !_MM81X_FW_H_ */\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h-5-\ndrivers/net/wireless/morsemicro/mm81x/hif.h:6:#ifndef _MM81X_HIF_H_\ndrivers/net/wireless/morsemicro/mm81x/hif.h:7:#define _MM81X_HIF_H_\ndrivers/net/wireless/morsemicro/mm81x/hif.h-8-\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=11=struct mm81x_skbq;\ndrivers/net/wireless/morsemicro/mm81x/hif.h-12-\ndrivers/net/wireless/morsemicro/mm81x/hif.h:13:#define MM81X_HIF_BYPASS_TX_STATUS_IRQ_NUM (15)\ndrivers/net/wireless/morsemicro/mm81x/hif.h:14:#define MM81X_HIF_BYPASS_CMD_RESP_IRQ_NUM (29)\ndrivers/net/wireless/morsemicro/mm81x/hif.h:15:#define MM81X_HIF_IRQ_BYPASS_TX_STATUS_AVAILABLE \\\ndrivers/net/wireless/morsemicro/mm81x/hif.h:16:\tBIT(MM81X_HIF_BYPASS_TX_STATUS_IRQ_NUM)\ndrivers/net/wireless/morsemicro/mm81x/hif.h:17:#define MM81X_HIF_IRQ_BYPASS_CMD_RESP_AVAILABLE \\\ndrivers/net/wireless/morsemicro/mm81x/hif.h:18:\tBIT(MM81X_HIF_BYPASS_CMD_RESP_IRQ_NUM)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-19-\ndrivers/net/wireless/morsemicro/mm81x/hif.h-20-/* Hardware IF interrupt mask. We may use any interrupts in this range */\ndrivers/net/wireless/morsemicro/mm81x/hif.h:21:#define MM81X_HIF_IRQ_MASK_ALL \\\ndrivers/net/wireless/morsemicro/mm81x/hif.h:22:\t(GENMASK(13, 0) | MM81X_HIF_IRQ_BYPASS_TX_STATUS_AVAILABLE | \\\ndrivers/net/wireless/morsemicro/mm81x/hif.h:23:\t MM81X_HIF_IRQ_BYPASS_CMD_RESP_AVAILABLE)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-24-\ndrivers/net/wireless/morsemicro/mm81x/hif.h=25=enum mm81x_hif_flags {\ndrivers/net/wireless/morsemicro/mm81x/hif.h:26:\tMM81X_HIF_FLAGS_DIR_TO_HOST = BIT(0),\ndrivers/net/wireless/morsemicro/mm81x/hif.h:27:\tMM81X_HIF_FLAGS_DIR_TO_CHIP = BIT(1),\ndrivers/net/wireless/morsemicro/mm81x/hif.h:28:\tMM81X_HIF_FLAGS_COMMAND = BIT(2),\ndrivers/net/wireless/morsemicro/mm81x/hif.h:29:\tMM81X_HIF_FLAGS_BEACON = BIT(3),\ndrivers/net/wireless/morsemicro/mm81x/hif.h:30:\tMM81X_HIF_FLAGS_DATA = BIT(4)\ndrivers/net/wireless/morsemicro/mm81x/hif.h-31-};\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h=112=static inline int mm81x_hif_get_tx_status_pending_count(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/hif.h-116-\ndrivers/net/wireless/morsemicro/mm81x/hif.h:117:#endif /* _MM81X_HIF_H_ */\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.c-54-\ndrivers/net/wireless/morsemicro/mm81x/hw.c:55:#define MM81X_OTP_MAC_ADDR_2_BANK_NUM 27\ndrivers/net/wireless/morsemicro/mm81x/hw.c:56:#define MM81X_OTP_MAC_ADDR_1_BANK_NUM 26\ndrivers/net/wireless/morsemicro/mm81x/hw.c:57:#define MM81X_OTP_MAC_ADDR_1_MASK GENMASK(31, 16)\ndrivers/net/wireless/morsemicro/mm81x/hw.c:58:#define MM81X_OTP_BOARD_TYPE_BANK_NUM 26\ndrivers/net/wireless/morsemicro/mm81x/hw.c:59:#define MM81X_OTP_BOARD_TYPE_MASK GENMASK(15, 0)\ndrivers/net/wireless/morsemicro/mm81x/hw.c-60-\ndrivers/net/wireless/morsemicro/mm81x/hw.c:61:#define MM810X_BOARD_TYPE_MAX_VALUE (MM81X_OTP_BOARD_TYPE_MASK - 1)\ndrivers/net/wireless/morsemicro/mm81x/hw.c-62-\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.c=128=int mm81x_hw_otp_get_board_type(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.c-137-\ndrivers/net/wireless/morsemicro/mm81x/hw.c:138:\tret = mm81x_hw_otp_read(mors, MM81X_OTP_BOARD_TYPE_BANK_NUM, \u0026otp_word,\ndrivers/net/wireless/morsemicro/mm81x/hw.c-139-\t\t\t\t1);\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.c-147-\ndrivers/net/wireless/morsemicro/mm81x/hw.c:148:\tboard_type = otp_word \u0026 MM81X_OTP_BOARD_TYPE_MASK;\ndrivers/net/wireless/morsemicro/mm81x/hw.c-149-\n--\ndrivers/net/wireless/morsemicro/mm81x/hw.c=158=int mm81x_hw_otp_get_mac_addr(struct mm81x *mors)\n--\n\n"
} |
| 77/2 | 2026/09/21 14:29 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 39604 output: 38 thoughts: 23 Thoughts: Here's my summary, as though I'm thinking it: **Digging into the Wireless Driver Configuration** Okay, so I need to understand the configuration structure for this new wireless driver, specifically how it's integrated within the kernel build system. The logical starting point for understanding how a driver is configured is always the `Kconfig` file. Given the path provided, `drivers/net/wireless/morsemicro/Kconfig`, it seems pretty straightforward to locate. I'll need to open that file to trace the dependencies, menu structure, and any relevant options related to the morsemicro driver. This will give me the foundational insight I require to work on it, its configuration options, and how it is activated or deactivated in a larger build. Let's get to it. |
| 78/2 | 2026/09/21 14:29 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/Kconfig",
"FirstLine": 1,
"LineCount": 20
}Results: {
"Contents": " 1:\t# SPDX-License-Identifier: GPL-2.0-only\n 2:\tconfig WLAN_VENDOR_MORSEMICRO\n 3:\t\tbool \"Morse Micro devices\"\n 4:\t\tdefault y\n 5:\t\thelp\n 6:\t\t If you have a wireless card belonging to this class, say Y.\n 7:\t\n 8:\t\t Note that the answer to this question doesn't directly affect the\n 9:\t\t kernel: saying N will just cause the configurator to skip all the\n 10:\t\t questions about these cards. If you say Y, you will be asked for\n 11:\t\t your specific card in the following questions.\n 12:\t\n 13:\tif WLAN_VENDOR_MORSEMICRO\n 14:\tsource \"drivers/net/wireless/morsemicro/mm81x/Kconfig\"\n 15:\tendif # WLAN_VENDOR_MORSEMICRO\n"
} |
| 79/2 | 2026/09/21 14:29 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 40064 output: 46 thoughts: 193 Thoughts: **Analyzing Potential Syzkaller Coverage of the Morse Micro Driver** Okay, let's break this down. My initial thought is to map `WLAN_VENDOR_MORSEMICRO` to either `MM81X_USB` or `MM81X_SDIO`. Right, and `MM81X_USB` seems to hinge on `MAC80211` and `USB`, and it *selects* `MM81X`. Then, `MM81X` takes responsibility for selecting `FW_LOADER` and `CRC7`. Standard setup so far. But, and this is where it gets interesting, can Syzkaller *actually* reach `mm81x_yaps_hw_read_pkts`? That's the core question. Does firmware loading have to succeed for us to ever get there, or does the driver simply fail gracefully if it can't find the firmware files? That's critical for determining if it's a good target. Let's dig into the source code directly, specifically in `drivers/net/wireless/morsemicro/mm81x/`. I need to confirm if the probe function itself initiates a firmware load. The answer to this is likely in the `mm81x_usb_probe` function. That's the first place to look. I'll check it. |
| 80/2 | 2026/09/21 14:29 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/usb.c",
"FirstLine": 745,
"LineCount": 80
}Results: {
"Contents": " 745:\tstatic int mm81x_usb_probe(struct usb_interface *interface,\n 746:\t\t\t\t const struct usb_device_id *id)\n 747:\t{\n 748:\t\tint ret;\n 749:\t\tstruct mm81x *mors;\n 750:\t\tstruct mm81x_usb *musb;\n 751:\t\n 752:\t\tmors = mm81x_core_alloc(sizeof(*musb), \u0026interface-\u003edev);\n 753:\t\tif (!mors)\n 754:\t\t\treturn -ENOMEM;\n 755:\t\n 756:\t\tmors-\u003ebus_ops = \u0026mm81x_usb_ops;\n 757:\t\tmors-\u003ebus_type = MM81X_BUS_TYPE_USB;\n 758:\t\n 759:\t\tmusb = (struct mm81x_usb *)mors-\u003edrv_priv;\n 760:\t\tmusb-\u003eudev = usb_get_dev(interface_to_usbdev(interface));\n 761:\t\tmusb-\u003einterface = usb_get_intf(interface);\n 762:\t\n 763:\t\tmutex_init(\u0026musb-\u003elock);\n 764:\t\tmutex_init(\u0026musb-\u003ebus_lock);\n 765:\t\tinit_waitqueue_head(\u0026musb-\u003erw_in_wait);\n 766:\t\tusb_set_intfdata(interface, mors);\n 767:\t\n 768:\t\tret = mm81x_usb_detect_endpoints(mors, interface);\n 769:\t\tif (ret \u003c 0)\n 770:\t\t\tgoto err_core_free;\n 771:\t\n 772:\t\tset_bit(MM81X_USB_FLAG_ATTACHED, \u0026musb-\u003eflags);\n 773:\t\n 774:\t\tret = mm81x_core_init(mors);\n 775:\t\tif (ret)\n 776:\t\t\tgoto err_urb_cleanup;\n 777:\t\n 778:\t\tINIT_WORK(\u0026mors-\u003eusb_irq_work, mm81x_usb_irq_work);\n 779:\t\n 780:\t\tret = mm81x_usb_int_enable(mors);\n 781:\t\tif (ret)\n 782:\t\t\tgoto err_core_deinit;\n 783:\t\n 784:\t\tret = mm81x_core_register(mors);\n 785:\t\tif (ret)\n 786:\t\t\tgoto err_usb_int_stop;\n 787:\t\n 788:\t\t/* USB requires remote wakeup functionality for suspend */\n 789:\t\tclear_bit(MM81X_USB_FLAG_SUSPENDED, \u0026musb-\u003eflags);\n 790:\t\tmusb-\u003einterface-\u003eneeds_remote_wakeup = 1;\n 791:\t\tusb_enable_autosuspend(musb-\u003eudev);\n 792:\t\tpm_runtime_set_autosuspend_delay(\u0026musb-\u003eudev-\u003edev,\n 793:\t\t\t\t\t\t PM_RUNTIME_AUTOSUSPEND_DELAY_MS);\n 794:\t\n 795:\t\tusb_autopm_get_interface(interface);\n 796:\t\treturn 0;\n 797:\t\n 798:\terr_usb_int_stop:\n 799:\t\tmm81x_usb_int_stop(mors);\n 800:\terr_core_deinit:\n 801:\t\tmm81x_core_deinit(mors);\n 802:\terr_urb_cleanup:\n 803:\t\tmm81x_urb_cleanup(mors);\n 804:\terr_core_free:\n 805:\t\tmm81x_core_free(mors);\n 806:\t\tusb_put_intf(interface);\n 807:\t\tusb_put_dev(interface_to_usbdev(interface));\n 808:\t\treturn ret;\n 809:\t}\n 810:\t\n 811:\tstatic void mm81x_usb_disconnect(struct usb_interface *interface)\n 812:\t{\n 813:\t\tstruct mm81x *mors = usb_get_intfdata(interface);\n 814:\t\tstruct mm81x_usb *musb = (struct mm81x_usb *)mors-\u003edrv_priv;\n 815:\t\tint minor = interface-\u003eminor;\n 816:\t\tstruct usb_device *udev = interface_to_usbdev(interface);\n 817:\t\n 818:\t\tif (udev-\u003estate == USB_STATE_NOTATTACHED) {\n 819:\t\t\tclear_bit(MM81X_USB_FLAG_ATTACHED, \u0026musb-\u003eflags);\n 820:\t\t\tset_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags);\n 821:\t\t\tdev_dbg(mors-\u003edev, \"USB suddenly unplugged\");\n 822:\t\t}\n 823:\t\n 824:\t\tusb_disable_autosuspend(udev);\n"
} |
| 81/2 | 2026/09/21 14:29 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 41939 output: 45 thoughts: 54 Thoughts: Here's my thought process, as if I were analyzing that code: **Analyzing the mm81x USB Probe and Initialization** Okay, let's break this down. I'm looking at `mm81x_usb_probe()`. The immediate call within that seems to be `mm81x_core_init(mors)`. My brain is immediately asking, does this initialization process involve a firmware request? That's a critical point to know upfront, so I'm going to jump right into examining `mm81x_core_init` to verify and understand how it handles this aspect. I need to understand the firmware loading flow right away. |
| 82/2 | 2026/09/21 14:29 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/core.c",
"FirstLine": 67,
"LineCount": 45
}Results: {
"Contents": " 67:\tint mm81x_core_init(struct mm81x *mors)\n 68:\t{\n 69:\t\tint ret;\n 70:\t\n 71:\t\tset_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags);\n 72:\t\tset_bit(MM81X_STATE_RELOAD_FW_AFTER_START, \u0026mors-\u003estate_flags);\n 73:\t\n 74:\t\tmm81x_core_init_mac_addr(mors);\n 75:\t\n 76:\t\tret = mm81x_core_attach_regs(mors);\n 77:\t\tif (ret)\n 78:\t\t\treturn ret;\n 79:\t\n 80:\t\tmors-\u003echip_wq = create_singlethread_workqueue(\"chip_wq\");\n 81:\t\tif (!mors-\u003echip_wq)\n 82:\t\t\treturn -ENOMEM;\n 83:\t\n 84:\t\tmors-\u003enet_wq = create_singlethread_workqueue(\"net_wq\");\n 85:\t\tif (!mors-\u003enet_wq) {\n 86:\t\t\tret = -ENOMEM;\n 87:\t\t\tgoto err_chip_wq;\n 88:\t\t}\n 89:\t\n 90:\t\tret = mm81x_hif_init(mors);\n 91:\t\tif (ret)\n 92:\t\t\tgoto err_wqs;\n 93:\t\n 94:\t\treturn 0;\n 95:\t\n 96:\terr_wqs:\n 97:\t\tflush_workqueue(mors-\u003enet_wq);\n 98:\t\tdestroy_workqueue(mors-\u003enet_wq);\n 99:\t\n 100:\terr_chip_wq:\n 101:\t\tflush_workqueue(mors-\u003echip_wq);\n 102:\t\tdestroy_workqueue(mors-\u003echip_wq);\n 103:\t\n 104:\t\treturn ret;\n 105:\t}\n 106:\tEXPORT_SYMBOL_GPL(mm81x_core_init);\n 107:\t\n 108:\tint mm81x_core_register(struct mm81x *mors)\n 109:\t{\n 110:\t\treturn mm81x_mac_register(mors);\n 111:\t}\n"
} |
| 83/2 | 2026/09/21 14:29 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 42813 output: 47 thoughts: 44 Thoughts: Here's my summary, as though I were thinking through the process: **Diving into the mm81x Register Functions** Okay, so `mm81x_core_register` is the entry point, and it's calling `mm81x_mac_register(mors)`. That's the key. I need to understand what `mm81x_mac_register` does within this context. Time to pull up the definition of `mm81x_mac_register(mors)` and see how the MAC is getting registered. I want to see what 'mors' is too, so I'll be looking for where that is defined. Is it a structure? A handle? What are the implications of passing 'mors' in as a parameter? |
| 84/2 | 2026/09/21 14:29 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/mac.c",
"FirstLine": 2360,
"LineCount": 45
}Results: {
"Contents": "2360:\t\n2361:\tint mm81x_mac_register(struct mm81x *mors)\n2362:\t{\n2363:\t\tint ret;\n2364:\t\tstruct ieee80211_hw *hw = mors-\u003ehw;\n2365:\t\n2366:\t\tmors-\u003etx_power_mbm = INT_MAX;\n2367:\t\tmors-\u003etx_max_power_mbm = INT_MAX;\n2368:\t\tmors-\u003erts_threshold = IEEE80211_MAX_RTS_THRESHOLD;\n2369:\t\n2370:\t\tret = mm81x_ps_init(mors);\n2371:\t\tif (ret)\n2372:\t\t\treturn ret;\n2373:\t\n2374:\t\tmm81x_mac_config_hw(mors);\n2375:\t\tmm81x_mac_hw_scan_init(mors);\n2376:\t\tmm81x_mac_stale_tx_status_timer_init(mors);\n2377:\t\n2378:\t\tret = ieee80211_register_hw(hw);\n2379:\t\tif (ret) {\n2380:\t\t\tdev_err(mors-\u003edev, \"ieee80211_register_hw failed %d\", ret);\n2381:\t\t\tmm81x_mac_unregister(mors);\n2382:\t\t\treturn ret;\n2383:\t\t}\n2384:\t\n2385:\t\tmm81x_rc_init(mors);\n2386:\t\n2387:\t\t/*\n2388:\t\t * At this stage, we know bus and pager system interrupts are enabled.\n2389:\t\t * Trigger the receive workqueue to drain any incoming chip-to-host\n2390:\t\t * pending packets been pushed in the period between the firmware\n2391:\t\t * initialization and interrupts being enabled.\n2392:\t\t */\n2393:\t\tset_bit(MM81X_HIF_EVT_RX_PEND, \u0026mors-\u003ehif.event_flags);\n2394:\t\tqueue_work(mors-\u003echip_wq, \u0026mors-\u003ehif_work);\n2395:\t\n2396:\t\treturn ret;\n2397:\t}\n2398:\t\n2399:\tvoid mm81x_mac_unregister(struct mm81x *mors)\n2400:\t{\n2401:\t\tmm81x_ps_disable(mors);\n2402:\t\tmm81x_rc_deinit(mors);\n2403:\t\tmm81x_mac_hw_scan_destroy(mors);\n2404:\t\n"
} |
| 85/2 | 2026/09/21 14:29 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 43806 output: 43 thoughts: 124 Thoughts: **Analyzing the Register and Its Implications** Okay, so I'm diving into this `mm81x_mac_register` function. I see it setting the `MM81X_HIF_EVT_RX_PEND` bit and queuing a work item, `mors->hif_work`. Pretty standard setup for handling incoming events, especially concerning a receiver. But something just pinged in my mind—what about the state check for `MM81X_STATE_CHIP_UNRESPONSIVE`? Where is that being handled, or not handled, within this sequence? I need to understand how the system recovers from chip unresponsiveness, or if it even does, given this seemingly event-driven approach. Alright, I need to investigate the `mm81x_yaps_work` in `yaps.c`. It's likely involved in responding to the YAPS (Yet Another Ping System) events, which is very likely to include some error recovery or monitoring functionality, and, hopefully, address my concern regarding the unresponsive chip state. Time to dig deeper and see if my hunch about the missing state check is correct. |
| 86/2 | 2026/09/21 14:29 | tool | grepper |
0mArgs:{
"Expression": "mm81x_yaps_work",
"PathPrefix": "drivers/net/wireless/morsemicro/mm81x"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/yaps.c=415=void mm81x_yaps_stale_tx_work(struct work_struct *work)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-442-\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:443:void mm81x_yaps_work(struct work_struct *work)\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-444-{\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c=603=int mm81x_yaps_init(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-647-\tmm81x_yaps_q_chip_full_timer_init(yaps);\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:648:\tINIT_WORK(\u0026mors-\u003ehif_work, mm81x_yaps_work);\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-649-\tINIT_WORK(\u0026mors-\u003etx_stale_work, mm81x_yaps_stale_tx_work);\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.h=71=void mm81x_yaps_flush_cmds(struct mm81x *mors);\ndrivers/net/wireless/morsemicro/mm81x/yaps.h:72:void mm81x_yaps_work(struct work_struct *work);\ndrivers/net/wireless/morsemicro/mm81x/yaps.h-73-void mm81x_yaps_stale_tx_work(struct work_struct *work);\n"
} |
| 87/2 | 2026/09/21 14:29 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 44707 output: 47 thoughts: 32 Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person: **Diving into `yaps.c` - Line 443** Alright, time to crack open the `drivers/net/wireless/morsemicro/mm81x/yaps.c` file. Specifically, I'm zeroing in on the area around line 443. Hmm, I wonder what's cooking there. Given my experience with the mm81x chipset and its interaction with the YAPS subsystem, I'm probably looking for something related to either initialization, interrupt handling, frame processing, or potentially some sort of error condition or workaround. Line 443 could be a critical branch point within a state machine, a check on a critical variable, or perhaps the start of a fairly involved function. My gut tells me this could be the source of a recent bug report or an area I know has been problematic in the past. Time to get my hands dirty and find out. |
| 88/2 | 2026/09/21 14:29 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/yaps.c",
"FirstLine": 440,
"LineCount": 60
}Results: {
"Contents": " 440:\t\t}\n 441:\t}\n 442:\t\n 443:\tvoid mm81x_yaps_work(struct work_struct *work)\n 444:\t{\n 445:\t\tstruct mm81x *mors = container_of(work, struct mm81x, hif_work);\n 446:\t\tunsigned long *flags = \u0026mors-\u003ehif.event_flags;\n 447:\t\tstruct mm81x_yaps *yaps = \u0026mors-\u003ehif.u.yaps;\n 448:\t\n 449:\t\tif (test_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags))\n 450:\t\t\treturn;\n 451:\t\n 452:\t\tif (!*flags)\n 453:\t\t\treturn;\n 454:\t\n 455:\t\t/* Disable power save in case it is running */\n 456:\t\tmm81x_ps_disable(mors);\n 457:\t\tmm81x_claim_bus(mors);\n 458:\t\n 459:\t\t/*\n 460:\t\t * Handle any populated RX pages from chip first to\n 461:\t\t * avoid dropping pkts due to full on-chip buffers.\n 462:\t\t * Check if all pages were removed, set event flags if not.\n 463:\t\t */\n 464:\t\tif (test_and_clear_bit(MM81X_HIF_EVT_RX_PEND, flags)) {\n 465:\t\t\tif (mm81x_yaps_rx_handler(yaps))\n 466:\t\t\t\tset_bit(MM81X_HIF_EVT_RX_PEND, flags);\n 467:\t\t}\n 468:\t\n 469:\t\t/* TX any commands before considering data */\n 470:\t\tif (test_and_clear_bit(MM81X_HIF_EVT_TX_COMMAND_PEND, flags)) {\n 471:\t\t\tif (mm81x_yaps_tx_cmd_handler(yaps))\n 472:\t\t\t\tset_bit(MM81X_HIF_EVT_TX_COMMAND_PEND, flags);\n 473:\t\t}\n 474:\t\n 475:\t\t/* TX beacons before considering mgmt/data */\n 476:\t\tif (test_and_clear_bit(MM81X_HIF_EVT_TX_BEACON_PEND, flags)) {\n 477:\t\t\tif (mm81x_yaps_tx_beacon_handler(yaps))\n 478:\t\t\t\tset_bit(MM81X_HIF_EVT_TX_BEACON_PEND, flags);\n 479:\t\t}\n 480:\t\n 481:\t\t/* TX mgmt before considering data */\n 482:\t\tif (test_and_clear_bit(MM81X_HIF_EVT_TX_MGMT_PEND, flags)) {\n 483:\t\t\tif (mm81x_yaps_tx_mgmt_handler(yaps))\n 484:\t\t\t\tset_bit(MM81X_HIF_EVT_TX_MGMT_PEND, flags);\n 485:\t\t}\n 486:\t\n 487:\t\t/* Pause TX data Qs */\n 488:\t\tif (test_and_clear_bit(MM81X_HIF_EVT_DATA_TRAFFIC_PAUSE_PEND, flags)) {\n 489:\t\t\ttest_and_clear_bit(MM81X_HIF_EVT_DATA_TRAFFIC_RESUME_PEND,\n 490:\t\t\t\t\t flags);\n 491:\t\t\tmm81x_skbq_data_traffic_pause(mors);\n 492:\t\t}\n 493:\t\n 494:\t\t/* Resume TX data Qs */\n 495:\t\tif (test_and_clear_bit(MM81X_HIF_EVT_DATA_TRAFFIC_RESUME_PEND, flags))\n 496:\t\t\tmm81x_skbq_data_traffic_resume(mors);\n 497:\t\n 498:\t\t/* Handle chip queue status */\n 499:\t\tif (test_and_clear_bit(MM81X_HIF_EVT_TX_PACKET_FREED_UP_PEND, flags))\n"
} |
| 89/2 | 2026/09/21 14:29 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 46140 output: 48 thoughts: 94 Thoughts: **Investigating the "Chip Unresponsive" State** Okay, so I'm looking at this code, specifically line 449, where it checks if the `MM81X_STATE_CHIP_UNRESPONSIVE` bit is set in `mors->state_flags`. The code returns immediately if that bit *is* set, which means the chip is considered unresponsive. My immediate question is: how and when is this state cleared? We don't want the driver to get stuck in a potentially erroneous unresponsive state. Therefore, I need to figure out where `MM81X_STATE_CHIP_UNRESPONSIVE` is actually *unset*. Time to fire up the grep and search for that constant; let's see where that flag is being manipulated within the driver's codebase. |
| 90/2 | 2026/09/21 14:30 | tool | grepper |
0mArgs:{
"Expression": "MM81X_STATE_CHIP_UNRESPONSIVE",
"PathPrefix": "drivers/net/wireless/morsemicro/mm81x"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/core.c=67=int mm81x_core_init(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/core.c-70-\ndrivers/net/wireless/morsemicro/mm81x/core.c:71:\tset_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags);\ndrivers/net/wireless/morsemicro/mm81x/core.c-72-\tset_bit(MM81X_STATE_RELOAD_FW_AFTER_START, \u0026mors-\u003estate_flags);\n--\ndrivers/net/wireless/morsemicro/mm81x/core.h=289=enum mm81x_state_flags {\ndrivers/net/wireless/morsemicro/mm81x/core.h:290:\tMM81X_STATE_CHIP_UNRESPONSIVE,\ndrivers/net/wireless/morsemicro/mm81x/core.h-291-\tMM81X_STATE_DATA_QS_STOPPED,\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c=2107=static int mm81x_mac_restart(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2159-\tclear_bit(MM81X_STATE_DATA_QS_STOPPED, \u0026mors-\u003estate_flags);\ndrivers/net/wireless/morsemicro/mm81x/mac.c:2160:\tclear_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags);\ndrivers/net/wireless/morsemicro/mm81x/mac.c-2161-\tclear_bit(MM81X_STATE_RELOAD_FW_AFTER_START, \u0026mors-\u003estate_flags);\n--\ndrivers/net/wireless/morsemicro/mm81x/skbq.c=955=int mm81x_skbq_skb_tx(struct mm81x_skbq *mq, struct sk_buff **skb_orig,\n--\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-964-\ndrivers/net/wireless/morsemicro/mm81x/skbq.c:965:\tif (test_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags)) {\ndrivers/net/wireless/morsemicro/mm81x/skbq.c-966-\t\tdev_kfree_skb_any(skb);\n--\ndrivers/net/wireless/morsemicro/mm81x/usb.c=109=static void mm81x_usb_int_handler(struct urb *urb)\n--\ndrivers/net/wireless/morsemicro/mm81x/usb.c-120-\t\t\tclear_bit(MM81X_USB_FLAG_ATTACHED, \u0026musb-\u003eflags);\ndrivers/net/wireless/morsemicro/mm81x/usb.c:121:\t\t\tset_bit(MM81X_STATE_CHIP_UNRESPONSIVE,\ndrivers/net/wireless/morsemicro/mm81x/usb.c-122-\t\t\t\t\u0026mors-\u003estate_flags);\n--\ndrivers/net/wireless/morsemicro/mm81x/usb.c=811=static void mm81x_usb_disconnect(struct usb_interface *interface)\n--\ndrivers/net/wireless/morsemicro/mm81x/usb.c-819-\t\tclear_bit(MM81X_USB_FLAG_ATTACHED, \u0026musb-\u003eflags);\ndrivers/net/wireless/morsemicro/mm81x/usb.c:820:\t\tset_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags);\ndrivers/net/wireless/morsemicro/mm81x/usb.c-821-\t\tdev_dbg(mors-\u003edev, \"USB suddenly unplugged\");\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c=443=void mm81x_yaps_work(struct work_struct *work)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-448-\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:449:\tif (test_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags))\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-450-\t\treturn;\n"
} |
| 91/2 | 2026/09/21 14:30 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 47653 output: 47 thoughts: 39 Thoughts: Here's a summary of my thought process: **Diving into the mm81x MAC Restart** Okay, time to get my hands dirty. I need to understand what's going on with the MAC restart function for the mm81x wireless driver. Specifically, I'm going to take a close look at `mm81x_mac_restart` within `drivers/net/wireless/morsemicro/mm81x/mac.c`. Let's see what interesting tidbits and gotchas are hiding in there. Gotta understand the restart mechanism intimately – it's crucial for reliable operation, especially under adverse conditions. This is where the rubber meets the road! I'm expecting some register manipulation and possibly some state machine management in this function, so let's see how they do it. |
| 92/2 | 2026/09/21 14:30 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/mac.c",
"FirstLine": 2107,
"LineCount": 60
}Results: {
"Contents": "2107:\tstatic int mm81x_mac_restart(struct mm81x *mors)\n2108:\t{\n2109:\t\tint ret;\n2110:\t\tu32 chip_id;\n2111:\t\n2112:\t\tmors-\u003estarted = false;\n2113:\t\tmm81x_ps_disable(mors);\n2114:\t\tmm81x_bus_set_irq(mors, false);\n2115:\t\tmm81x_hw_irq_clear(mors);\n2116:\t\tieee80211_stop_queues(mors-\u003ehw);\n2117:\t\n2118:\t\tset_bit(MM81X_STATE_DATA_TX_STOPPED, \u0026mors-\u003estate_flags);\n2119:\t\tset_bit(MM81X_STATE_DATA_QS_STOPPED, \u0026mors-\u003estate_flags);\n2120:\t\n2121:\t\t/* Allow time for in-transit tx/rx packets to settle */\n2122:\t\tmdelay(MM81X_HW_RESTART_DELAY_MS);\n2123:\t\tflush_work(\u0026mors-\u003ehif_work);\n2124:\t\tflush_work(\u0026mors-\u003etx_stale_work);\n2125:\t\tmm81x_hif_clear_events(mors);\n2126:\t\tmm81x_hif_flush_tx_data(mors);\n2127:\t\tmm81x_hif_flush_cmds(mors);\n2128:\t\n2129:\t\tmm81x_claim_bus(mors);\n2130:\t\tret = mm81x_reg32_read(mors, MM81X_REG_CHIP_ID(mors), \u0026chip_id);\n2131:\t\tmm81x_release_bus(mors);\n2132:\t\n2133:\t\tif (ret \u003c 0) {\n2134:\t\t\tdev_err(mors-\u003edev, \"Failed to access HW: %d\", ret);\n2135:\t\t\tgoto exit;\n2136:\t\t}\n2137:\t\n2138:\t\tmm81x_mac_restart_cleanup(mors);\n2139:\t\n2140:\t\tret = mm81x_fw_init(mors, true);\n2141:\t\tif (ret \u003c 0) {\n2142:\t\t\tdev_err(mors-\u003edev, \"Failed to init firmware: %d\", ret);\n2143:\t\t\tgoto exit;\n2144:\t\t}\n2145:\t\n2146:\t\tmm81x_hw_irq_enable(mors, MM81X_INT_HW_STOP_NOTIFICATION_NUM, true);\n2147:\t\n2148:\t\tret = mm81x_fw_parse_ext_host_tbl(mors);\n2149:\t\tif (ret) {\n2150:\t\t\tdev_err(mors-\u003edev, \"failed to parse extended host table: %d\",\n2151:\t\t\t\tret);\n2152:\t\t\tgoto exit;\n2153:\t\t}\n2154:\t\n2155:\t\tmm81x_mac_caps_init(mors);\n2156:\t\n2157:\t\tmm81x_bus_set_irq(mors, true);\n2158:\t\tclear_bit(MM81X_STATE_DATA_TX_STOPPED, \u0026mors-\u003estate_flags);\n2159:\t\tclear_bit(MM81X_STATE_DATA_QS_STOPPED, \u0026mors-\u003estate_flags);\n2160:\t\tclear_bit(MM81X_STATE_CHIP_UNRESPONSIVE, \u0026mors-\u003estate_flags);\n2161:\t\tclear_bit(MM81X_STATE_RELOAD_FW_AFTER_START, \u0026mors-\u003estate_flags);\n2162:\t\tmm81x_mac_check_fw_disabled_chans(mors-\u003ehw);\n2163:\t\tieee80211_restart_hw(mors-\u003ehw);\n2164:\t\n2165:\texit:\n2166:\t\tmm81x_ps_enable(mors);\n"
} |
| 93/2 | 2026/09/21 14:30 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 49028 output: 210 thoughts: 1752 Thoughts: **Analysis of the Morse Micro USB Driver for Fuzzing**
Okay, let's break this down. My initial thought was about `mm81x_mac_restart` and the firmware initialization. Specifically, lines 2140-2144 raise a flag, pointing to `mm81x_fw_init`, which in turn involves `request_firmware`. The potential problem is that standard fuzzing environments, like what I'd expect from syzkaller, often lack the necessary firmware files. So the first instinct is to wonder if this is a hard stop.
However, I need to consider all possibilities. Can firmware be provided through other means, or is the `request_firmware` a definitive failure point? Then I thought about Syzkaller and its support for firmware. Does it have it? Generally no, or it depends on how it is built. Does it support loading firmware at all? I need to think this through carefully.
The core question revolves around the fuzzability of this code. To make a judgement, I re-read Sections 2 and 3 of the relevant documentation very carefully. The key is in the precise wording: "ONLY IF all modified code falls strictly into one or more of these categories".
The crucial insight here is the USB driver is accessible via virtual buses, specifically USB gadget / raw gadget emulation, which syzkaller supports! The driver code can be tested. And the modified code is within `mm81x_yaps_hw_read_pkts`, which is responsible for parsing packets coming from the hardware. The patch specifically fixes a bounds check, preventing an out-of-bounds read. This is crucial: the fix addresses a vulnerability that can be exploited, and the code path is reachable.
Now, let's nail down the specifics. The functions that are involved include: `mm81x_yaps_hw_read_pkts` (which is in `yaps_hw.c`), which is registered in `mm81x_yaps_hw_ops` and called through `mm81x_yaps_read_pkts` -> `mm81x_yaps_rx_handler` -> `mm81x_yaps_work`.
I need to confirm that these functions can be focus symbols. I think the static nature of `mm81x_yaps_hw_read_pkts` can be a problem, but it is unlikely to be inlined since it is a function pointer. I checked and verified that. Also, the function has a symbol. Other non-ubiquitous focus symbols are `mm81x_yaps_rx_handler` and `mm81x_yaps_work`.
Finally, the required configurations: `MM81X`, `MM81X_USB`, `MAC80211`, and `USB` are essential. Also, `WLAN_VENDOR_MORSEMICRO` is a config.
Therefore, after going through all the requirements, here's my final assessment:
* **WorthFuzzing: true**
* **FocusSymbols:**
* `mm81x_yaps_hw_read_pkts`
* `mm81x_yaps_rx_handler`
* `mm81x_yaps_work`
* **EnableConfigs:**
* `MM81X`
* `MM81X_USB`
* `WLAN_VENDOR_MORSEMICRO`
* `MAC80211`
* `USB`
I should go ahead and use `set-results` now.
|
| 94/2 | 2026/09/21 14:30 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"MM81X",
"MM81X_USB",
"WLAN_VENDOR_MORSEMICRO",
"MAC80211",
"USB"
],
"FocusSymbols": [
"mm81x_yaps_hw_read_pkts",
"mm81x_yaps_rx_handler",
"mm81x_yaps_work"
],
"Reasoning": "The patch adds a bounds check in mm81x_yaps_hw_read_pkts to prevent out-of-bounds reads when parsing received packet delimiters from the chip buffer. The Morse Micro MM81x wireless driver supports USB devices (CONFIG_MM81X_USB), which can be probed and fuzzed in standard virtualized environments using USB emulation (such as Raw Gadget). Therefore, the modified executable code is reachable and worth fuzzing.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"MM81X",
"MM81X_USB",
"WLAN_VENDOR_MORSEMICRO",
"MAC80211",
"USB"
],
"FocusSymbols": [
"mm81x_yaps_hw_read_pkts",
"mm81x_yaps_rx_handler",
"mm81x_yaps_work"
],
"Reasoning": "The patch adds a bounds check in mm81x_yaps_hw_read_pkts to prevent out-of-bounds reads when parsing received packet delimiters from the chip buffer. The Morse Micro MM81x wireless driver supports USB devices (CONFIG_MM81X_USB), which can be probed and fuzzed in standard virtualized environments using USB emulation (such as Raw Gadget). Therefore, the modified executable code is reachable and worth fuzzing.",
"WorthFuzzing": true
} |
| 95/1 | 2026/09/21 14:30 | action | If |
3mArgs:{
"WorthFuzzing": true
}Results: null |
| 96/2 | 2026/09/21 14:30 | agent | kmsan-evaluator |
3mModel:core Args: null Results: {
"KMSANReasoning": "The patch adds a bounds check in mm81x_yaps_hw_read_pkts() ensuring that bytes_remaining \u003e= sizeof(delim) before reading a 32-bit delimiter from read_ptr. Previously, if bytes_remaining was between 1 and 3, reading 4 bytes could perform an out-of-bounds read past the buffer or valid data and underflow bytes_remaining to a negative value, leading to severe out-of-bounds memcpy issues. These types of bugs (out-of-bounds reads/writes and buffer overflows) are directly caught by KASAN. The patch does not introduce or expose uninitialized memory, does not alter uninitialized padding or structures copied to user space, and does not branch on uninitialized variables. Therefore, a dedicated KMSAN fuzzing session is not justified.",
"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: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit 0ffa363bb947a4fc8b8cbb1ffa89fbf41b792e59
Author: syz-cluster <triage@syzkaller.com>
Date: Mon Sep 21 14:24:11 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/wireless/morsemicro/mm81x/yaps_hw.c b/drivers/net/wireless/morsemicro/mm81x/yaps_hw.c
index 3d641d23c35ba..e1102b8fb8020 100644
--- a/drivers/net/wireless/morsemicro/mm81x/yaps_hw.c
+++ b/drivers/net/wireless/morsemicro/mm81x/yaps_hw.c
@@ -486,6 +486,9 @@ static int mm81x_yaps_hw_read_pkts(struct mm81x_yaps *yaps,
int total_len;
int pkt_size;
+ if (bytes_remaining < (int)sizeof(delim))
+ break;
+
delim = le32_to_cpu(*((__le32 *)read_ptr));
read_ptr += sizeof(delim);
bytes_remaining -= sizeof(delim);
|
| 97/3 | 2026/09/21 14:30 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 2135 output: 49 thoughts: 468 Thoughts: **KMSAN Fuzzing Justification: A Quick Risk Assessment** Okay, so I've got this patch, and the question is: does it warrant firing up a KMSAN fuzzing session on top of the usual KASAN? Let's break this down. From a risk perspective, this looks pretty benign. It's a software quality and security check, purely defensive and QA-focused, no offensive shenanigans or exploit payload generation involved. This is all about safe and responsible testing. Now, let's get into the code itself. I need to take a look at the diff. I see the addition of a check within the `mm81x_yaps_hw_read_pkts` function in `drivers/net/wireless/morsemicro/mm81x/yaps_hw.c`. Specifically, it checks if `bytes_remaining` is large enough to contain `sizeof(delim)` before proceeding. This clearly addresses a potential buffer underrun. I'm going to take a closer look at the `mm81x_yaps_hw_read_pkts` function, line by line, to understand the context and implications of this added check. Okay, time to pull up the source code for a better look around line 486. |
| 98/3 | 2026/09/21 14:30 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/yaps_hw.c",
"FirstLine": 460,
"LineCount": 70
}Results: {
"Contents": " 460:\t\t\tbytes_remaining = YAPS_HW_WINDOW_SIZE_BYTES;\n 461:\t\t\tagain = true;\n 462:\t\t}\n 463:\t\n 464:\t\t/*\n 465:\t\t * This is more coarse-grained than it needs to be - once the data\n 466:\t\t * is read into a local buffer the lock can be released, however\n 467:\t\t * access to from_chip_buffer will need to be protected with its\n 468:\t\t * own lock\n 469:\t\t */\n 470:\t\tret = mm81x_yaps_hw_lock(yaps);\n 471:\t\tif (ret) {\n 472:\t\t\tdev_dbg(yaps-\u003emors-\u003edev, \"yaps lock failed %d\", ret);\n 473:\t\t\treturn ret;\n 474:\t\t}\n 475:\t\n 476:\t\t/* Read all available packets to the buffer */\n 477:\t\tret = mm81x_dm_read(yaps-\u003emors, yaps-\u003eaux_data-\u003eysl_addr,\n 478:\t\t\t\t from_chip_buffer_aligned, bytes_remaining);\n 479:\t\n 480:\t\tif (ret)\n 481:\t\t\tgoto exit;\n 482:\t\n 483:\t\t/* Split serialised packets from buffer */\n 484:\t\twhile (i \u003c num_pkts_max \u0026\u0026 bytes_remaining \u003e 0) {\n 485:\t\t\tu32 delim;\n 486:\t\t\tint total_len;\n 487:\t\t\tint pkt_size;\n 488:\t\n 489:\t\t\tif (bytes_remaining \u003c (int)sizeof(delim))\n 490:\t\t\t\tbreak;\n 491:\t\n 492:\t\t\tdelim = le32_to_cpu(*((__le32 *)read_ptr));\n 493:\t\t\tread_ptr += sizeof(delim);\n 494:\t\t\tbytes_remaining -= sizeof(delim);\n 495:\t\n 496:\t\t\t/* End of stream */\n 497:\t\t\tif (!delim)\n 498:\t\t\t\tbreak;\n 499:\t\n 500:\t\t\tif (!mm81x_read_pkts_h_is_valid_delim(delim)) {\n 501:\t\t\t\t/*\n 502:\t\t\t\t * This will start a hunt for a valid delimiter. Given\n 503:\t\t\t\t * the CRC is only 7 bit it's possible to find an\n 504:\t\t\t\t * invalid block with a valid delimiter, leading to\n 505:\t\t\t\t * desynchronisation.\n 506:\t\t\t\t */\n 507:\t\t\t\tdev_warn(yaps-\u003emors-\u003edev, \"yaps invalid delim\");\n 508:\t\t\t\tbreak;\n 509:\t\t\t}\n 510:\t\n 511:\t\t\t/* Total length in chip */\n 512:\t\t\tpkt_size = YAPS_DELIM_GET_PKT_SIZE(delim);\n 513:\t\t\ttotal_len = pkt_size + YAPS_DELIM_GET_PADDING(delim);\n 514:\t\n 515:\t\t\tif (pkts[i].skb)\n 516:\t\t\t\tdev_err(yaps-\u003emors-\u003edev, \"yaps packet leak\");\n 517:\t\n 518:\t\t\t/* SKB doesn't want padding */\n 519:\t\t\tpkts[i].skb = dev_alloc_skb(pkt_size);\n 520:\t\t\tif (!pkts[i].skb) {\n 521:\t\t\t\tret = -ENOMEM;\n 522:\t\t\t\tdev_err(yaps-\u003emors-\u003edev, \"yaps no mem for skb\");\n 523:\t\t\t\tgoto exit;\n 524:\t\t\t}\n 525:\t\t\tskb_put(pkts[i].skb, pkt_size);\n 526:\t\n 527:\t\t\tif (total_len \u003c= bytes_remaining) {\n 528:\t\t\t\tmemcpy(pkts[i].skb-\u003edata, read_ptr, pkt_size);\n 529:\t\t\t\tread_ptr += total_len;\n"
} |
| 99/3 | 2026/09/21 14:30 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 3995 output: 49 thoughts: 23 Thoughts: Okay, here's my interpretation of what's going on, framed as a first-person expert perspective: **Diving into `mm81x_yaps_hw_read_pkts`** Alright, let's get into the details of `mm81x_yaps_hw_read_pkts`. I need to understand this function's role in the larger picture, especially concerning the MM81x and YAPS hardware interaction. I'm assuming, based on the naming, that this is the low-level function responsible for reading packets directly from the hardware. I need to figure out the exact flow, the data structures it uses, and how it handles potential errors. Is it reading directly from DMA buffers? Is there any kind of hardware-level acknowledgement or synchronization involved? I'm particularly interested in any potential bottlenecks or areas where performance could be an issue, especially in a high-throughput scenario. What kind of interrupt handling is in place, if any? I need to look for any optimizations employed here, and if not, where I might be able to implement them. The function's interaction with the higher layers, specifically any queue management or buffer allocation strategies, is key to its overall efficiency. |
| 100/3 | 2026/09/21 14:30 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/yaps_hw.c",
"FirstLine": 525,
"LineCount": 40
}Results: {
"Contents": " 525:\t\t\tskb_put(pkts[i].skb, pkt_size);\n 526:\t\n 527:\t\t\tif (total_len \u003c= bytes_remaining) {\n 528:\t\t\t\tmemcpy(pkts[i].skb-\u003edata, read_ptr, pkt_size);\n 529:\t\t\t\tread_ptr += total_len;\n 530:\t\t\t\tbytes_remaining -= total_len;\n 531:\t\t\t} else {\n 532:\t\t\t\tconst int read_overhang_len =\n 533:\t\t\t\t\ttotal_len - bytes_remaining;\n 534:\t\t\t\tconst int pkt_overhang_len = pkt_size - bytes_remaining;\n 535:\t\n 536:\t\t\t\tmemcpy(pkts[i].skb-\u003edata, read_ptr, bytes_remaining);\n 537:\t\t\t\tread_ptr = from_chip_buffer_aligned;\n 538:\t\n 539:\t\t\t\tret = mm81x_dm_read(\n 540:\t\t\t\t\tyaps-\u003emors,\n 541:\t\t\t\t\t/* Offset by 4 to avoid retry logic */\n 542:\t\t\t\t\tyaps-\u003eaux_data-\u003eysl_addr + 4, read_ptr,\n 543:\t\t\t\t\tread_overhang_len);\n 544:\t\n 545:\t\t\t\tif (ret)\n 546:\t\t\t\t\tgoto exit;\n 547:\t\n 548:\t\t\t\tmemcpy(pkts[i].skb-\u003edata + bytes_remaining, read_ptr,\n 549:\t\t\t\t pkt_overhang_len);\n 550:\t\t\t\tread_ptr += read_overhang_len;\n 551:\t\t\t\tbytes_remaining = 0;\n 552:\t\t\t}\n 553:\t\n 554:\t\t\t*num_pkts_received += 1;\n 555:\t\t\ti++;\n 556:\t\t}\n 557:\t\n 558:\t\tif (again)\n 559:\t\t\tret = -EAGAIN;\n 560:\t\n 561:\texit:\n 562:\t\tmm81x_yaps_hw_unlock(yaps);\n 563:\t\treturn ret;\n 564:\t}\n"
} |
| 101/3 | 2026/09/21 14:30 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 4902 output: 49 thoughts: 23 Thoughts: Okay, here's my attempt at summarizing the thought process, as requested, in the first person and assuming an expert audience: **Diving into `mm81x_yaps_hw_read_pkts`** Alright, let's get down to brass tacks. I'm taking a look at the `mm81x_yaps_hw_read_pkts` function. Given the naming convention, it's pretty clear this is a hardware-level packet reading function, likely related to a YAPS (Yet Another Packet Stream) or a similar low-level packet processing block within an mm81x system. I need to understand its role in the data path. My initial thoughts are: * **Entry Point & Context:** I want to get a grip on how this function is called. What are the calling conventions? Who's calling it? Is it interrupt-driven or polled? Knowing the context immediately tells me the expected throughput and latency constraints. Is this a critical path function? * **Hardware Interface:** I'm assuming that this function interacts directly with some kind of hardware registers for data transfer. Understanding the memory map, register definitions, and bitfields is key. I'll need to identify the relevant addresses for FIFOs, status registers, and control bits. * **Packet Buffer Management:** How does the function handle packet buffers? Are we talking about a DMA-based approach, or are packets transferred directly into system memory? Are there pre-allocated buffers, or is dynamic allocation involved? I need to understand the memory allocation and deallocation strategy to identify any potential bottlenecks or memory corruption risks. * **Error Handling:** It's absolutely critical to examine the error handling. What mechanisms are in place to detect and handle hardware errors (e.g., FIFO overflows, parity errors, incorrect checksums)? How are these errors reported? What are the recovery strategies? Robustness at this level is paramount. * **Synchronization & Concurrency:** This is a multi-threaded or multi-core environment, I need to know how this function handles synchronization, especially if there are shared resources (e.g., hardware registers, packet buffers). Are there any race conditions? Mutexes? Spinlocks? Atomic operations? * **Data Validation and Processing:** Does this function perform any basic packet validation (e.g., length checks, checksum verification) before passing the packet up the stack? What's the data format (e.g., Ethernet, custom framing)? Are there any format translations or header manipulations happening here? I need to see the code, and probably some surrounding code, to answer all these questions. Time to dig in! |
| 102/3 | 2026/09/21 14:30 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/yaps_hw.c",
"FirstLine": 430,
"LineCount": 40
}Results: {
"Contents": " 430:\t\n 431:\t\tif (WARN_ON(bytes_in_queue \u003e INT_MAX) ||\n 432:\t\t WARN_ON(delim_overhead \u003e INT_MAX) ||\n 433:\t\t WARN_ON(reserved_bytes \u003e INT_MAX))\n 434:\t\t\treturn -EIO;\n 435:\t\n 436:\t\treturn (int)bytes_in_queue;\n 437:\t}\n 438:\t\n 439:\tstatic int mm81x_yaps_hw_read_pkts(struct mm81x_yaps *yaps,\n 440:\t\t\t\t\t struct mm81x_yaps_pkt *pkts,\n 441:\t\t\t\t\t int num_pkts_max, int *num_pkts_received)\n 442:\t{\n 443:\t\tint ret;\n 444:\t\tint i = 0;\n 445:\t\tchar *from_chip_buffer_aligned =\n 446:\t\t\tPTR_ALIGN(yaps-\u003eaux_data-\u003efrom_chip_buffer,\n 447:\t\t\t\t mm81x_bus_get_alignment(yaps-\u003emors));\n 448:\t\tchar *read_ptr = from_chip_buffer_aligned;\n 449:\t\tint bytes_remaining = mm81x_read_pkts_h_bytes_remaining(yaps);\n 450:\t\tbool again = false;\n 451:\t\n 452:\t\t*num_pkts_received = 0;\n 453:\t\n 454:\t\tif (num_pkts_max == 0 || bytes_remaining == 0)\n 455:\t\t\treturn 0;\n 456:\t\tif (bytes_remaining \u003c 0)\n 457:\t\t\treturn bytes_remaining;\n 458:\t\n 459:\t\tif (bytes_remaining \u003e YAPS_HW_WINDOW_SIZE_BYTES) {\n 460:\t\t\tbytes_remaining = YAPS_HW_WINDOW_SIZE_BYTES;\n 461:\t\t\tagain = true;\n 462:\t\t}\n 463:\t\n 464:\t\t/*\n 465:\t\t * This is more coarse-grained than it needs to be - once the data\n 466:\t\t * is read into a local buffer the lock can be released, however\n 467:\t\t * access to from_chip_buffer will need to be protected with its\n 468:\t\t * own lock\n 469:\t\t */\n"
} |
| 103/3 | 2026/09/21 14:30 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 6184 output: 35 thoughts: 163 Thoughts: **Analyzing the Pre-Patch Vulnerability** Okay, let's dissect this. Before the patch was applied, `bytes_remaining` could have held a value greater than zero, but less than four. We're talking 1, 2, or 3 bytes left. Then, we hit this block of code: ```c delim = le32_to_cpu(*((__le32 *)read_ptr)); read_ptr += sizeof(delim); bytes_remaining -= sizeof(delim); ``` And it's clear: Reading four bytes (`sizeof(delim)`) when fewer than four are available is a recipe for disaster. This is classic out-of-bounds read territory. It's almost guaranteed to read past the allocated `from_chip_buffer_aligned` which is derived from the size of the `from_chip_buffer` itself or even beyond what `mm81x_dm_read` actually read. Now, the critical question is, how large is `from_chip_buffer`? I need to check its size to fully understand the scope of this vulnerability and confirm how big the possible out-of-bounds read is. |
| 104/3 | 2026/09/21 14:30 | tool | grepper |
0mArgs:{
"Expression": "from_chip_buffer",
"PathPrefix": "drivers/net/wireless/morsemicro/"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/yaps_hw.c=98=struct mm81x_yaps_hw_aux_data {\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-126-\tchar *to_chip_buffer;\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:127:\tchar *from_chip_buffer;\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-128-\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c=439=static int mm81x_yaps_hw_read_pkts(struct mm81x_yaps *yaps,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-444-\tint i = 0;\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:445:\tchar *from_chip_buffer_aligned =\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:446:\t\tPTR_ALIGN(yaps-\u003eaux_data-\u003efrom_chip_buffer,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-447-\t\t\t mm81x_bus_get_alignment(yaps-\u003emors));\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:448:\tchar *read_ptr = from_chip_buffer_aligned;\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-449-\tint bytes_remaining = mm81x_read_pkts_h_bytes_remaining(yaps);\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-466-\t * is read into a local buffer the lock can be released, however\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:467:\t * access to from_chip_buffer will need to be protected with its\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-468-\t * own lock\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-477-\tret = mm81x_dm_read(yaps-\u003emors, yaps-\u003eaux_data-\u003eysl_addr,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:478:\t\t\t from_chip_buffer_aligned, bytes_remaining);\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-479-\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-536-\t\t\tmemcpy(pkts[i].skb-\u003edata, read_ptr, bytes_remaining);\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:537:\t\t\tread_ptr = from_chip_buffer_aligned;\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-538-\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c=650=int mm81x_yaps_hw_init(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-670-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:671:\tyaps-\u003eaux_data-\u003efrom_chip_buffer =\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-672-\t\tkzalloc(YAPS_HW_WINDOW_SIZE_BYTES + alignment - 1, GFP_KERNEL);\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:673:\tif (!yaps-\u003eaux_data-\u003efrom_chip_buffer) {\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-674-\t\tret = -ENOMEM;\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c=692=void mm81x_yaps_hw_finish(struct mm81x *mors)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-697-\tif (yaps-\u003eaux_data) {\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:698:\t\tkfree(yaps-\u003eaux_data-\u003efrom_chip_buffer);\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:699:\t\tyaps-\u003eaux_data-\u003efrom_chip_buffer = NULL;\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-700-\t\tkfree(yaps-\u003eaux_data-\u003eto_chip_buffer);\n"
} |
| 105/3 | 2026/09/21 14:30 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 7937 output: 41 thoughts: 441 Thoughts: **Analyzing a Potential Read Buffer Overrun in the YAPS Hardware Driver**
Okay, let's break this down. My initial thought is to examine how `from_chip_buffer` is allocated in `mm81x_yaps_hw_init` – `kzalloc` with the addition of alignment. I need to keep that in mind. Then, looking at `mm81x_yaps_hw_read_pkts`, I'm keying in on `bytes_remaining`. This variable tracks the amount of data still to be processed from the buffer.
The scenario in my head is this: if `bytes_remaining` is, say, just 2 bytes, but then the code attempts to read a 4-byte delimiter (`sizeof(delim)`), it's a problem. Before the patch, the `while` loop condition `bytes_remaining > 0` would be satisfied, and the code would read the 4-byte `delim` value via `le32_to_cpu`. This leads to `read_ptr` incrementing, and `bytes_remaining` going *negative* (2 - 4 = -2). Uh oh.
Then, there's the following sequence, and it smells really bad if `bytes_remaining` is negative:
```c
pkt_size = YAPS_DELIM_GET_PKT_SIZE(delim);
total_len = pkt_size + YAPS_DELIM_GET_PADDING(delim);
...
if (total_len <= bytes_remaining) {
memcpy(pkts[i].skb->data, read_ptr, pkt_size);
...
} else {
const int read_overhang_len =
total_len - bytes_remaining;
const int pkt_overhang_len = pkt_size - bytes_remaining;
```
If `bytes_remaining` is negative or is smaller than `total_len`, this is almost certainly a read buffer overrun or underflow. The `read_overhang_len` and `pkt_overhang_len` calculations look like they would trigger incorrect lengths being passed to the `memcpy`.
Now, the question is, what triggered this? What did syzbot find, or what problem was this patch fixing? I need to go digging into the git logs for this file. That will hopefully give me context and explain why this vulnerability was found.
|
| 106/3 | 2026/09/21 14:30 | tool | grepper |
0mArgs:{
"Expression": "bytes_remaining \u003c \\(int\\)sizeof\\(delim\\)",
"PathPrefix": "drivers/net/wireless/morsemicro/"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/yaps_hw.c=439=static int mm81x_yaps_hw_read_pkts(struct mm81x_yaps *yaps,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-488-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:489:\t\tif (bytes_remaining \u003c (int)sizeof(delim))\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-490-\t\t\tbreak;\n"
} |
| 107/3 | 2026/09/21 14:30 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 9110 output: 38 thoughts: 216 Thoughts: **Analyzing this Patch: A Deep Dive** Okay, let's break this down. My initial question is always, "What problem is this patch solving, or what new functionality does it introduce?" Right away, I see the addition of this crucial `if` statement: ```c + if (bytes_remaining < (int)sizeof(delim)) + break; ``` Immediately, my mind starts tracing the flow. Before this check, the code was vulnerable to a memory access issue if `bytes_remaining` was a small positive value, specifically, between 1 and the size of `delim`. This means, if there were, say, only one, two, or three bytes left in `from_chip_buffer_aligned`, it would attempt to dereference `*(__le32 *)read_ptr`, which attempts to read 4 bytes. Hold on a second... Could those bytes in `from_chip_buffer` actually be uninitialized data? That would be a serious bug! Now I need to know where it's allocated. Okay, good. Let me see... `from_chip_buffer` is allocated with `kzalloc` in `mm81x_yaps_hw_init`! That's `k[z]alloc` which is *great* because `kzalloc` zeroes the memory. This means the buffer is properly initialized to zero, which eliminates the possibility of uninitialized data in this instance! Wait, but what is `mm81x_dm_read` doing? Let me pull up the definition of `mm81x_dm_read` to be certain! I need to ensure that the code path does not lead to potential issues. |
| 108/3 | 2026/09/21 14:31 | tool | grepper |
0mArgs:{
"Expression": "mm81x_dm_read",
"PathPrefix": "drivers/net/wireless/morsemicro/"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/bus.h=17=struct mm81x_bus_ops {\n--\ndrivers/net/wireless/morsemicro/mm81x/bus.h-36-\ndrivers/net/wireless/morsemicro/mm81x/bus.h:37:/* mm81x_dm_read - len must be rounded up to the nearest 4-byte boundary */\ndrivers/net/wireless/morsemicro/mm81x/bus.h:38:static inline int mm81x_dm_read(struct mm81x *mors, u32 addr, u8 *data, int len)\ndrivers/net/wireless/morsemicro/mm81x/bus.h-39-{\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c=447=static int mm81x_fw_read_ext_host_table(struct mm81x *mors,\n--\ndrivers/net/wireless/morsemicro/mm81x/fw.c-489-\ndrivers/net/wireless/morsemicro/mm81x/fw.c:490:\tret = mm81x_dm_read(mors, ext_host_tbl_ptr, (u8 *)host_tbl,\ndrivers/net/wireless/morsemicro/mm81x/fw.c-491-\t\t\t (int)ext_host_tbl_len);\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c=439=static int mm81x_yaps_hw_read_pkts(struct mm81x_yaps *yaps,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-476-\t/* Read all available packets to the buffer */\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:477:\tret = mm81x_dm_read(yaps-\u003emors, yaps-\u003eaux_data-\u003eysl_addr,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-478-\t\t\t from_chip_buffer_aligned, bytes_remaining);\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-538-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:539:\t\t\tret = mm81x_dm_read(\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-540-\t\t\t\tyaps-\u003emors,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c=566=static int mm81x_yaps_hw_update_status(struct mm81x_yaps *yaps)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-588-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:589:\t\tret = mm81x_dm_read(yaps-\u003emors,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-590-\t\t\t\t yaps-\u003eaux_data-\u003estatus_regs_addr,\n"
} |
| 109/3 | 2026/09/21 14:31 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 10561 output: 45 thoughts: 36 Thoughts: Here's my take on the `mm81x_dm_read` function: **Diving into the mm81x Data Management Read Function** Okay, so I'm looking at the `mm81x_dm_read` function, specifically within the `drivers/net/wireless/morsemicro/mm81x/bus.h` header file. Right, I need to understand how this data management read function is implemented for this specific Morse Micro wireless chip. I'm assuming it handles reading data from some sort of device memory or register space, likely over a bus interface. I'm immediately interested in how they've handled the low-level bus access - are they using direct memory access, some kind of polling mechanism, or interrupts? And what about the data size and alignment considerations for the specific MM81x architecture? It's the usual suspects when you're dealing with device drivers: potential race conditions, error handling for I/O errors and, of course, memory barrier usage to maintain data integrity. Let's see how they approach it... this should be interesting. I'm hoping for some clean, well-commented code, given this is likely a critical part of the wireless stack. |
| 110/3 | 2026/09/21 14:31 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/bus.h",
"FirstLine": 35,
"LineCount": 20
}Results: {
"Contents": " 35:\t#define MM81X_BUS_DEFAULT_BULK_ALIGNMENT (2)\n 36:\t\n 37:\t/* mm81x_dm_read - len must be rounded up to the nearest 4-byte boundary */\n 38:\tstatic inline int mm81x_dm_read(struct mm81x *mors, u32 addr, u8 *data, int len)\n 39:\t{\n 40:\t\treturn mors-\u003ebus_ops-\u003edm_read(mors, addr, data, len);\n 41:\t}\n 42:\t\n 43:\tstatic inline int mm81x_dm_write(struct mm81x *mors, u32 addr, const u8 *data,\n 44:\t\t\t\t\t int len)\n 45:\t{\n 46:\t\treturn mors-\u003ebus_ops-\u003edm_write(mors, addr, data, len);\n 47:\t}\n 48:\t\n 49:\tstatic inline int mm81x_reg32_read(struct mm81x *mors, u32 addr, u32 *data)\n 50:\t{\n 51:\t\treturn mors-\u003ebus_ops-\u003ereg32_read(mors, addr, data);\n 52:\t}\n 53:\t\n 54:\tstatic inline int mm81x_reg32_write(struct mm81x *mors, u32 addr, u32 data)\n"
} |
| 111/3 | 2026/09/21 14:31 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 11280 output: 49 thoughts: 91 Thoughts: **Analyzing a Potential Vulnerability in Packet Handling** Okay, let's break this down. My initial focus is on the condition where `bytes_remaining` falls below the size of the delimiter (`delim`). Specifically, I'm thinking about the implications of that inequality within `mm81x_yaps_hw_read_pkts`. The key here is that `bytes_remaining` originates from a call to `mm81x_read_pkts_h_bytes_remaining(yaps)`. So, before I go any further, I need to understand how *that* function calculates its value. I'll need to dig into `mm81x_read_pkts_h_bytes_remaining` and scrutinize its logic. Only then can I properly assess the potential vulnerability in the comparison itself. |
| 112/3 | 2026/09/21 14:31 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/yaps_hw.c",
"FirstLine": 400,
"LineCount": 40
}Results: {
"Contents": " 400:\t\n 401:\tstatic bool mm81x_read_pkts_h_is_valid_delim(u32 delim)\n 402:\t{\n 403:\t\tu8 calc_crc = mm81x_yaps_hw_crc(delim);\n 404:\t\tint pkt_size = YAPS_DELIM_GET_PHANDLE_SIZE(delim);\n 405:\t\tint padding = YAPS_DELIM_GET_PADDING(delim);\n 406:\t\n 407:\t\tif (calc_crc != YAPS_DELIM_GET_CRC(delim))\n 408:\t\t\treturn false;\n 409:\t\n 410:\t\tif (pkt_size == 0)\n 411:\t\t\treturn false;\n 412:\t\n 413:\t\tif ((pkt_size + padding) \u003e YAPS_MAX_PKT_SIZE_BYTES)\n 414:\t\t\treturn false;\n 415:\t\n 416:\t\t/* Pkt length + padding should not require more padding */\n 417:\t\tif (YAPS_CALC_PADDING(pkt_size) != padding)\n 418:\t\t\treturn false;\n 419:\t\n 420:\t\treturn true;\n 421:\t}\n 422:\t\n 423:\tstatic int mm81x_read_pkts_h_bytes_remaining(struct mm81x_yaps *yaps)\n 424:\t{\n 425:\t\tu32 bytes_in_queue = yaps-\u003eaux_data-\u003estatus_regs.fc_rx_bytes_in_queue;\n 426:\t\tu32 delim_overhead =\n 427:\t\t\tyaps-\u003eaux_data-\u003estatus_regs.fc_num_pkts * sizeof(u32);\n 428:\t\tu32 reserved_bytes = yaps-\u003eaux_data-\u003estatus_regs.fc_num_pkts *\n 429:\t\t\t\t yaps-\u003eaux_data-\u003ereserved_yaps_page_size;\n 430:\t\n 431:\t\tif (WARN_ON(bytes_in_queue \u003e INT_MAX) ||\n 432:\t\t WARN_ON(delim_overhead \u003e INT_MAX) ||\n 433:\t\t WARN_ON(reserved_bytes \u003e INT_MAX))\n 434:\t\t\treturn -EIO;\n 435:\t\n 436:\t\treturn (int)bytes_in_queue;\n 437:\t}\n 438:\t\n 439:\tstatic int mm81x_yaps_hw_read_pkts(struct mm81x_yaps *yaps,\n"
} |
| 113/3 | 2026/09/21 14:31 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 12286 output: 34 thoughts: 537 Thoughts: **Analyzing Potential Buffer Overrun Vulnerability** Okay, let's break this down. I'm looking at this snippet and immediately see a potential issue with how `bytes_remaining` is being handled. The goal seems to be to read data from a device, parse packets from that data, and then process them. First, I see `bytes_remaining` represents the number of bytes available in the input queue. We then call `mm81x_dm_read` to populate a buffer (`from_chip_buffer_aligned`) with data read from a device, presumably a DMA read or some form of direct memory access, but it's not clear what bus the device is even using yet. The problem comes in the loop where we extract packet data. The loop condition `bytes_remaining > 0` looks fine, but the critical part is inside the loop. We check if `bytes_remaining` is less than the size of the delimiter (`sizeof(delim)`). If that check is bypassed, let's say `bytes_remaining` is 1, 2, or 3, then it's going to try to read a 4-byte delimiter from the buffer, but there are less than 4 bytes available. This looks like it could lead to an out-of-bounds read, because we're dereferencing a pointer (`read_ptr`) to read the delimiter without adequately validating the amount of data we have available. We then decrement `bytes_remaining` by `sizeof(delim)`, even if we didn't actually read `sizeof(delim)` bytes. This is where things get really bad; `bytes_remaining` could become negative! My initial thoughts are that if `bytes_remaining` is 1, 2, or 3, and then `bytes_remaining` becomes negative, how do we know what data from the device to expect after? Is the data corrupted? Even more worrying is that while `mm81x_dm_read` will only have written up to `bytes_remaining` bytes from the device into the buffer, the subsequent operations assume that entire `delim` is valid. We have kzalloc'd the buffer initially, so at least we're starting with zeroed memory. But the call to `mm81x_dm_read` overwrites that. It's the `dm_read` that's the key, I need to check its implementation, and the bus in use (SDIO, SPI, USB, PCIe) will be very important in determining whether we have a buffer overflow vulnerability, or simply a misinterpretation of the data. That bus's read behavior might also subtly influence how the data is read/interpreted. It's time to check what `bus_ops->dm_read` is. |
| 114/3 | 2026/09/21 14:31 | tool | grepper |
0mArgs:{
"Expression": "\\.dm_read",
"PathPrefix": "drivers/net/wireless/morsemicro/"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/sdio.c=481=static const struct mm81x_bus_ops mm81x_sdio_ops = {\ndrivers/net/wireless/morsemicro/mm81x/sdio.c:482:\t.dm_read = mm81x_sdio_dm_read,\ndrivers/net/wireless/morsemicro/mm81x/sdio.c-483-\t.dm_write = mm81x_sdio_dm_write,\n--\ndrivers/net/wireless/morsemicro/mm81x/usb.c=563=static const struct mm81x_bus_ops mm81x_usb_ops = {\ndrivers/net/wireless/morsemicro/mm81x/usb.c:564:\t.dm_read = mm81x_usb_dm_read,\ndrivers/net/wireless/morsemicro/mm81x/usb.c-565-\t.dm_write = mm81x_usb_dm_write,\n"
} |
| 115/3 | 2026/09/21 14:31 | llm | kmsan-evaluator |
1mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 13720 output: 47 thoughts: 33 Thoughts: Okay, let's dive into this. Here's my take on those functions, as if they were my own mental process: **Diving into DMA Reads: SDIO and USB** Alright, time to get a grip on these `mm81x_sdio_dm_read` and `mm81x_usb_dm_read` functions. I need to understand their roles in this DMA data transfer process. My assumption is that the "mm81x" prefix is likely specific to the hardware or the device driver architecture of this system and this is the specific driver implementation. I need to quickly analyze how these routines handle data retrieval via Direct Memory Access (DMA) from SDIO and USB peripherals, respectively. I expect `_dm_read` to denote a DMA read operation. The key will be understanding how these functions are configured for that functionality. I'll be looking for things like: * **Hardware Initialization:** Are the DMA channels initialized within these functions, or assumed to be setup elsewhere? Are there register writes to enable and configure the DMA controller for these specific peripherals? * **Buffer Management:** How are the source and destination buffers handled? Is there a pointer to a buffer in memory, or are they built into the function? Is there any buffer allocation or deallocation within these functions? * **Descriptor Chaining:** Is descriptor chaining used? If so, I need to see how the transfer descriptors are created and linked. * **Interrupt Handling:** Does the code set up an interrupt to be triggered upon DMA completion? If so, what interrupt handler is assigned, and what does it do? * **Error Handling:** Are there any checks for errors during the DMA transfer? How are errors signaled or handled? * **Peripheral Specifics:** How do these functions differ based on the peripheral (SDIO vs. USB)? Are there any configuration steps specific to the SDIO controller or the USB host controller? Ultimately, my goal is to grasp how DMA is orchestrated to efficiently read data from these interfaces. |
| 116/3 | 2026/09/21 14:32 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/sdio.c",
"FirstLine": 400,
"LineCount": 50
}Results: {
"Contents": " 400:\terror:\n 401:\t\tif (original_address == MM81X_REG_RESET(mors) \u0026\u0026\n 402:\t\t val == MM81X_REG_RESET_VALUE(mors)) {\n 403:\t\t\tdev_dbg(mors-\u003edev,\n 404:\t\t\t\t\"SDIO reset detected, invalidating base addr\\n\");\n 405:\t\t\tmm81x_sdio_reset_base_address(sdio);\n 406:\t\t}\n 407:\t\n 408:\t\treturn -EIO;\n 409:\t}\n 410:\t\n 411:\tstatic int mm81x_sdio_reg32_read(struct mm81x *mors, u32 address, u32 *val)\n 412:\t{\n 413:\t\tu32 value;\n 414:\t\tssize_t ret = 0;\n 415:\t\tstruct mm81x_sdio *sdio = (struct mm81x_sdio *)mors-\u003edrv_priv;\n 416:\t\tstruct sdio_func *func1 = sdio-\u003efunc-\u003ecard-\u003esdio_func[0];\n 417:\t\n 418:\t\tmm81x_sdio_set_func_address_base(sdio, func1, address,\n 419:\t\t\t\t\t\t MM81X_CONFIG_ACCESS_4BYTE);\n 420:\t\n 421:\t\taddress \u0026= 0x0000FFFF;\n 422:\t\tvalue = sdio_readl(func1, (__force u32)cpu_to_le32(address),\n 423:\t\t\t\t (int *)\u0026ret);\n 424:\t\tif (ret)\n 425:\t\t\treturn ret;\n 426:\t\n 427:\t\t*val = le32_to_cpup((__le32 *)\u0026value);\n 428:\t\treturn 0;\n 429:\t}\n 430:\t\n 431:\tstatic void mm81x_sdio_bus_enable(struct mm81x *mors, bool enable)\n 432:\t{\n 433:\t\tstruct mm81x_sdio *sdio = (struct mm81x_sdio *)mors-\u003edrv_priv;\n 434:\t\tstruct sdio_func *func = sdio-\u003efunc;\n 435:\t\tstruct mmc_host *host = func-\u003ecard-\u003ehost;\n 436:\t\n 437:\t\tsdio_claim_host(func);\n 438:\t\n 439:\t\tif (enable) {\n 440:\t\t\t/*\n 441:\t\t\t * No need to do anything special to re-enable the sdio bus.\n 442:\t\t\t * This will happen automatically when a read/write is\n 443:\t\t\t * attempted and sdio-\u003ebulk_addr_base == 0.\n 444:\t\t\t */\n 445:\t\t\tsdio-\u003eenabled = true;\n 446:\t\t\thost-\u003eops-\u003eenable_sdio_irq(host, 1);\n 447:\t\t\tdev_dbg(mors-\u003edev, \"%s: enabling bus\\n\", __func__);\n 448:\t\t} else {\n 449:\t\t\thost-\u003eops-\u003eenable_sdio_irq(host, 0);\n"
} |
| 117/3 | 2026/09/21 14:32 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 15096 output: 41 thoughts: 20 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Tracing the Data Move** Okay, so I need to understand what `mm81x_sdio_dm_read` is doing. Where's it defined? Let me quickly find the declaration for this function to start my tracing. I suspect it's involved in the SDIO data transfer, but I need to see the implementation to confirm my assumptions and understand the data path. Knowing the source will immediately shed light on how they're handling the DMA. I need the function definition to understand if it's acting as a higher-level abstraction, handling the register setup directly, or interacting with a lower-level driver component. This quickly reveals the level of abstraction this piece is operating at and will inform what to look for next. I'm looking for the nitty gritty, so I can see what I need to see. |
| 118/3 | 2026/09/21 14:32 | tool | grepper |
0mArgs:{
"Expression": "mm81x_sdio_dm_read",
"PathPrefix": "drivers/net/wireless/morsemicro/"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/sdio.c=269=static int mm81x_sdio_dm_write(struct mm81x *mors, u32 address, const u8 *data,\n--\ndrivers/net/wireless/morsemicro/mm81x/sdio.c-325-\ndrivers/net/wireless/morsemicro/mm81x/sdio.c:326:static int mm81x_sdio_dm_read(struct mm81x *mors, u32 address, u8 *data,\ndrivers/net/wireless/morsemicro/mm81x/sdio.c-327-\t\t\t int len)\n--\ndrivers/net/wireless/morsemicro/mm81x/sdio.c=481=static const struct mm81x_bus_ops mm81x_sdio_ops = {\ndrivers/net/wireless/morsemicro/mm81x/sdio.c:482:\t.dm_read = mm81x_sdio_dm_read,\ndrivers/net/wireless/morsemicro/mm81x/sdio.c-483-\t.dm_write = mm81x_sdio_dm_write,\n"
} |
| 119/3 | 2026/09/21 14:32 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 15670 output: 40 thoughts: 19 Thoughts: Okay, let's dive into this. Here's my perspective on this specific point of investigation: **Focusing In: `mm81x_usb_dm_read`** Right, so we're looking at something. I've been considering a few things, and it feels like we need to take a closer look at `mm81x_usb_dm_read`. This function is likely a key component, and its behavior could hold significant clues. I suspect it's involved in the data movement or initialization, potentially related to something I'm trying to diagnose. Focusing on this function is important. Let's see what we can find. |
| 120/3 | 2026/09/21 14:32 | tool | grepper |
0mArgs:{
"Expression": "mm81x_usb_dm_read",
"PathPrefix": "drivers/net/wireless/morsemicro/"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/usb.c=391=static int mm81x_usb_mem_write(struct mm81x_usb *musb, u32 address, u8 *data,\n--\ndrivers/net/wireless/morsemicro/mm81x/usb.c-458-\ndrivers/net/wireless/morsemicro/mm81x/usb.c:459:static int mm81x_usb_dm_read(struct mm81x *mors, u32 address, u8 *data, int len)\ndrivers/net/wireless/morsemicro/mm81x/usb.c-460-{\n--\ndrivers/net/wireless/morsemicro/mm81x/usb.c=563=static const struct mm81x_bus_ops mm81x_usb_ops = {\ndrivers/net/wireless/morsemicro/mm81x/usb.c:564:\t.dm_read = mm81x_usb_dm_read,\ndrivers/net/wireless/morsemicro/mm81x/usb.c-565-\t.dm_write = mm81x_usb_dm_write,\n"
} |
| 121/3 | 2026/09/21 14:32 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 16178 output: 44 thoughts: 1770 Thoughts: **Analysis of a Potential Out-of-Bounds Read in `mm81x_yaps_hw_read_pkts`** Okay, let's break this down. The code in `mm81x_yaps_hw_read_pkts` is responsible for parsing serialized packets from a buffer. I see a `while` loop that iterates through the packets, and the critical point is the handling of `bytes_remaining`. The original code had a potential vulnerability: if `bytes_remaining` was less than `sizeof(delim)` (which is 4 bytes), it would read 4 bytes into `delim`, even if those 4 bytes went past the valid data in the buffer. Then, it decrements bytes_remaining by 4, creating a negative value for bytes_remaining. The subsequent checks and operations relied on this `bytes_remaining` variable. If a negative value made it past the checks with `total_len` then `memcpy` would then be called with `bytes_remaining` as its length parameter, resulting in an out-of-bounds `memcpy` write or read (depending on what was intended). Let's go through the details of the problem. If `bytes_remaining` is less than `sizeof(delim)`, the code proceeds to read `delim`. It then reduces `bytes_remaining` by `sizeof(delim)`. This could make `bytes_remaining` negative. After the if statement checking `total_len`, the critical flaw is `memcpy(pkts[i].skb->data, read_ptr, bytes_remaining);`. If `bytes_remaining` is negative, `memcpy` would try to copy a large number of bytes (due to the underflow and implicit cast) or perform an out-of-bounds read and write, potentially leading to a crash or security vulnerability. I thought about the initialization of `from_chip_buffer`. The buffer is allocated with `kzalloc`, which should zero-initialize it. However, the data read into the buffer isn't zeroed at each read. If the read function only transfers `bytes_remaining` bytes, that leaves uninitialized memory in the buffer. If the code tries to read beyond the end of the data, it might read stale or uninitialized data. The patch seems to address this by adding a check: `if (bytes_remaining < (int)sizeof(delim)) break;`. That's a good thing! The original code was only checking `bytes_remaining > 0`, but the added check forces an early exit from the loop if there aren't enough bytes to read a complete delimiter, which is the key to preventing the out-of-bounds access. Now, the crucial question: does this patch introduce any *new* risks related to uninitialized memory? No, it doesn't. This patch is tightening a bound check by adding the extra clause. It *prevents* the possibility of `bytes_remaining` going negative, so it *prevents* accessing past the allocated buffer. I carefully reviewed the criteria for setting `NeedsKMSAN=true`, which revolve around the introduction or modification of code that could lead to information leaks or the use of uninitialized memory. This patch doesn't introduce any new structures, it doesn't leak uninitialized data to user space, it doesn't depend on uninitialized variables, and it doesn't create new risks related to uninitialized data. It's solely focused on strengthening the existing bounds check. I confirmed this by checking the code *after* the `while` loop. The control flow after the loop will still exit the function safely with appropriate error codes, so there's no way to leak uninitialized data. |
| 122/3 | 2026/09/21 14:33 | tool | grepper |
0mArgs:{
"Expression": "mm81x_yaps_hw_read_pkts",
"PathPrefix": "drivers/net/wireless/morsemicro/"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/yaps_hw.c=423=static int mm81x_read_pkts_h_bytes_remaining(struct mm81x_yaps *yaps)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-438-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:439:static int mm81x_yaps_hw_read_pkts(struct mm81x_yaps *yaps,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-440-\t\t\t\t struct mm81x_yaps_pkt *pkts,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c=644=static const struct mm81x_yaps_ops mm81x_yaps_hw_ops = {\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-645-\t.write_pkts = mm81x_yaps_hw_write_pkts,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:646:\t.read_pkts = mm81x_yaps_hw_read_pkts,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-647-\t.update_status = mm81x_yaps_hw_update_status,\n"
} |
| 123/3 | 2026/09/21 14:33 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 19169 output: 34 thoughts: 14 Thoughts: Here's my attempt at summarizing the thought process, tailored for an expert audience: **Tracing the Execution Path of `.read_pkts`** Okay, so I need to understand the execution flow of `.read_pkts`. The obvious first step is to perform a code search to identify all instances where this method is invoked. I'll need to use my usual tools and strategies to ensure I capture all calls, including potentially indirect calls or those within conditional blocks. I'll be looking for both direct calls (e.g., `object.read_pkts()`) and any variations due to dynamic dispatch or method indirection, if applicable in this language/environment. The goal is to build a complete call graph, starting from the potential entry points. From there, I'll analyze the context around each call to understand the intended purpose and any relevant dependencies. This is where I'll look at the specific arguments passed, the returned value (if any), and the state of the surrounding objects. This should give me a solid map for how `.read_pkts` is *supposed* to behave, and any obvious areas where issues might come up. |
| 124/3 | 2026/09/21 14:33 | tool | grepper |
0mArgs:{
"Expression": "read_pkts",
"PathPrefix": "drivers/net/wireless/morsemicro/"
}Results: {
"Output": "drivers/net/wireless/morsemicro/mm81x/yaps.c=51=static int mm81x_yaps_write_pkts(struct mm81x_yaps *yaps,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-57-\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:58:static int mm81x_yaps_read_pkts(struct mm81x_yaps *yaps,\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-59-\t\t\t\tstruct mm81x_yaps_pkt *pkts, int num_pkts_max,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-61-{\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:62:\treturn yaps-\u003eops-\u003eread_pkts(yaps, pkts, num_pkts_max,\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-63-\t\t\t\t num_pkts_received);\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c=386=static bool mm81x_yaps_rx_handler(struct mm81x_yaps *yaps)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-395-\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:396:\tret = mm81x_yaps_read_pkts(yaps, yaps-\u003ehw.from_chip_pkts,\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-397-\t\t\t\t MAX_PKTS_PER_RX_TXN, \u0026num_pks_received);\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-398-\tif (ret \u0026\u0026 ret != -EAGAIN) {\ndrivers/net/wireless/morsemicro/mm81x/yaps.c:399:\t\tdev_err(yaps-\u003emors-\u003edev, \"YAPS read_pkts fail: %d\", ret);\ndrivers/net/wireless/morsemicro/mm81x/yaps.c-400-\t\tgoto exit;\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.h=59=struct mm81x_yaps_ops {\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps.h-61-\t\t\t int num_pkts, int *num_pkts_sent);\ndrivers/net/wireless/morsemicro/mm81x/yaps.h:62:\tint (*read_pkts)(struct mm81x_yaps *yaps, struct mm81x_yaps_pkt *pkts,\ndrivers/net/wireless/morsemicro/mm81x/yaps.h-63-\t\t\t int num_pkts_max, int *num_pkts_received);\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c=308=static int mm81x_yaps_hw_write_pkts(struct mm81x_yaps *yaps,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-400-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:401:static bool mm81x_read_pkts_h_is_valid_delim(u32 delim)\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-402-{\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-422-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:423:static int mm81x_read_pkts_h_bytes_remaining(struct mm81x_yaps *yaps)\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-424-{\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-438-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:439:static int mm81x_yaps_hw_read_pkts(struct mm81x_yaps *yaps,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-440-\t\t\t\t struct mm81x_yaps_pkt *pkts,\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-448-\tchar *read_ptr = from_chip_buffer_aligned;\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:449:\tint bytes_remaining = mm81x_read_pkts_h_bytes_remaining(yaps);\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-450-\tbool again = false;\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-499-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:500:\t\tif (!mm81x_read_pkts_h_is_valid_delim(delim)) {\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-501-\t\t\t/*\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c=566=static int mm81x_yaps_hw_update_status(struct mm81x_yaps *yaps)\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-635-\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:636:\tif (mm81x_read_pkts_h_bytes_remaining(yaps))\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-637-\t\tset_bit(MM81X_HIF_EVT_RX_PEND, \u0026yaps-\u003emors-\u003ehif.event_flags);\n--\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c=644=static const struct mm81x_yaps_ops mm81x_yaps_hw_ops = {\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-645-\t.write_pkts = mm81x_yaps_hw_write_pkts,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c:646:\t.read_pkts = mm81x_yaps_hw_read_pkts,\ndrivers/net/wireless/morsemicro/mm81x/yaps_hw.c-647-\t.update_status = mm81x_yaps_hw_update_status,\n"
} |
| 125/3 | 2026/09/21 14:33 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 21275 output: 47 thoughts: 77 Thoughts: Here's my thinking process: **Diving into the YAPS RX Handler** Okay, so I need to understand what's happening with `mm81x_yaps_rx_handler`. Right, that's in the `yaps.c` file within the `morsemicro` section of the wireless drivers. Good, I know where that is. Now, to get a clear picture of its behavior, let's zero in on lines 385 through 430 in `drivers/net/wireless/morsemicro/mm81x/yaps.c`. That should give me a specific chunk of the function to analyze, rather than the entire file. Hopefully, this section contains a key part of the logic that deals with receiving data from the YAPS (Yet Another Packet System) interface. I'm expecting this to handle the packet processing, potential error checking, and data buffering, or the subsequent handing off to a higher layer. Let's see what the code reveals. |
| 126/3 | 2026/09/21 14:33 | tool | read-file |
0mArgs:{
"File": "drivers/net/wireless/morsemicro/mm81x/yaps.c",
"FirstLine": 385,
"LineCount": 45
}Results: {
"Contents": " 385:\t/* Returns true if there are populated RX pages left in the device */\n 386:\tstatic bool mm81x_yaps_rx_handler(struct mm81x_yaps *yaps)\n 387:\t{\n 388:\t\tint ret = 0;\n 389:\t\tint i;\n 390:\t\tint num_pks_received;\n 391:\t\n 392:\t\tret = mm81x_yaps_update_status(yaps);\n 393:\t\tif (ret)\n 394:\t\t\tgoto exit;\n 395:\t\n 396:\t\tret = mm81x_yaps_read_pkts(yaps, yaps-\u003ehw.from_chip_pkts,\n 397:\t\t\t\t\t MAX_PKTS_PER_RX_TXN, \u0026num_pks_received);\n 398:\t\tif (ret \u0026\u0026 ret != -EAGAIN) {\n 399:\t\t\tdev_err(yaps-\u003emors-\u003edev, \"YAPS read_pkts fail: %d\", ret);\n 400:\t\t\tgoto exit;\n 401:\t\t}\n 402:\t\n 403:\t\tfor (i = 0; i \u003c num_pks_received; ++i) {\n 404:\t\t\tmm81x_yaps_read_pkt(yaps, yaps-\u003ehw.from_chip_pkts[i].skb);\n 405:\t\t\tyaps-\u003ehw.from_chip_pkts[i].skb = NULL;\n 406:\t\t}\n 407:\t\n 408:\texit:\n 409:\t\tif (ret == -ENOMEM || ret == -EAGAIN)\n 410:\t\t\treturn true;\n 411:\t\telse\n 412:\t\t\treturn false;\n 413:\t}\n 414:\t\n 415:\tvoid mm81x_yaps_stale_tx_work(struct work_struct *work)\n 416:\t{\n 417:\t\tint i;\n 418:\t\tint flushed = 0;\n 419:\t\tstruct mm81x *mors = container_of(work, struct mm81x, tx_stale_work);\n 420:\t\tstruct mm81x_yaps *yaps;\n 421:\t\n 422:\t\tyaps = \u0026mors-\u003ehif.u.yaps;\n 423:\t\tflushed += mm81x_skbq_check_for_stale_tx(mors, \u0026yaps-\u003ebeacon_q);\n 424:\t\tflushed += mm81x_skbq_check_for_stale_tx(mors, \u0026yaps-\u003emgmt_q);\n 425:\t\n 426:\t\tfor (i = 0; i \u003c ARRAY_SIZE(yaps-\u003edata_tx_qs); i++)\n 427:\t\t\tflushed += mm81x_skbq_check_for_stale_tx(mors,\n 428:\t\t\t\t\t\t\t\t \u0026yaps-\u003edata_tx_qs[i]);\n 429:\t\n"
} |
| 127/3 | 2026/09/21 14:33 | llm | kmsan-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 22425 output: 198 thoughts: 527 Thoughts: **KMSAN Assessment: No Need Here** Okay, so I've examined this patch, specifically the fix for `mm81x_yaps_hw_read_pkts`. My analysis is straightforward, and frankly, quite reassuring. The key issue was an early exit from the packet read function. Before the patch, if the remaining bytes in the buffer (`bytes_remaining`) were less than the size of the delimiter (`delim`, which is 4 bytes), the code would attempt to read the delimiter anyway. This could lead to an out-of-bounds read from the hardware buffer, and consequently, `bytes_remaining` would have an integer underflow and be a massive negative number passed to `memcpy()`. That's a classic bounds check violation. The patch itself resolves this by simply adding a check to prevent that out-of-bounds access. The existing functionality handles packets read successfully up until the point of failure (stored in `*num_pkts_received`), meaning that no uninitialized memory is ever read or written. The remaining, incomplete data is just discarded – no harm, no foul. Furthermore, and importantly, there is no uninitialized memory introduced, no uninitialized values being passed to userspace. Now, considering KMSAN's role – identifying uses of uninitialized memory – it’s clear this isn't relevant here. KASAN, with its focus on bounds issues, handles the core problem this patch addresses. KASAN and UBSAN would flag those out-of-bounds reads and the potential negative values passed to `memcpy()`, respectively, making KMSAN overkill. I've confirmed my understanding, and the architecture (amd64) is as expected. I'm confident there's no need for a KMSAN fuzzing session here. This is a KASAN issue. The patch is clean and correct. `set-results`. |
| 128/3 | 2026/09/21 14:33 | tool | set-results |
0mArgs:{
"KMSANReasoning": "The patch adds a bounds check in mm81x_yaps_hw_read_pkts() ensuring that bytes_remaining \u003e= sizeof(delim) before reading a 32-bit delimiter from read_ptr. Previously, if bytes_remaining was between 1 and 3, reading 4 bytes could perform an out-of-bounds read past the buffer or valid data and underflow bytes_remaining to a negative value, leading to severe out-of-bounds memcpy issues. These types of bugs (out-of-bounds reads/writes and buffer overflows) are directly caught by KASAN. The patch does not introduce or expose uninitialized memory, does not alter uninitialized padding or structures copied to user space, and does not branch on uninitialized variables. Therefore, a dedicated KMSAN fuzzing session is not justified.",
"NeedsKMSAN": false
}Results: {
"KMSANReasoning": "The patch adds a bounds check in mm81x_yaps_hw_read_pkts() ensuring that bytes_remaining \u003e= sizeof(delim) before reading a 32-bit delimiter from read_ptr. Previously, if bytes_remaining was between 1 and 3, reading 4 bytes could perform an out-of-bounds read past the buffer or valid data and underflow bytes_remaining to a negative value, leading to severe out-of-bounds memcpy issues. These types of bugs (out-of-bounds reads/writes and buffer overflows) are directly caught by KASAN. The patch does not introduce or expose uninitialized memory, does not alter uninitialized padding or structures copied to user space, and does not branch on uninitialized variables. Therefore, a dedicated KMSAN fuzzing session is not justified.",
"NeedsKMSAN": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|