| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/10/28 01:28 | flow | patch-triage |
27mArgs:null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"KMSANReasoning": "",
"NeedsKMSAN": false,
"Reasoning": "The patch modifies `mhi_wwan_ctrl_dtr_rts` and `mhi_wwan_ctrl_stop` in `drivers/net/wwan/mhi_wwan_ctrl.c`. This is an MHI (Modem Host Interface) driver for Qualcomm-based PCIe modems (such as SDX24/SDX55/SDX65). It requires physical Qualcomm PCIe modem hardware and cannot be emulated or probed in standard virtualized fuzzing environments (QEMU/GCE), making the modified code structurally unreachable.",
"WorthFuzzing": false
} |
| 1/1 | 2026/10/28 01:28 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 66acb988918c4397df33a90c14849bdc246f3dcb\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Wed Oct 28 01:28:13 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/wwan/mhi_wwan_ctrl.c b/drivers/net/wwan/mhi_wwan_ctrl.c\nindex e3c20758895657..7723199278671f 100644\n--- a/drivers/net/wwan/mhi_wwan_ctrl.c\n+++ b/drivers/net/wwan/mhi_wwan_ctrl.c\n@@ -209,9 +209,17 @@ static void mhi_wwan_ctrl_dtr_work(struct work_struct *work)\n static void mhi_wwan_ctrl_dtr_rts(struct wwan_port *port, unsigned int mdmbits)\n {\n \tstruct mhi_wwan_dev *mhiwwan = wwan_port_get_drvdata(port);\n+\tbool drop = (READ_ONCE(mhiwwan-\u003edtr_mdmbits) \u0026 TIOCM_DTR) \u0026\u0026\n+\t\t !(mdmbits \u0026 TIOCM_DTR);\n \n \tWRITE_ONCE(mhiwwan-\u003edtr_mdmbits, mdmbits);\n \tschedule_delayed_work(\u0026mhiwwan-\u003edtr_work, 0);\n+\n+\t/* A DTR drop matters on its own, e.g. to hang up a modem set to AT\u0026D2,\n+\t * so send it now rather than let a following raise coalesce it away\n+\t */\n+\tif (drop)\n+\t\tflush_delayed_work(\u0026mhiwwan-\u003edtr_work);\n }\n \n static int mhi_wwan_ctrl_start(struct wwan_port *port)\n@@ -246,6 +254,9 @@ static void mhi_wwan_ctrl_stop(struct wwan_port *port)\n \n \tcancel_work_sync(\u0026mhiwwan-\u003erx_refill);\n \n+\t/* Send any pending DTR/RTS state before the channel stops */\n+\tflush_delayed_work(\u0026mhiwwan-\u003edtr_work);\n+\n \tmhi_unprepare_from_transfer(mhiwwan-\u003emhi_dev);\n }\n \n"
} |
| 2/1 | 2026/10/28 01:28 | agent | patch-evaluator |
27mModel:core Args: null Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies `mhi_wwan_ctrl_dtr_rts` and `mhi_wwan_ctrl_stop` in `drivers/net/wwan/mhi_wwan_ctrl.c`. This is an MHI (Modem Host Interface) driver for Qualcomm-based PCIe modems (such as SDX24/SDX55/SDX65). It requires physical Qualcomm PCIe modem hardware and cannot be emulated or probed in standard virtualized fuzzing environments (QEMU/GCE), making the modified code structurally unreachable.",
"WorthFuzzing": false
}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 66acb988918c4397df33a90c14849bdc246f3dcb
Author: syz-cluster <triage@syzkaller.com>
Date: Wed Oct 28 01:28:13 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/wwan/mhi_wwan_ctrl.c b/drivers/net/wwan/mhi_wwan_ctrl.c
index e3c20758895657..7723199278671f 100644
--- a/drivers/net/wwan/mhi_wwan_ctrl.c
+++ b/drivers/net/wwan/mhi_wwan_ctrl.c
@@ -209,9 +209,17 @@ static void mhi_wwan_ctrl_dtr_work(struct work_struct *work)
static void mhi_wwan_ctrl_dtr_rts(struct wwan_port *port, unsigned int mdmbits)
{
struct mhi_wwan_dev *mhiwwan = wwan_port_get_drvdata(port);
+ bool drop = (READ_ONCE(mhiwwan->dtr_mdmbits) & TIOCM_DTR) &&
+ !(mdmbits & TIOCM_DTR);
WRITE_ONCE(mhiwwan->dtr_mdmbits, mdmbits);
schedule_delayed_work(&mhiwwan->dtr_work, 0);
+
+ /* A DTR drop matters on its own, e.g. to hang up a modem set to AT&D2,
+ * so send it now rather than let a following raise coalesce it away
+ */
+ if (drop)
+ flush_delayed_work(&mhiwwan->dtr_work);
}
static int mhi_wwan_ctrl_start(struct wwan_port *port)
@@ -246,6 +254,9 @@ static void mhi_wwan_ctrl_stop(struct wwan_port *port)
cancel_work_sync(&mhiwwan->rx_refill);
+ /* Send any pending DTR/RTS state before the channel stops */
+ flush_delayed_work(&mhiwwan->dtr_work);
+
mhi_unprepare_from_transfer(mhiwwan->mhi_dev);
}
|
| 3/2 | 2026/10/28 01:28 | llm | patch-evaluator |
3mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 3343 output: 34 thoughts: 113 Thoughts: Okay, let's get down to brass tacks. **Analyzing this Kernel Patch** Right, so the patch I'm looking at touches `drivers/net/wwan/mhi_wwan_ctrl.c`. My first instinct is to dive into that file and get the lay of the land. I need to understand what this driver *does*. What hardware is it connected to? Is it a WWAN interface specifically, and if so, what underlying technology? Is it a common or niche piece of equipment? More importantly, is it likely to be exposed in standard fuzzing setups? I need to know if I can reliably test this thing in QEMU or even a cloud environment like GCE without needing some esoteric hardware. I want to see how readily I can exercise this code. Therefore, I will go through this driver and start with the Kconfig and determine how it is registered and bound to its associated device(s). |
| 4/2 | 2026/10/28 01:31 | tool | grepper |
0mArgs:{
"Expression": "mhi_wwan_ctrl",
"PathPrefixes": [
"drivers/net/wwan"
]
}Results: {
"Output": "drivers/net/wwan/Kconfig=40=config MHI_WWAN_CTRL\n--\ndrivers/net/wwan/Kconfig-50-\t To compile this driver as a module, choose M here: the module will be\ndrivers/net/wwan/Kconfig:51:\t called mhi_wwan_ctrl.\ndrivers/net/wwan/Kconfig-52-\n--\ndrivers/net/wwan/Makefile=9=obj-$(CONFIG_WWAN_HWSIM) += wwan_hwsim.o\ndrivers/net/wwan/Makefile-10-\ndrivers/net/wwan/Makefile:11:obj-$(CONFIG_MHI_WWAN_CTRL) += mhi_wwan_ctrl.o\ndrivers/net/wwan/Makefile-12-obj-$(CONFIG_MHI_WWAN_MBIM) += mhi_wwan_mbim.o\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c=108=static void __mhi_skb_destructor(struct sk_buff *skb)\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-113-\ndrivers/net/wwan/mhi_wwan_ctrl.c:114:static void mhi_wwan_ctrl_refill_work(struct work_struct *work)\ndrivers/net/wwan/mhi_wwan_ctrl.c-115-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-143-/* Signal the modem's DTR/RTS lines over its own controller's IP_CTRL channel */\ndrivers/net/wwan/mhi_wwan_ctrl.c:144:static int mhi_wwan_ctrl_send_dtr(struct mhi_wwan_dev *mhiwwan, unsigned int mdmbits)\ndrivers/net/wwan/mhi_wwan_ctrl.c-145-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-193- */\ndrivers/net/wwan/mhi_wwan_ctrl.c:194:static void mhi_wwan_ctrl_dtr_work(struct work_struct *work)\ndrivers/net/wwan/mhi_wwan_ctrl.c-195-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-199-\ndrivers/net/wwan/mhi_wwan_ctrl.c:200:\tret = mhi_wwan_ctrl_send_dtr(mhiwwan, READ_ONCE(mhiwwan-\u003edtr_mdmbits));\ndrivers/net/wwan/mhi_wwan_ctrl.c-201-\tif (ret == -EAGAIN || ret == -ENOMEM)\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-208-\ndrivers/net/wwan/mhi_wwan_ctrl.c:209:static void mhi_wwan_ctrl_dtr_rts(struct wwan_port *port, unsigned int mdmbits)\ndrivers/net/wwan/mhi_wwan_ctrl.c-210-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-224-\ndrivers/net/wwan/mhi_wwan_ctrl.c:225:static int mhi_wwan_ctrl_start(struct wwan_port *port)\ndrivers/net/wwan/mhi_wwan_ctrl.c-226-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-240-\t\tset_bit(MHI_WWAN_RX_REFILL, \u0026mhiwwan-\u003eflags);\ndrivers/net/wwan/mhi_wwan_ctrl.c:241:\t\tmhi_wwan_ctrl_refill_work(\u0026mhiwwan-\u003erx_refill);\ndrivers/net/wwan/mhi_wwan_ctrl.c-242-\t}\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-246-\ndrivers/net/wwan/mhi_wwan_ctrl.c:247:static void mhi_wwan_ctrl_stop(struct wwan_port *port)\ndrivers/net/wwan/mhi_wwan_ctrl.c-248-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-262-\ndrivers/net/wwan/mhi_wwan_ctrl.c:263:static int mhi_wwan_ctrl_tx(struct wwan_port *port, struct sk_buff *skb)\ndrivers/net/wwan/mhi_wwan_ctrl.c-264-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c=284=static const struct wwan_port_ops wwan_pops = {\ndrivers/net/wwan/mhi_wwan_ctrl.c:285:\t.start = mhi_wwan_ctrl_start,\ndrivers/net/wwan/mhi_wwan_ctrl.c:286:\t.stop = mhi_wwan_ctrl_stop,\ndrivers/net/wwan/mhi_wwan_ctrl.c:287:\t.tx = mhi_wwan_ctrl_tx,\ndrivers/net/wwan/mhi_wwan_ctrl.c:288:\t.dtr_rts = mhi_wwan_ctrl_dtr_rts,\ndrivers/net/wwan/mhi_wwan_ctrl.c-289-};\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c=311=static void mhi_dl_xfer_cb(struct mhi_device *mhi_dev,\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-335-\ndrivers/net/wwan/mhi_wwan_ctrl.c:336:static int mhi_wwan_ctrl_probe(struct mhi_device *mhi_dev,\ndrivers/net/wwan/mhi_wwan_ctrl.c-337-\t\t\t const struct mhi_device_id *id)\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-348-\tmhiwwan-\u003emtu = MHI_WWAN_MAX_MTU;\ndrivers/net/wwan/mhi_wwan_ctrl.c:349:\tINIT_WORK(\u0026mhiwwan-\u003erx_refill, mhi_wwan_ctrl_refill_work);\ndrivers/net/wwan/mhi_wwan_ctrl.c:350:\tINIT_DELAYED_WORK(\u0026mhiwwan-\u003edtr_work, mhi_wwan_ctrl_dtr_work);\ndrivers/net/wwan/mhi_wwan_ctrl.c-351-\tspin_lock_init(\u0026mhiwwan-\u003etx_lock);\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-373-\ndrivers/net/wwan/mhi_wwan_ctrl.c:374:static void mhi_wwan_ctrl_remove(struct mhi_device *mhi_dev)\ndrivers/net/wwan/mhi_wwan_ctrl.c-375-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c=474=static void mhi_wwan_dtr_remove(struct mhi_device *mhi_dev)\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-490-\ndrivers/net/wwan/mhi_wwan_ctrl.c:491:static const struct mhi_device_id mhi_wwan_ctrl_match_table[] = {\ndrivers/net/wwan/mhi_wwan_ctrl.c-492-\t{ .chan = \"DUN\", .driver_data = WWAN_PORT_AT },\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-500-};\ndrivers/net/wwan/mhi_wwan_ctrl.c:501:MODULE_DEVICE_TABLE(mhi, mhi_wwan_ctrl_match_table);\ndrivers/net/wwan/mhi_wwan_ctrl.c-502-\ndrivers/net/wwan/mhi_wwan_ctrl.c:503:static struct mhi_driver mhi_wwan_ctrl_driver = {\ndrivers/net/wwan/mhi_wwan_ctrl.c:504:\t.id_table = mhi_wwan_ctrl_match_table,\ndrivers/net/wwan/mhi_wwan_ctrl.c:505:\t.remove = mhi_wwan_ctrl_remove,\ndrivers/net/wwan/mhi_wwan_ctrl.c:506:\t.probe = mhi_wwan_ctrl_probe,\ndrivers/net/wwan/mhi_wwan_ctrl.c-507-\t.ul_xfer_cb = mhi_ul_xfer_cb,\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-509-\t.driver = {\ndrivers/net/wwan/mhi_wwan_ctrl.c:510:\t\t.name = \"mhi_wwan_ctrl\",\ndrivers/net/wwan/mhi_wwan_ctrl.c-511-\t},\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c=520=static struct mhi_driver mhi_wwan_dtr_driver = {\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-530-\ndrivers/net/wwan/mhi_wwan_ctrl.c:531:static int __init mhi_wwan_ctrl_init(void)\ndrivers/net/wwan/mhi_wwan_ctrl.c-532-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-538-\ndrivers/net/wwan/mhi_wwan_ctrl.c:539:\tret = mhi_driver_register(\u0026mhi_wwan_ctrl_driver);\ndrivers/net/wwan/mhi_wwan_ctrl.c-540-\tif (ret)\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-544-}\ndrivers/net/wwan/mhi_wwan_ctrl.c:545:module_init(mhi_wwan_ctrl_init);\ndrivers/net/wwan/mhi_wwan_ctrl.c-546-\ndrivers/net/wwan/mhi_wwan_ctrl.c:547:static void __exit mhi_wwan_ctrl_exit(void)\ndrivers/net/wwan/mhi_wwan_ctrl.c-548-{\ndrivers/net/wwan/mhi_wwan_ctrl.c:549:\tmhi_driver_unregister(\u0026mhi_wwan_ctrl_driver);\ndrivers/net/wwan/mhi_wwan_ctrl.c-550-\tmhi_driver_unregister(\u0026mhi_wwan_dtr_driver);\ndrivers/net/wwan/mhi_wwan_ctrl.c-551-}\ndrivers/net/wwan/mhi_wwan_ctrl.c:552:module_exit(mhi_wwan_ctrl_exit);\ndrivers/net/wwan/mhi_wwan_ctrl.c-553-\n"
} |
| 5/2 | 2026/10/28 01:31 | llm | patch-evaluator |
2mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 6568 output: 29 thoughts: 35 Thoughts: Okay, here's my take on those thoughts, framed from my perspective: **Investigating MHI Emulation** Alright, let's dive in. My immediate thought is, "What's the lay of the land with MHI?" I need to understand what this MHI thing *is* – specifically, the Mobile Host Interface. My focus right now is on figuring out if we can emulate or instantiate it, perhaps for testing or development purposes. Is there a viable way to simulate the MHI bus or even individual MHI-based devices? That's the question. To get the answers, the next logical step is to crack open the kernel source code. Time to fire up the search tools and look for the MHI codebase. I need to see what's already there, how it's implemented, and if there are any hooks or existing infrastructure that might help me with emulation. This is where the real work begins. Let's see what the kernel reveals. |
| 6/2 | 2026/10/28 01:33 | tool | grepper |
0mArgs:{
"Expression": "mhi_driver_register",
"PathPrefixes": [
"drivers/"
]
}Results: {
"Output": "drivers/accel/qaic/qaic_debugfs.c=298=int qaic_bootlog_register(void)\ndrivers/accel/qaic/qaic_debugfs.c-299-{\ndrivers/accel/qaic/qaic_debugfs.c:300:\treturn mhi_driver_register(\u0026qaic_bootlog_mhi_driver);\ndrivers/accel/qaic/qaic_debugfs.c-301-}\n--\ndrivers/accel/qaic/qaic_drv.c=776=static int __init qaic_init(void)\n--\ndrivers/accel/qaic/qaic_drv.c-785-\ndrivers/accel/qaic/qaic_drv.c:786:\tret = mhi_driver_register(\u0026qaic_mhi_driver);\ndrivers/accel/qaic/qaic_drv.c-787-\tif (ret) {\ndrivers/accel/qaic/qaic_drv.c:788:\t\tpr_debug(\"qaic: mhi_driver_register failed %d\\n\", ret);\ndrivers/accel/qaic/qaic_drv.c-789-\t\tgoto free_pci;\n--\ndrivers/accel/qaic/qaic_ras.c=633=int qaic_ras_register(void)\ndrivers/accel/qaic/qaic_ras.c-634-{\ndrivers/accel/qaic/qaic_ras.c:635:\treturn mhi_driver_register(\u0026qaic_ras_mhi_driver);\ndrivers/accel/qaic/qaic_ras.c-636-}\n--\ndrivers/accel/qaic/qaic_ssr.c=807=int qaic_ssr_register(void)\ndrivers/accel/qaic/qaic_ssr.c-808-{\ndrivers/accel/qaic/qaic_ssr.c:809:\treturn mhi_driver_register(\u0026qaic_ssr_mhi_driver);\ndrivers/accel/qaic/qaic_ssr.c-810-}\n--\ndrivers/accel/qaic/qaic_timesync.c=388=int qaic_timesync_init(void)\n--\ndrivers/accel/qaic/qaic_timesync.c-391-\ndrivers/accel/qaic/qaic_timesync.c:392:\tret = mhi_driver_register(\u0026qaic_timesync_driver);\ndrivers/accel/qaic/qaic_timesync.c-393-\tif (ret)\ndrivers/accel/qaic/qaic_timesync.c-394-\t\treturn ret;\ndrivers/accel/qaic/qaic_timesync.c:395:\tret = mhi_driver_register(\u0026qaic_boot_timesync_driver);\ndrivers/accel/qaic/qaic_timesync.c-396-\n--\ndrivers/accel/qaic/sahara.c=926=int sahara_register(void)\ndrivers/accel/qaic/sahara.c-927-{\ndrivers/accel/qaic/sahara.c:928:\treturn mhi_driver_register(\u0026sahara_mhi_driver);\ndrivers/accel/qaic/sahara.c-929-}\n--\ndrivers/bus/mhi/host/init.c=1333=static void mhi_remove(struct device *dev)\n--\ndrivers/bus/mhi/host/init.c-1400-\ndrivers/bus/mhi/host/init.c:1401:int __mhi_driver_register(struct mhi_driver *mhi_drv, struct module *owner)\ndrivers/bus/mhi/host/init.c-1402-{\n--\ndrivers/bus/mhi/host/init.c-1412-}\ndrivers/bus/mhi/host/init.c:1413:EXPORT_SYMBOL_GPL(__mhi_driver_register);\ndrivers/bus/mhi/host/init.c-1414-\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c=531=static int __init mhi_wwan_ctrl_init(void)\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-534-\ndrivers/net/wwan/mhi_wwan_ctrl.c:535:\tret = mhi_driver_register(\u0026mhi_wwan_dtr_driver);\ndrivers/net/wwan/mhi_wwan_ctrl.c-536-\tif (ret)\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-538-\ndrivers/net/wwan/mhi_wwan_ctrl.c:539:\tret = mhi_driver_register(\u0026mhi_wwan_ctrl_driver);\ndrivers/net/wwan/mhi_wwan_ctrl.c-540-\tif (ret)\n"
} |
| 7/2 | 2026/10/28 01:33 | llm | patch-evaluator |
1mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 8099 output: 24 thoughts: 46 Thoughts: Okay, let's dive into this. I need to get a handle on the Multiple Host Interface (MHI) controllers that the kernel supports. I'm assuming, and it's a critical assumption, that MHI isn't completely generic. I need to confirm if it's tied to specific hardware implementations, like the Qualcomm MHI PCIe devices I'm familiar with. My first port of call will be the source code, specifically the `drivers/bus/mhi/` directory. That seems like the logical place to start digging for the core MHI driver and potential platform-specific implementations. I'll be looking for clues about the supported controllers and any dependencies on particular hardware architectures or vendors. This should give me a good overview of the state of MHI support in the kernel. |
| 8/2 | 2026/10/28 01:35 | tool | codesearch-dir-index |
0mArgs:{
"Dir": "drivers/bus/mhi"
}Results: {
"Files": [
"common.h"
],
"Subdirs": [
"ep",
"host"
]
} |
| 9/2 | 2026/10/28 01:35 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 8365 output: 26 thoughts: 27 Thoughts: Here's my take on the thought process: **Diving into the MHI Bus Driver Implementation** Okay, time to get my hands dirty. I need to understand the MHI bus driver implementation. My immediate focus is on the core code and the configuration aspects. Therefore, I should start by examining two crucial areas: `drivers/bus/mhi/host/`, where the main driver logic should reside, and then `drivers/bus/mhi/Kconfig`. The Kconfig file should define how the driver is configured and enabled within the kernel build system. This is where I'll find the dependencies and compile-time options I'll need to consider. Understanding these two locations together should provide a solid initial picture of the MHI bus driver and how it's integrated within the wider kernel. |
| 10/2 | 2026/10/28 01:35 | tool | codesearch-dir-index |
0mArgs:{
"Dir": "drivers/bus/mhi/host"
}Results: {
"Files": [
"boot.c",
"debugfs.c",
"init.c",
"internal.h",
"main.c",
"pci_generic.c",
"pm.c",
"trace.h"
],
"Subdirs": null
} |
| 11/2 | 2026/10/28 01:35 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 8651 output: 36 thoughts: 61 Thoughts: Okay, let's dive into this. Here's how I'm thinking about it: **Investigating MHI Host Support** Right, so to understand the scope of MHI host support, I need to start with the source code itself. My initial instinct tells me to look at `drivers/bus/mhi/host/pci_generic.c`. That should provide a good foundational understanding of how the MHI host interacts with the PCI bus, and more importantly, which devices it's designed to interface with. That `pci_generic.c` file is the key to understanding its capabilities. Now, I'm thinking I should cross-reference this with where it *might* be used. Since MHI is often used for cellular modem control, the next logical step is to explore related configurations. Let's see... I'll check `drivers/net/wwan/Kconfig` and zoom in around the `CONFIG_MHI_WWAN_CTRL` option. That's highly likely to give me some insight into which WWAN devices are specifically leveraging the MHI host functionality, and how that support is enabled and disabled. This should give me a more comprehensive picture of the supported devices and configurations. |
| 12/2 | 2026/10/28 01:36 | tool | read-file |
0mArgs:{
"File": "drivers/net/wwan/Kconfig",
"FirstLine": 35,
"LineCount": 40
}Results: {
"Contents": " 35:\t\t framework.\n 36:\t\n 37:\t\t To compile this driver as a module, choose M here: the module will be\n 38:\t\t called wwan_hwsim. If unsure, say N.\n 39:\t\n 40:\tconfig MHI_WWAN_CTRL\n 41:\t\ttristate \"MHI WWAN control driver for Qualcomm-based PCIe modems\"\n 42:\t\tdepends on MHI_BUS\n 43:\t\thelp\n 44:\t\t MHI WWAN CTRL allows QCOM-based PCIe modems to expose different modem\n 45:\t\t control protocols/ports to userspace, including AT, MBIM, QMI, DIAG\n 46:\t\t and FIREHOSE. These protocols can be accessed directly from userspace\n 47:\t\t (e.g. AT commands) or via libraries/tools (e.g. libmbim, libqmi,\n 48:\t\t libqcdm...).\n 49:\t\n 50:\t\t To compile this driver as a module, choose M here: the module will be\n 51:\t\t called mhi_wwan_ctrl.\n 52:\t\n 53:\tconfig MHI_WWAN_MBIM\n 54:\t tristate \"MHI WWAN MBIM network driver for Qualcomm-based PCIe modems\"\n 55:\t depends on MHI_BUS\n 56:\t help\n 57:\t MHI WWAN MBIM is a WWAN network driver for QCOM-based PCIe modems.\n 58:\t It implements MBIM over MHI, for IP data aggregation and muxing.\n 59:\t A default wwan0 network interface is created for MBIM data session\n 60:\t ID 0. Additional links can be created via wwan rtnetlink type.\n 61:\t\n 62:\t To compile this driver as a module, choose M here: the module will be\n 63:\t called mhi_wwan_mbim.\n 64:\t\n 65:\tconfig QCOM_BAM_DMUX\n 66:\t\ttristate \"Qualcomm BAM-DMUX WWAN network driver\"\n 67:\t\tdepends on (DMA_ENGINE \u0026\u0026 PM \u0026\u0026 QCOM_SMEM_STATE) || COMPILE_TEST\n 68:\t\thelp\n 69:\t\t The BAM Data Multiplexer provides access to the network data channels\n 70:\t\t of modems integrated into many older Qualcomm SoCs, e.g. Qualcomm\n 71:\t\t MSM8916 or MSM8974. The connection can be established via QMI/AT from\n 72:\t\t userspace with control ports available through the WWAN subsystem\n 73:\t\t (CONFIG_RPMSG_WWAN_CTRL) or QRTR network sockets (CONFIG_QRTR).\n 74:\t\n"
} |
| 13/2 | 2026/10/28 01:36 | llm | patch-evaluator |
1mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 9716 output: 32 thoughts: 93 Thoughts: **Investigating MHI WWAN Control and Simulation** Okay, so `config MHI_WWAN_CTRL` is defining the "MHI WWAN control driver for Qualcomm-based PCIe modems". Right, that's straightforward. Now, the question that pops into my head is, can we actually *create* or *simulate* MHI devices? Are there any tools for this? I have a feeling there might be, as it's something I've needed in the past. Aha! There it is. `wwan_hwsim: "wwan_hwsim - WWAN simulator"`. *That* looks promising. Now the crucial question: does `wwan_hwsim` utilize `mhi_wwan_ctrl`? If they're tightly integrated, this could be really useful for testing and development. I need to confirm this. Time to dig into the source code – let's check `wwan_hwsim.c`. This is where the magic (or lack thereof) will be revealed. |
| 14/2 | 2026/10/28 01:37 | tool | grepper |
0mArgs:{
"Expression": "wwan_hwsim",
"PathPrefixes": [
"drivers/net/wwan"
]
}Results: {
"Output": "\nFull output is too long, showing 200 out of 390 lines.\nUse more precise expression or PathPrefixes if possible.\n\nNumber of matching lines per file (3 files in total):\ndrivers/net/wwan/Kconfig:1\ndrivers/net/wwan/Makefile:1\ndrivers/net/wwan/wwan_hwsim.c:144\n\ndrivers/net/wwan/Kconfig=31=config WWAN_HWSIM\n--\ndrivers/net/wwan/Kconfig-37-\t To compile this driver as a module, choose M here: the module will be\ndrivers/net/wwan/Kconfig:38:\t called wwan_hwsim. If unsure, say N.\ndrivers/net/wwan/Kconfig-39-\n--\ndrivers/net/wwan/Makefile=7=wwan-objs += wwan_core.o\ndrivers/net/wwan/Makefile-8-\ndrivers/net/wwan/Makefile:9:obj-$(CONFIG_WWAN_HWSIM) += wwan_hwsim.o\ndrivers/net/wwan/Makefile-10-\n--\ndrivers/net/wwan/wwan_hwsim.c-25-\ndrivers/net/wwan/wwan_hwsim.c:26:static int wwan_hwsim_devsnum = 2;\ndrivers/net/wwan/wwan_hwsim.c:27:module_param_named(devices, wwan_hwsim_devsnum, int, 0444);\ndrivers/net/wwan/wwan_hwsim.c-28-MODULE_PARM_DESC(devices, \"Number of simulated devices\");\ndrivers/net/wwan/wwan_hwsim.c-29-\ndrivers/net/wwan/wwan_hwsim.c:30:static const struct class wwan_hwsim_class = {\ndrivers/net/wwan/wwan_hwsim.c:31:\t.name = \"wwan_hwsim\",\ndrivers/net/wwan/wwan_hwsim.c-32-};\ndrivers/net/wwan/wwan_hwsim.c-33-\ndrivers/net/wwan/wwan_hwsim.c:34:static struct dentry *wwan_hwsim_debugfs_topdir;\ndrivers/net/wwan/wwan_hwsim.c:35:static struct dentry *wwan_hwsim_debugfs_devcreate;\ndrivers/net/wwan/wwan_hwsim.c-36-\ndrivers/net/wwan/wwan_hwsim.c:37:static DEFINE_SPINLOCK(wwan_hwsim_devs_lock);\ndrivers/net/wwan/wwan_hwsim.c:38:static LIST_HEAD(wwan_hwsim_devs);\ndrivers/net/wwan/wwan_hwsim.c:39:static unsigned int wwan_hwsim_dev_idx;\ndrivers/net/wwan/wwan_hwsim.c-40-static struct workqueue_struct *wwan_wq;\ndrivers/net/wwan/wwan_hwsim.c-41-\ndrivers/net/wwan/wwan_hwsim.c:42:struct wwan_hwsim_dev {\ndrivers/net/wwan/wwan_hwsim.c-43-\tstruct list_head list;\n--\ndrivers/net/wwan/wwan_hwsim.c-53-\ndrivers/net/wwan/wwan_hwsim.c:54:struct wwan_hwsim_port {\ndrivers/net/wwan/wwan_hwsim.c-55-\tstruct list_head list;\ndrivers/net/wwan/wwan_hwsim.c-56-\tunsigned int id;\ndrivers/net/wwan/wwan_hwsim.c:57:\tstruct wwan_hwsim_dev *dev;\ndrivers/net/wwan/wwan_hwsim.c-58-\tstruct wwan_port *wwan;\n--\ndrivers/net/wwan/wwan_hwsim.c-75-\ndrivers/net/wwan/wwan_hwsim.c:76:static const struct file_operations wwan_hwsim_debugfs_portdestroy_fops;\ndrivers/net/wwan/wwan_hwsim.c:77:static const struct file_operations wwan_hwsim_debugfs_portcreate_fops;\ndrivers/net/wwan/wwan_hwsim.c:78:static const struct file_operations wwan_hwsim_debugfs_devdestroy_fops;\ndrivers/net/wwan/wwan_hwsim.c:79:static void wwan_hwsim_port_del_work(struct work_struct *work);\ndrivers/net/wwan/wwan_hwsim.c:80:static void wwan_hwsim_dev_del_work(struct work_struct *work);\ndrivers/net/wwan/wwan_hwsim.c-81-\ndrivers/net/wwan/wwan_hwsim.c:82:static netdev_tx_t wwan_hwsim_netdev_xmit(struct sk_buff *skb,\ndrivers/net/wwan/wwan_hwsim.c-83-\t\t\t\t\t struct net_device *ndev)\n--\ndrivers/net/wwan/wwan_hwsim.c-90-\ndrivers/net/wwan/wwan_hwsim.c:91:static const struct net_device_ops wwan_hwsim_netdev_ops = {\ndrivers/net/wwan/wwan_hwsim.c:92:\t.ndo_start_xmit = wwan_hwsim_netdev_xmit,\ndrivers/net/wwan/wwan_hwsim.c-93-};\ndrivers/net/wwan/wwan_hwsim.c-94-\ndrivers/net/wwan/wwan_hwsim.c:95:static void wwan_hwsim_netdev_setup(struct net_device *ndev)\ndrivers/net/wwan/wwan_hwsim.c-96-{\ndrivers/net/wwan/wwan_hwsim.c:97:\tndev-\u003enetdev_ops = \u0026wwan_hwsim_netdev_ops;\ndrivers/net/wwan/wwan_hwsim.c-98-\tndev-\u003eneeds_free_netdev = true;\n--\ndrivers/net/wwan/wwan_hwsim.c-107-\ndrivers/net/wwan/wwan_hwsim.c:108:static const struct wwan_ops wwan_hwsim_wwan_rtnl_ops = {\ndrivers/net/wwan/wwan_hwsim.c-109-\t.priv_size = 0,\t\t\t/* No private data */\ndrivers/net/wwan/wwan_hwsim.c:110:\t.setup = wwan_hwsim_netdev_setup,\ndrivers/net/wwan/wwan_hwsim.c-111-};\ndrivers/net/wwan/wwan_hwsim.c-112-\ndrivers/net/wwan/wwan_hwsim.c:113:static int wwan_hwsim_at_emul_start(struct wwan_port *wport)\ndrivers/net/wwan/wwan_hwsim.c-114-{\ndrivers/net/wwan/wwan_hwsim.c:115:\tstruct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);\ndrivers/net/wwan/wwan_hwsim.c-116-\n--\ndrivers/net/wwan/wwan_hwsim.c-121-\ndrivers/net/wwan/wwan_hwsim.c:122:static void wwan_hwsim_at_emul_stop(struct wwan_port *wport)\ndrivers/net/wwan/wwan_hwsim.c-123-{\n--\ndrivers/net/wwan/wwan_hwsim.c-131- */\ndrivers/net/wwan/wwan_hwsim.c:132:static int wwan_hwsim_at_emul_tx(struct wwan_port *wport, struct sk_buff *in)\ndrivers/net/wwan/wwan_hwsim.c-133-{\ndrivers/net/wwan/wwan_hwsim.c:134:\tstruct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);\ndrivers/net/wwan/wwan_hwsim.c-135-\tstruct sk_buff *out;\n--\ndrivers/net/wwan/wwan_hwsim.c-194-\ndrivers/net/wwan/wwan_hwsim.c:195:static const struct wwan_port_ops wwan_hwsim_at_emul_port_ops = {\ndrivers/net/wwan/wwan_hwsim.c:196:\t.start = wwan_hwsim_at_emul_start,\ndrivers/net/wwan/wwan_hwsim.c:197:\t.stop = wwan_hwsim_at_emul_stop,\ndrivers/net/wwan/wwan_hwsim.c:198:\t.tx = wwan_hwsim_at_emul_tx,\ndrivers/net/wwan/wwan_hwsim.c-199-};\n--\ndrivers/net/wwan/wwan_hwsim.c=206=static __printf(2, 3)\ndrivers/net/wwan/wwan_hwsim.c:207:void wwan_hwsim_nmea_skb_push_sentence(struct sk_buff *skb,\ndrivers/net/wwan/wwan_hwsim.c-208-\t\t\t\t const char *fmt, ...)\n--\ndrivers/net/wwan/wwan_hwsim.c-233-\ndrivers/net/wwan/wwan_hwsim.c:234:static void wwan_hwsim_nmea_emul_timer(struct timer_list *t)\ndrivers/net/wwan/wwan_hwsim.c-235-{\n--\ndrivers/net/wwan/wwan_hwsim.c-238-\t\t\t\t\t\t 11, 15, 4559, 0 };\ndrivers/net/wwan/wwan_hwsim.c:239:\tstruct wwan_hwsim_port *port = timer_container_of(port, t, nmea_emul.timer);\ndrivers/net/wwan/wwan_hwsim.c-240-\tstruct sk_buff *skb;\n--\ndrivers/net/wwan/wwan_hwsim.c-250-\ndrivers/net/wwan/wwan_hwsim.c:251:\twwan_hwsim_nmea_skb_push_sentence(skb,\ndrivers/net/wwan/wwan_hwsim.c-252-\t\t\t\t\t \"$GPGGA,%02u%02u%02u.000,%02u%02u.%04u,%c,%03u%02u.%04u,%c,1,7,1.03,176.2,M,55.2,M,,\",\n--\ndrivers/net/wwan/wwan_hwsim.c-258-\ndrivers/net/wwan/wwan_hwsim.c:259:\twwan_hwsim_nmea_skb_push_sentence(skb,\ndrivers/net/wwan/wwan_hwsim.c-260-\t\t\t\t\t \"$GPRMC,%02u%02u%02u.000,A,%02u%02u.%04u,%c,%03u%02u.%04u,%c,0.02,31.66,%02u%02u%02u,,,A\",\n--\ndrivers/net/wwan/wwan_hwsim.c-271-\ndrivers/net/wwan/wwan_hwsim.c:272:static int wwan_hwsim_nmea_emul_start(struct wwan_port *wport)\ndrivers/net/wwan/wwan_hwsim.c-273-{\ndrivers/net/wwan/wwan_hwsim.c:274:\tstruct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);\ndrivers/net/wwan/wwan_hwsim.c-275-\ndrivers/net/wwan/wwan_hwsim.c:276:\ttimer_setup(\u0026port-\u003enmea_emul.timer, wwan_hwsim_nmea_emul_timer, 0);\ndrivers/net/wwan/wwan_hwsim.c:277:\twwan_hwsim_nmea_emul_timer(\u0026port-\u003enmea_emul.timer);\ndrivers/net/wwan/wwan_hwsim.c-278-\n--\ndrivers/net/wwan/wwan_hwsim.c-281-\ndrivers/net/wwan/wwan_hwsim.c:282:static void wwan_hwsim_nmea_emul_stop(struct wwan_port *wport)\ndrivers/net/wwan/wwan_hwsim.c-283-{\ndrivers/net/wwan/wwan_hwsim.c:284:\tstruct wwan_hwsim_port *port = wwan_port_get_drvdata(wport);\ndrivers/net/wwan/wwan_hwsim.c-285-\n--\ndrivers/net/wwan/wwan_hwsim.c-288-\ndrivers/net/wwan/wwan_hwsim.c:289:static int wwan_hwsim_nmea_emul_tx(struct wwan_port *wport, struct sk_buff *in)\ndrivers/net/wwan/wwan_hwsim.c-290-{\n--\ndrivers/net/wwan/wwan_hwsim.c-295-\ndrivers/net/wwan/wwan_hwsim.c:296:static const struct wwan_port_ops wwan_hwsim_nmea_emul_port_ops = {\ndrivers/net/wwan/wwan_hwsim.c:297:\t.start = wwan_hwsim_nmea_emul_start,\ndrivers/net/wwan/wwan_hwsim.c:298:\t.stop = wwan_hwsim_nmea_emul_stop,\ndrivers/net/wwan/wwan_hwsim.c:299:\t.tx = wwan_hwsim_nmea_emul_tx,\ndrivers/net/wwan/wwan_hwsim.c-300-};\n--\ndrivers/net/wwan/wwan_hwsim.c-302-\ndrivers/net/wwan/wwan_hwsim.c:303:static struct wwan_hwsim_port *wwan_hwsim_port_new(struct wwan_hwsim_dev *dev,\ndrivers/net/wwan/wwan_hwsim.c-304-\t\t\t\t\t\t enum wwan_port_type type)\n--\ndrivers/net/wwan/wwan_hwsim.c-306-\tconst struct wwan_port_ops *ops;\ndrivers/net/wwan/wwan_hwsim.c:307:\tstruct wwan_hwsim_port *port;\ndrivers/net/wwan/wwan_hwsim.c-308-\tchar name[0x10];\n--\ndrivers/net/wwan/wwan_hwsim.c-311-\tif (type == WWAN_PORT_AT)\ndrivers/net/wwan/wwan_hwsim.c:312:\t\tops = \u0026wwan_hwsim_at_emul_port_ops;\ndrivers/net/wwan/wwan_hwsim.c-313-#if IS_ENABLED(CONFIG_GNSS)\ndrivers/net/wwan/wwan_hwsim.c-314-\telse if (type == WWAN_PORT_NMEA)\ndrivers/net/wwan/wwan_hwsim.c:315:\t\tops = \u0026wwan_hwsim_nmea_emul_port_ops;\ndrivers/net/wwan/wwan_hwsim.c-316-#endif\n--\ndrivers/net/wwan/wwan_hwsim.c-335-\ndrivers/net/wwan/wwan_hwsim.c:336:\tINIT_WORK(\u0026port-\u003edel_work, wwan_hwsim_port_del_work);\ndrivers/net/wwan/wwan_hwsim.c-337-\n--\ndrivers/net/wwan/wwan_hwsim.c-340-\tdebugfs_create_file(\"destroy\", 0200, port-\u003edebugfs_topdir, port,\ndrivers/net/wwan/wwan_hwsim.c:341:\t\t\t \u0026wwan_hwsim_debugfs_portdestroy_fops);\ndrivers/net/wwan/wwan_hwsim.c-342-\n--\ndrivers/net/wwan/wwan_hwsim.c-350-\ndrivers/net/wwan/wwan_hwsim.c:351:static void wwan_hwsim_port_del(struct wwan_hwsim_port *port)\ndrivers/net/wwan/wwan_hwsim.c-352-{\n--\ndrivers/net/wwan/wwan_hwsim.c-362-\ndrivers/net/wwan/wwan_hwsim.c:363:static void wwan_hwsim_port_del_work(struct work_struct *work)\ndrivers/net/wwan/wwan_hwsim.c-364-{\ndrivers/net/wwan/wwan_hwsim.c:365:\tstruct wwan_hwsim_port *port =\ndrivers/net/wwan/wwan_hwsim.c-366-\t\t\t\tcontainer_of(work, typeof(*port), del_work);\ndrivers/net/wwan/wwan_hwsim.c:367:\tstruct wwan_hwsim_dev *dev = port-\u003edev;\ndrivers/net/wwan/wwan_hwsim.c-368-\n--\ndrivers/net/wwan/wwan_hwsim.c-377-\ndrivers/net/wwan/wwan_hwsim.c:378:\twwan_hwsim_port_del(port);\ndrivers/net/wwan/wwan_hwsim.c-379-}\ndrivers/net/wwan/wwan_hwsim.c-380-\ndrivers/net/wwan/wwan_hwsim.c:381:static void wwan_hwsim_dev_release(struct device *sysdev)\ndrivers/net/wwan/wwan_hwsim.c-382-{\ndrivers/net/wwan/wwan_hwsim.c:383:\tstruct wwan_hwsim_dev *dev = container_of(sysdev, typeof(*dev), dev);\ndrivers/net/wwan/wwan_hwsim.c-384-\n--\ndrivers/net/wwan/wwan_hwsim.c-387-\ndrivers/net/wwan/wwan_hwsim.c:388:static struct wwan_hwsim_dev *wwan_hwsim_dev_new(void)\ndrivers/net/wwan/wwan_hwsim.c-389-{\ndrivers/net/wwan/wwan_hwsim.c:390:\tstruct wwan_hwsim_dev *dev;\ndrivers/net/wwan/wwan_hwsim.c-391-\tint err;\n--\ndrivers/net/wwan/wwan_hwsim.c-396-\ndrivers/net/wwan/wwan_hwsim.c:397:\tspin_lock(\u0026wwan_hwsim_devs_lock);\ndrivers/net/wwan/wwan_hwsim.c:398:\tdev-\u003eid = wwan_hwsim_dev_idx++;\ndrivers/net/wwan/wwan_hwsim.c:399:\tspin_unlock(\u0026wwan_hwsim_devs_lock);\ndrivers/net/wwan/wwan_hwsim.c-400-\ndrivers/net/wwan/wwan_hwsim.c:401:\tdev-\u003edev.release = wwan_hwsim_dev_release;\ndrivers/net/wwan/wwan_hwsim.c:402:\tdev-\u003edev.class = \u0026wwan_hwsim_class;\ndrivers/net/wwan/wwan_hwsim.c-403-\tdev_set_name(\u0026dev-\u003edev, \"hwsim%u\", dev-\u003eid);\n--\ndrivers/net/wwan/wwan_hwsim.c-411-\ndrivers/net/wwan/wwan_hwsim.c:412:\tINIT_WORK(\u0026dev-\u003edel_work, wwan_hwsim_dev_del_work);\ndrivers/net/wwan/wwan_hwsim.c-413-\ndrivers/net/wwan/wwan_hwsim.c:414:\terr = wwan_register_ops(\u0026dev-\u003edev, \u0026wwan_hwsim_wwan_rtnl_ops, dev, 1);\ndrivers/net/wwan/wwan_hwsim.c-415-\tif (err)\n--\ndrivers/net/wwan/wwan_hwsim.c-418-\tdev-\u003edebugfs_topdir = debugfs_create_dir(dev_name(\u0026dev-\u003edev),\ndrivers/net/wwan/wwan_hwsim.c:419:\t\t\t\t\t\t wwan_hwsim_debugfs_topdir);\ndrivers/net/wwan/wwan_hwsim.c-420-\tdebugfs_create_file(\"destroy\", 0200, dev-\u003edebugfs_topdir, dev,\n\n"
} |
| 15/2 | 2026/10/28 01:37 | llm | patch-evaluator |
2mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 15509 output: 29 thoughts: 183 Thoughts: **Analyzing WWAN Simulation and MHI Control** Alright, let's break this down. It seems `wwan_hwsim` takes a direct approach, simulating WWAN ports using `wwan_register_ops` and `wwan_create_port`, leveraging those specific emulation operation structures – `wwan_hwsim_at_emul_port_ops` and `wwan_hwsim_nmea_emul_port_ops`. Key takeaway: it bypasses `mhi_wwan_ctrl` entirely for its simulated ports. Good to know. Now, I need to understand what role `mhi_wwan_ctrl` *actually* plays. My initial understanding is that it's acting as a Mobile Host Interface (MHI) driver, specifically linked to `mhi_driver` structs for both control and data transfer (`mhi_wwan_ctrl_driver` and `mhi_wwan_dtr_driver`). The next logical question: how are these MHI devices getting instantiated? I need to trace the device creation process, digging into calls to `mhi_device_create`, `mhi_register_controller`, or any similar MHI registration or device creation functions within the kernel. This should reveal the initialization pathway and clarify the relationship between `wwan_hwsim` and MHI in a WWAN context. |
| 16/2 | 2026/10/28 01:40 | tool | grepper |
0mArgs:{
"Expression": "mhi_register_controller",
"PathPrefixes": [
"drivers/"
]
}Results: {
"Output": "drivers/accel/qaic/mhi_controller.c=800=static int mhi_reset_and_async_power_up(struct mhi_controller *mhi_cntrl)\n--\ndrivers/accel/qaic/mhi_controller.c-826-\ndrivers/accel/qaic/mhi_controller.c:827:struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, void __iomem *mhi_bar,\ndrivers/accel/qaic/mhi_controller.c-828-\t\t\t\t\t\t int mhi_irq, bool shared_msi, int family)\n--\ndrivers/accel/qaic/mhi_controller.c-875-\tmhi_config.timeout_ms = mhi_timeout_ms;\ndrivers/accel/qaic/mhi_controller.c:876:\tret = mhi_register_controller(mhi_cntrl, \u0026mhi_config);\ndrivers/accel/qaic/mhi_controller.c-877-\tif (ret) {\ndrivers/accel/qaic/mhi_controller.c:878:\t\tpci_err(pci_dev, \"mhi_register_controller failed %d\\n\", ret);\ndrivers/accel/qaic/mhi_controller.c-879-\t\treturn ERR_PTR(ret);\n--\ndrivers/accel/qaic/mhi_controller.h-8-\ndrivers/accel/qaic/mhi_controller.h:9:struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, void __iomem *mhi_bar,\ndrivers/accel/qaic/mhi_controller.h-10-\t\t\t\t\t\t int mhi_irq, bool shared_msi, int family);\n--\ndrivers/accel/qaic/qaic_drv.c=570=static int qaic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)\n--\ndrivers/accel/qaic/qaic_drv.c-596-\ndrivers/accel/qaic/qaic_drv.c:597:\tqdev-\u003emhi_cntrl = qaic_mhi_register_controller(pdev, qdev-\u003ebar_mhi, mhi_irq,\ndrivers/accel/qaic/qaic_drv.c-598-\t\t\t\t\t\t qdev-\u003esingle_msi, config-\u003efamily);\n--\ndrivers/bus/mhi/host/init.c=881=static int parse_config(struct mhi_controller *mhi_cntrl,\n--\ndrivers/bus/mhi/host/init.c-918-\ndrivers/bus/mhi/host/init.c:919:int mhi_register_controller(struct mhi_controller *mhi_cntrl,\ndrivers/bus/mhi/host/init.c-920-\t\t\t const struct mhi_controller_config *config)\n--\ndrivers/bus/mhi/host/init.c-1058-}\ndrivers/bus/mhi/host/init.c:1059:EXPORT_SYMBOL_GPL(mhi_register_controller);\ndrivers/bus/mhi/host/init.c-1060-\n--\ndrivers/bus/mhi/host/pci_generic.c=1365=static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)\n--\ndrivers/bus/mhi/host/pci_generic.c-1440-\ndrivers/bus/mhi/host/pci_generic.c:1441:\terr = mhi_register_controller(mhi_cntrl, mhi_cntrl_config);\ndrivers/bus/mhi/host/pci_generic.c-1442-\tif (err)\n--\ndrivers/net/wireless/ath/ath11k/mhi.c=335=int ath11k_mhi_register(struct ath11k_pci *ab_pci)\n--\ndrivers/net/wireless/ath/ath11k/mhi.c-409-\tab_pci-\u003emhi_pre_cb = MHI_CB_INVALID;\ndrivers/net/wireless/ath/ath11k/mhi.c:410:\tret = mhi_register_controller(mhi_ctrl, ath11k_mhi_config);\ndrivers/net/wireless/ath/ath11k/mhi.c-411-\tif (ret) {\n--\ndrivers/net/wireless/ath/ath12k/mhi.c=187=int ath12k_mhi_register(struct ath12k_pci *ab_pci)\n--\ndrivers/net/wireless/ath/ath12k/mhi.c-264-\ndrivers/net/wireless/ath/ath12k/mhi.c:265:\tret = mhi_register_controller(mhi_ctrl, ab-\u003ehw_params-\u003emhi_config);\ndrivers/net/wireless/ath/ath12k/mhi.c-266-\tif (ret) {\n"
} |
| 17/2 | 2026/10/28 01:40 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 17322 output: 29 thoughts: 138 Thoughts: Okay, let's break this down. **Analyzing the `mhi_register_controller` Function Calls** Alright, I need to get a clear picture of where `mhi_register_controller` is used. Looking at the call sites, it's pretty diverse, but the common thread seems to be PCIe devices. First, I see it's called within `drivers/bus/mhi/host/pci_generic.c` from the `mhi_pci_probe` function. That’s the workhorse for PCIe MHI devices, like the Qualcomm modems, Foxconn, Quectel, Telit modems, etc. This is the expected and most common use case. Then, interestingly, it's also used in the `drivers/accel/qaic/mhi_controller.c` file. This tells me the Qualcomm Cloud AI 100 PCIe accelerator relies on it. That's good to know, confirming its utility beyond just modems. Next, it's called within the Qualcomm WiFi drivers, `ath11k` and `ath12k` located in `drivers/net/wireless/ath/`. I suspected that these devices would be using the MHI bus, and now this is confirmed. The WiFi drivers make sense; it's another common PCIe application with MHI. Finally, I should check whether it’s used by any platform drivers. I'll need to look a bit deeper to make sure I haven't missed anything specific to a particular system-on-chip or platform. Just want to make sure I have a complete view of how this thing is being used. |
| 18/2 | 2026/10/28 01:40 | tool | grepper |
0mArgs:{
"Expression": "mhi_register_controller",
"PathPrefixes": [
"drivers/"
]
}Results: {
"Output": "drivers/accel/qaic/mhi_controller.c=800=static int mhi_reset_and_async_power_up(struct mhi_controller *mhi_cntrl)\n--\ndrivers/accel/qaic/mhi_controller.c-826-\ndrivers/accel/qaic/mhi_controller.c:827:struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, void __iomem *mhi_bar,\ndrivers/accel/qaic/mhi_controller.c-828-\t\t\t\t\t\t int mhi_irq, bool shared_msi, int family)\n--\ndrivers/accel/qaic/mhi_controller.c-875-\tmhi_config.timeout_ms = mhi_timeout_ms;\ndrivers/accel/qaic/mhi_controller.c:876:\tret = mhi_register_controller(mhi_cntrl, \u0026mhi_config);\ndrivers/accel/qaic/mhi_controller.c-877-\tif (ret) {\ndrivers/accel/qaic/mhi_controller.c:878:\t\tpci_err(pci_dev, \"mhi_register_controller failed %d\\n\", ret);\ndrivers/accel/qaic/mhi_controller.c-879-\t\treturn ERR_PTR(ret);\n--\ndrivers/accel/qaic/mhi_controller.h-8-\ndrivers/accel/qaic/mhi_controller.h:9:struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, void __iomem *mhi_bar,\ndrivers/accel/qaic/mhi_controller.h-10-\t\t\t\t\t\t int mhi_irq, bool shared_msi, int family);\n--\ndrivers/accel/qaic/qaic_drv.c=570=static int qaic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)\n--\ndrivers/accel/qaic/qaic_drv.c-596-\ndrivers/accel/qaic/qaic_drv.c:597:\tqdev-\u003emhi_cntrl = qaic_mhi_register_controller(pdev, qdev-\u003ebar_mhi, mhi_irq,\ndrivers/accel/qaic/qaic_drv.c-598-\t\t\t\t\t\t qdev-\u003esingle_msi, config-\u003efamily);\n--\ndrivers/bus/mhi/host/init.c=881=static int parse_config(struct mhi_controller *mhi_cntrl,\n--\ndrivers/bus/mhi/host/init.c-918-\ndrivers/bus/mhi/host/init.c:919:int mhi_register_controller(struct mhi_controller *mhi_cntrl,\ndrivers/bus/mhi/host/init.c-920-\t\t\t const struct mhi_controller_config *config)\n--\ndrivers/bus/mhi/host/init.c-1058-}\ndrivers/bus/mhi/host/init.c:1059:EXPORT_SYMBOL_GPL(mhi_register_controller);\ndrivers/bus/mhi/host/init.c-1060-\n--\ndrivers/bus/mhi/host/pci_generic.c=1365=static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)\n--\ndrivers/bus/mhi/host/pci_generic.c-1440-\ndrivers/bus/mhi/host/pci_generic.c:1441:\terr = mhi_register_controller(mhi_cntrl, mhi_cntrl_config);\ndrivers/bus/mhi/host/pci_generic.c-1442-\tif (err)\n--\ndrivers/net/wireless/ath/ath11k/mhi.c=335=int ath11k_mhi_register(struct ath11k_pci *ab_pci)\n--\ndrivers/net/wireless/ath/ath11k/mhi.c-409-\tab_pci-\u003emhi_pre_cb = MHI_CB_INVALID;\ndrivers/net/wireless/ath/ath11k/mhi.c:410:\tret = mhi_register_controller(mhi_ctrl, ath11k_mhi_config);\ndrivers/net/wireless/ath/ath11k/mhi.c-411-\tif (ret) {\n--\ndrivers/net/wireless/ath/ath12k/mhi.c=187=int ath12k_mhi_register(struct ath12k_pci *ab_pci)\n--\ndrivers/net/wireless/ath/ath12k/mhi.c-264-\ndrivers/net/wireless/ath/ath12k/mhi.c:265:\tret = mhi_register_controller(mhi_ctrl, ab-\u003ehw_params-\u003emhi_config);\ndrivers/net/wireless/ath/ath12k/mhi.c-266-\tif (ret) {\n"
} |
| 19/2 | 2026/10/28 01:40 | llm | patch-evaluator |
1mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 19152 output: 20 thoughts: 51 Thoughts: Okay, let's dive into this. Here's how I'd approach this task, as if these were my internal thoughts: **Investigating MHI Driver Interactions** Right, let's get down to brass tacks. I need to understand the complete picture of how the MHI (Mobile Host Interface) framework is operating within the kernel. My immediate focus is on potential interactions with `mhi_register_controller` and `mhi_device`. I want to ensure I'm not missing any critical calls or creations. My goal is to fully understand the full picture. First things first, I'll need to broaden my search. I've got to ensure I've covered all the relevant spots where this function is called, or an mhi device is constructed. I'll need to carefully check `drivers/bus/mhi/ep/`, as that seems like a likely candidate given the context. But, I won't limit myself to that directory alone; it's always smart to have a wider search parameter, which I will. My goal here is to establish the complete context, not just to look in the obvious spots. |
| 20/2 | 2026/10/28 01:42 | tool | grepper |
0mArgs:{
"Expression": "mhi_register_controller"
}Results: {
"Output": "Documentation/mhi/topology.rst=20=Below are the roles of the MHI controller driver:\n--\nDocumentation/mhi/topology.rst-24-* Allocates struct mhi_controller and registers with the MHI bus framework\nDocumentation/mhi/topology.rst:25: with channel and event configurations using mhi_register_controller.\nDocumentation/mhi/topology.rst-26-* Initiates power on and shutdown sequence\n--\ndrivers/accel/qaic/mhi_controller.c=800=static int mhi_reset_and_async_power_up(struct mhi_controller *mhi_cntrl)\n--\ndrivers/accel/qaic/mhi_controller.c-826-\ndrivers/accel/qaic/mhi_controller.c:827:struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, void __iomem *mhi_bar,\ndrivers/accel/qaic/mhi_controller.c-828-\t\t\t\t\t\t int mhi_irq, bool shared_msi, int family)\n--\ndrivers/accel/qaic/mhi_controller.c-875-\tmhi_config.timeout_ms = mhi_timeout_ms;\ndrivers/accel/qaic/mhi_controller.c:876:\tret = mhi_register_controller(mhi_cntrl, \u0026mhi_config);\ndrivers/accel/qaic/mhi_controller.c-877-\tif (ret) {\ndrivers/accel/qaic/mhi_controller.c:878:\t\tpci_err(pci_dev, \"mhi_register_controller failed %d\\n\", ret);\ndrivers/accel/qaic/mhi_controller.c-879-\t\treturn ERR_PTR(ret);\n--\ndrivers/accel/qaic/mhi_controller.h-8-\ndrivers/accel/qaic/mhi_controller.h:9:struct mhi_controller *qaic_mhi_register_controller(struct pci_dev *pci_dev, void __iomem *mhi_bar,\ndrivers/accel/qaic/mhi_controller.h-10-\t\t\t\t\t\t int mhi_irq, bool shared_msi, int family);\n--\ndrivers/accel/qaic/qaic_drv.c=570=static int qaic_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)\n--\ndrivers/accel/qaic/qaic_drv.c-596-\ndrivers/accel/qaic/qaic_drv.c:597:\tqdev-\u003emhi_cntrl = qaic_mhi_register_controller(pdev, qdev-\u003ebar_mhi, mhi_irq,\ndrivers/accel/qaic/qaic_drv.c-598-\t\t\t\t\t\t qdev-\u003esingle_msi, config-\u003efamily);\n--\ndrivers/bus/mhi/host/init.c=881=static int parse_config(struct mhi_controller *mhi_cntrl,\n--\ndrivers/bus/mhi/host/init.c-918-\ndrivers/bus/mhi/host/init.c:919:int mhi_register_controller(struct mhi_controller *mhi_cntrl,\ndrivers/bus/mhi/host/init.c-920-\t\t\t const struct mhi_controller_config *config)\n--\ndrivers/bus/mhi/host/init.c-1058-}\ndrivers/bus/mhi/host/init.c:1059:EXPORT_SYMBOL_GPL(mhi_register_controller);\ndrivers/bus/mhi/host/init.c-1060-\n--\ndrivers/bus/mhi/host/pci_generic.c=1365=static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)\n--\ndrivers/bus/mhi/host/pci_generic.c-1440-\ndrivers/bus/mhi/host/pci_generic.c:1441:\terr = mhi_register_controller(mhi_cntrl, mhi_cntrl_config);\ndrivers/bus/mhi/host/pci_generic.c-1442-\tif (err)\n--\ndrivers/net/wireless/ath/ath11k/mhi.c=335=int ath11k_mhi_register(struct ath11k_pci *ab_pci)\n--\ndrivers/net/wireless/ath/ath11k/mhi.c-409-\tab_pci-\u003emhi_pre_cb = MHI_CB_INVALID;\ndrivers/net/wireless/ath/ath11k/mhi.c:410:\tret = mhi_register_controller(mhi_ctrl, ath11k_mhi_config);\ndrivers/net/wireless/ath/ath11k/mhi.c-411-\tif (ret) {\n--\ndrivers/net/wireless/ath/ath12k/mhi.c=187=int ath12k_mhi_register(struct ath12k_pci *ab_pci)\n--\ndrivers/net/wireless/ath/ath12k/mhi.c-264-\ndrivers/net/wireless/ath/ath12k/mhi.c:265:\tret = mhi_register_controller(mhi_ctrl, ab-\u003ehw_params-\u003emhi_config);\ndrivers/net/wireless/ath/ath12k/mhi.c-266-\tif (ret) {\n--\ninclude/linux/mhi.h=294=struct mhi_controller_config {\n--\ninclude/linux/mhi.h-385- * Fields marked as (required) need to be populated by the controller driver\ninclude/linux/mhi.h:386: * before calling mhi_register_controller(). For the fields marked as (optional)\ninclude/linux/mhi.h-387- * they can be populated depending on the usecase.\n--\ninclude/linux/mhi.h=550=void mhi_free_controller(struct mhi_controller *mhi_cntrl);\n--\ninclude/linux/mhi.h-552-/**\ninclude/linux/mhi.h:553: * mhi_register_controller - Register MHI controller\ninclude/linux/mhi.h-554- * @mhi_cntrl: MHI controller to register\n--\ninclude/linux/mhi.h-556- */\ninclude/linux/mhi.h:557:int mhi_register_controller(struct mhi_controller *mhi_cntrl,\ninclude/linux/mhi.h-558-\t\t\tconst struct mhi_controller_config *config);\n"
} |
| 21/2 | 2026/10/28 01:42 | llm | patch-evaluator |
1mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 21175 output: 37 thoughts: 176 Thoughts: **Analyzing the Scope of `mhi_register_controller`** Okay, so I'm taking a look at where `mhi_register_controller` is being used, and it's pretty clear that it's the core function for managing MHI controllers. I'm seeing it's invoked from the Qualcomm Cloud AI 100 PCIe accelerator driver, the generic PCI driver (`pci_generic.c`), and then both ath11k and ath12k wifi drivers. That's a solid spread, covering accelerators, modems and wireless devices, all over PCIe. Hmm, wait a second... `mhi_pci_generic.c`? Where does the `mhi_register_controller` use appear? I thought that was the generic PCI controller. Let me quickly double-check that this function is being used. And what about the PCI IDs that it supports? I should take a look at the `pci_generic.c` file itself. I need to understand what specific hardware is using this function. I have to make sure I am not missing any cases. Let me make sure I understand the scope of this before proceeding with my analysis. |
| 22/2 | 2026/10/28 01:44 | tool | grepper |
0mArgs:{
"Expression": "MODULE_DEVICE_TABLE\\(pci",
"PathPrefixes": [
"drivers/bus/mhi/host"
]
}Results: {
"Output": "drivers/bus/mhi/host/pci_generic.c=952=static const struct pci_device_id mhi_pci_id_table[] = {\n--\ndrivers/bus/mhi/host/pci_generic.c-1086-};\ndrivers/bus/mhi/host/pci_generic.c:1087:MODULE_DEVICE_TABLE(pci, mhi_pci_id_table);\ndrivers/bus/mhi/host/pci_generic.c-1088-\n"
} |
| 23/2 | 2026/10/28 01:44 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 21779 output: 43 thoughts: 36 Thoughts: Okay, let's dive into this. Here's my thought process on what I'm about to do: **Examining the MHI PCI ID Table** Right, I'm going to take a look at the `mhi_pci_id_table` within `drivers/bus/mhi/host/pci_generic.c`. I need to understand what devices this table supports and how it's used to identify MHI (Mobile Host Interface) devices connected via PCI. My assumption is it contains a list of PCI device IDs – vendor and device IDs, probably – that this driver recognizes. I'm expecting to find a list, likely structured as an array, defining which PCI devices are treated as MHI hosts by this generic PCI driver. I'm hoping to see if there are any familiar devices that I work with and look to see if it is used for a broader set of PCI devices or only some. It will probably also contain some specific flags or data related to initialization or probe, maybe even associated function pointers for specific device handling. From there, I can figure out how that driver handles various MHI-related tasks. |
| 24/2 | 2026/10/28 01:44 | tool | read-file |
0mArgs:{
"File": "drivers/bus/mhi/host/pci_generic.c",
"FirstLine": 952,
"LineCount": 50
}Results: {
"Contents": " 952:\tstatic const struct pci_device_id mhi_pci_id_table[] = {\n 953:\t\t{PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0116),\n 954:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_qcom_sa8775p_info },\n 955:\t\t/* Telit FN920C04 (sdx35) */\n 956:\t\t{PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x011a, 0x1c5d, 0x2020),\n 957:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_telit_fn920c04_info },\n 958:\t\t/* Telit FE910C04 (sdx35) */\n 959:\t\t{PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x011a, 0x1c5d, 0x202a),\n 960:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_telit_fe910c04_info },\n 961:\t\t/* Telit FE912C04 (sdx35) */\n 962:\t\t{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x011a, 0x1c5d, 0x2045),\n 963:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_telit_fe912c04_info },\n 964:\t\t{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x011a),\n 965:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_qcom_sdx35_info },\n 966:\t\t{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0304),\n 967:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_qcom_sdx24_info },\n 968:\t\t{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0306, PCI_VENDOR_ID_QCOM, 0x010c),\n 969:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_foxconn_sdx55_info },\n 970:\t\t/* EM919x (sdx55), use the same vid:pid as qcom-sdx55m */\n 971:\t\t{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0306, 0x18d7, 0x0200),\n 972:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_sierra_em919x_info },\n 973:\t\t/* EM929x (sdx65), use the same configuration as EM919x */\n 974:\t\t{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0308, 0x18d7, 0x0301),\n 975:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_sierra_em919x_info },\n 976:\t\t/* Telit FN980 hardware revision v1 */\n 977:\t\t{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0306, 0x1C5D, 0x2000),\n 978:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_telit_fn980_hw_v1_info },\n 979:\t\t{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0306),\n 980:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_qcom_sdx55_info },\n 981:\t\t/* Telit FN990 */\n 982:\t\t{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0308, 0x1c5d, 0x2010),\n 983:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_telit_fn990_info },\n 984:\t\t/* Telit FE990A */\n 985:\t\t{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0308, 0x1c5d, 0x2015),\n 986:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_telit_fe990a_info },\n 987:\t\t/* Foxconn T99W696, all variants */\n 988:\t\t{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0308, PCI_VENDOR_ID_FOXCONN, PCI_ANY_ID),\n 989:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_foxconn_t99w696_info },\n 990:\t\t{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0308),\n 991:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_qcom_sdx65_info },\n 992:\t\t/* Telit FN990B40 (sdx72) */\n 993:\t\t{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0309, 0x1c5d, 0x201a),\n 994:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_telit_fn990b40_info },\n 995:\t\t/* Telit FE990B40 (sdx72) */\n 996:\t\t{ PCI_DEVICE_SUB(PCI_VENDOR_ID_QCOM, 0x0309, 0x1c5d, 0x2025),\n 997:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_telit_fe990b40_info },\n 998:\t\t{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0309),\n 999:\t\t\t.driver_data = (kernel_ulong_t) \u0026mhi_qcom_sdx75_info },\n1000:\t\t/* QDU100, x100-DU */\n1001:\t\t{ PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0601),\n"
} |
| 25/2 | 2026/10/28 01:44 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 23792 output: 27 thoughts: 95 Thoughts: Okay, here's my quick take on what I'm thinking about, given my experience: **MHI Device Landscape: A Quick Survey** Alright, my initial mental inventory has these all pegged as physical PCIe modems. Qualcomm, Foxconn, Sierra, Telit, Quectel, Fibocom – all real hardware, connected via PCIe. But wait a minute… this feels a bit too narrow. I need to take a step back and make sure I'm not missing something fundamental. The real question I need to be asking right now is: *Is there anything… ANYTHING at all… emulating or virtualizing that Mobile Host Interface (MHI) connection?* Maybe I'm starting at the wrong level. Is there even a software construct representing an MHI device, or a virtual controller, anywhere in the kernel? I highly doubt this is the first thing that someone would seek out, however, better to be sure. Time to dive in. I'm going to leverage my kernel search skills immediately. I'll need to check the presence of a virtual endpoint or emulated device. Let's start with a focused search. I'll throw in a bunch of queries, things like "mhi_ep," "mhi_endpoint," and related keywords and see what shows up. I need to make sure I haven't overlooked some kind of development tool, test setup, or even a clever debugging mechanism within the kernel itself. This is the place to be, to quickly eliminate a whole class of possibilities. |
| 26/2 | 2026/10/28 01:45 | tool | grepper |
0mArgs:{
"Expression": "mhi_ep",
"PathPrefixes": [
"drivers/"
]
}Results: {
"Output": "\nFull output is too long, showing 200 out of 1401 lines.\nUse more precise expression or PathPrefixes if possible.\n\nNumber of matching lines per file (7 files in total):\ndrivers/bus/mhi/ep/Makefile:2\ndrivers/bus/mhi/ep/internal.h:59\ndrivers/bus/mhi/ep/main.c:239\ndrivers/bus/mhi/ep/mmio.c:73\ndrivers/bus/mhi/ep/ring.c:31\ndrivers/bus/mhi/ep/sm.c:23\ndrivers/pci/endpoint/functions/pci-epf-mhi.c:56\n\ndrivers/bus/mhi/ep/Makefile:1:obj-$(CONFIG_MHI_BUS_EP) += mhi_ep.o\ndrivers/bus/mhi/ep/Makefile:2:mhi_ep-y := main.o mmio.o ring.o sm.o\n--\ndrivers/bus/mhi/ep/internal.h-13-\ndrivers/bus/mhi/ep/internal.h:14:extern const struct bus_type mhi_ep_bus_type;\ndrivers/bus/mhi/ep/internal.h-15-\n--\ndrivers/bus/mhi/ep/internal.h=94=struct mhi_generic_ctx {\n--\ndrivers/bus/mhi/ep/internal.h-104-\ndrivers/bus/mhi/ep/internal.h:105:enum mhi_ep_ring_type {\ndrivers/bus/mhi/ep/internal.h-106-\tRING_TYPE_CMD,\n--\ndrivers/bus/mhi/ep/internal.h-111-/* Ring element */\ndrivers/bus/mhi/ep/internal.h:112:union mhi_ep_ring_ctx {\ndrivers/bus/mhi/ep/internal.h-113-\tstruct mhi_cmd_ctxt cmd;\n--\ndrivers/bus/mhi/ep/internal.h-118-\ndrivers/bus/mhi/ep/internal.h:119:struct mhi_ep_ring_item {\ndrivers/bus/mhi/ep/internal.h-120-\tstruct list_head node;\ndrivers/bus/mhi/ep/internal.h:121:\tstruct mhi_ep_ring *ring;\ndrivers/bus/mhi/ep/internal.h-122-};\ndrivers/bus/mhi/ep/internal.h-123-\ndrivers/bus/mhi/ep/internal.h:124:struct mhi_ep_ring {\ndrivers/bus/mhi/ep/internal.h:125:\tstruct mhi_ep_cntrl *mhi_cntrl;\ndrivers/bus/mhi/ep/internal.h:126:\tunion mhi_ep_ring_ctx *ring_ctx;\ndrivers/bus/mhi/ep/internal.h-127-\tstruct mhi_ring_element *ring_cache;\ndrivers/bus/mhi/ep/internal.h:128:\tenum mhi_ep_ring_type type;\ndrivers/bus/mhi/ep/internal.h-129-\tstruct delayed_work intmodt_work;\n--\ndrivers/bus/mhi/ep/internal.h-143-\ndrivers/bus/mhi/ep/internal.h:144:struct mhi_ep_cmd {\ndrivers/bus/mhi/ep/internal.h:145:\tstruct mhi_ep_ring ring;\ndrivers/bus/mhi/ep/internal.h-146-};\ndrivers/bus/mhi/ep/internal.h-147-\ndrivers/bus/mhi/ep/internal.h:148:struct mhi_ep_event {\ndrivers/bus/mhi/ep/internal.h:149:\tstruct mhi_ep_ring ring;\ndrivers/bus/mhi/ep/internal.h-150-};\ndrivers/bus/mhi/ep/internal.h-151-\ndrivers/bus/mhi/ep/internal.h:152:struct mhi_ep_state_transition {\ndrivers/bus/mhi/ep/internal.h-153-\tstruct list_head node;\n--\ndrivers/bus/mhi/ep/internal.h-156-\ndrivers/bus/mhi/ep/internal.h:157:struct mhi_ep_chan {\ndrivers/bus/mhi/ep/internal.h-158-\tchar *name;\ndrivers/bus/mhi/ep/internal.h:159:\tstruct mhi_ep_device *mhi_dev;\ndrivers/bus/mhi/ep/internal.h:160:\tstruct mhi_ep_ring ring;\ndrivers/bus/mhi/ep/internal.h-161-\tstruct mutex lock;\ndrivers/bus/mhi/ep/internal.h:162:\tvoid (*xfer_cb)(struct mhi_ep_device *mhi_dev, struct mhi_result *result);\ndrivers/bus/mhi/ep/internal.h-163-\tenum mhi_ch_state state;\n--\ndrivers/bus/mhi/ep/internal.h-173-/* MHI Ring related functions */\ndrivers/bus/mhi/ep/internal.h:174:void mhi_ep_ring_init(struct mhi_ep_ring *ring, enum mhi_ep_ring_type type, u32 id);\ndrivers/bus/mhi/ep/internal.h:175:void mhi_ep_ring_reset(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_ring *ring);\ndrivers/bus/mhi/ep/internal.h:176:int mhi_ep_ring_start(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_ring *ring,\ndrivers/bus/mhi/ep/internal.h:177:\t\t union mhi_ep_ring_ctx *ctx);\ndrivers/bus/mhi/ep/internal.h:178:size_t mhi_ep_ring_addr2offset(struct mhi_ep_ring *ring, u64 ptr);\ndrivers/bus/mhi/ep/internal.h:179:int mhi_ep_ring_add_element(struct mhi_ep_ring *ring, struct mhi_ring_element *element);\ndrivers/bus/mhi/ep/internal.h:180:void mhi_ep_ring_inc_index(struct mhi_ep_ring *ring);\ndrivers/bus/mhi/ep/internal.h:181:int mhi_ep_update_wr_offset(struct mhi_ep_ring *ring);\ndrivers/bus/mhi/ep/internal.h-182-\ndrivers/bus/mhi/ep/internal.h-183-/* MMIO related functions */\ndrivers/bus/mhi/ep/internal.h:184:u32 mhi_ep_mmio_read(struct mhi_ep_cntrl *mhi_cntrl, u32 offset);\ndrivers/bus/mhi/ep/internal.h:185:void mhi_ep_mmio_write(struct mhi_ep_cntrl *mhi_cntrl, u32 offset, u32 val);\ndrivers/bus/mhi/ep/internal.h:186:void mhi_ep_mmio_masked_write(struct mhi_ep_cntrl *mhi_cntrl, u32 offset, u32 mask, u32 val);\ndrivers/bus/mhi/ep/internal.h:187:u32 mhi_ep_mmio_masked_read(struct mhi_ep_cntrl *dev, u32 offset, u32 mask);\ndrivers/bus/mhi/ep/internal.h:188:void mhi_ep_mmio_enable_ctrl_interrupt(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:189:void mhi_ep_mmio_disable_ctrl_interrupt(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:190:void mhi_ep_mmio_enable_cmdb_interrupt(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:191:void mhi_ep_mmio_disable_cmdb_interrupt(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:192:void mhi_ep_mmio_enable_chdb(struct mhi_ep_cntrl *mhi_cntrl, u32 ch_id);\ndrivers/bus/mhi/ep/internal.h:193:void mhi_ep_mmio_disable_chdb(struct mhi_ep_cntrl *mhi_cntrl, u32 ch_id);\ndrivers/bus/mhi/ep/internal.h:194:void mhi_ep_mmio_enable_chdb_interrupts(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:195:bool mhi_ep_mmio_read_chdb_status_interrupts(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:196:void mhi_ep_mmio_mask_interrupts(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:197:void mhi_ep_mmio_get_chc_base(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:198:void mhi_ep_mmio_get_erc_base(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:199:void mhi_ep_mmio_get_crc_base(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:200:u64 mhi_ep_mmio_get_db(struct mhi_ep_ring *ring);\ndrivers/bus/mhi/ep/internal.h:201:void mhi_ep_mmio_set_env(struct mhi_ep_cntrl *mhi_cntrl, u32 value);\ndrivers/bus/mhi/ep/internal.h:202:void mhi_ep_mmio_clear_reset(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:203:void mhi_ep_mmio_reset(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:204:void mhi_ep_mmio_get_mhi_state(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state *state,\ndrivers/bus/mhi/ep/internal.h-205-\t\t\t bool *mhi_reset);\ndrivers/bus/mhi/ep/internal.h:206:void mhi_ep_mmio_init(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:207:void mhi_ep_mmio_update_ner(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h-208-\ndrivers/bus/mhi/ep/internal.h-209-/* MHI EP core functions */\ndrivers/bus/mhi/ep/internal.h:210:int mhi_ep_send_state_change_event(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state state);\ndrivers/bus/mhi/ep/internal.h:211:int mhi_ep_send_ee_event(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_ee_type exec_env);\ndrivers/bus/mhi/ep/internal.h:212:bool mhi_ep_check_mhi_state(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state cur_mhi_state,\ndrivers/bus/mhi/ep/internal.h-213-\t\t\t enum mhi_state mhi_state);\ndrivers/bus/mhi/ep/internal.h:214:int mhi_ep_set_mhi_state(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state mhi_state);\ndrivers/bus/mhi/ep/internal.h:215:int mhi_ep_set_m0_state(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:216:int mhi_ep_set_m3_state(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:217:int mhi_ep_set_ready_state(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:218:void mhi_ep_handle_syserr(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:219:void mhi_ep_resume_channels(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h:220:void mhi_ep_suspend_channels(struct mhi_ep_cntrl *mhi_cntrl);\ndrivers/bus/mhi/ep/internal.h-221-\n--\ndrivers/bus/mhi/ep/main.c-14-#include \u003clinux/irq.h\u003e\ndrivers/bus/mhi/ep/main.c:15:#include \u003clinux/mhi_ep.h\u003e\ndrivers/bus/mhi/ep/main.c-16-#include \u003clinux/module.h\u003e\n--\ndrivers/bus/mhi/ep/main.c-21-\ndrivers/bus/mhi/ep/main.c:22:static DEFINE_IDA(mhi_ep_cntrl_ida);\ndrivers/bus/mhi/ep/main.c-23-\ndrivers/bus/mhi/ep/main.c:24:static int mhi_ep_create_device(struct mhi_ep_cntrl *mhi_cntrl, u32 ch_id);\ndrivers/bus/mhi/ep/main.c:25:static int mhi_ep_destroy_device(struct device *dev, void *data);\ndrivers/bus/mhi/ep/main.c-26-\ndrivers/bus/mhi/ep/main.c:27:static int mhi_ep_send_event(struct mhi_ep_cntrl *mhi_cntrl, u32 ring_idx,\ndrivers/bus/mhi/ep/main.c-28-\t\t\t struct mhi_ring_element *el, bool bei)\n--\ndrivers/bus/mhi/ep/main.c-30-\tstruct device *dev = \u0026mhi_cntrl-\u003emhi_dev-\u003edev;\ndrivers/bus/mhi/ep/main.c:31:\tunion mhi_ep_ring_ctx *ctx;\ndrivers/bus/mhi/ep/main.c:32:\tstruct mhi_ep_ring *ring;\ndrivers/bus/mhi/ep/main.c-33-\tint ret;\n--\ndrivers/bus/mhi/ep/main.c-36-\tring = \u0026mhi_cntrl-\u003emhi_event[ring_idx].ring;\ndrivers/bus/mhi/ep/main.c:37:\tctx = (union mhi_ep_ring_ctx *)\u0026mhi_cntrl-\u003eev_ctx_cache[ring_idx];\ndrivers/bus/mhi/ep/main.c-38-\tif (!ring-\u003estarted) {\ndrivers/bus/mhi/ep/main.c:39:\t\tret = mhi_ep_ring_start(mhi_cntrl, ring, ctx);\ndrivers/bus/mhi/ep/main.c-40-\t\tif (ret) {\n--\ndrivers/bus/mhi/ep/main.c-46-\t/* Add element to the event ring */\ndrivers/bus/mhi/ep/main.c:47:\tret = mhi_ep_ring_add_element(ring, el);\ndrivers/bus/mhi/ep/main.c-48-\tif (ret) {\n--\ndrivers/bus/mhi/ep/main.c-85-\ndrivers/bus/mhi/ep/main.c:86:static int mhi_ep_send_completion_event(struct mhi_ep_cntrl *mhi_cntrl, struct mhi_ep_ring *ring,\ndrivers/bus/mhi/ep/main.c-87-\t\t\t\t\tstruct mhi_ring_element *tre, u32 len, enum mhi_ev_ccs code)\n--\ndrivers/bus/mhi/ep/main.c-99-\ndrivers/bus/mhi/ep/main.c:100:\tret = mhi_ep_send_event(mhi_cntrl, ring-\u003eer_index, event, MHI_TRE_DATA_GET_BEI(tre));\ndrivers/bus/mhi/ep/main.c-101-\tkmem_cache_free(mhi_cntrl-\u003eev_ring_el_cache, event);\n--\ndrivers/bus/mhi/ep/main.c-105-\ndrivers/bus/mhi/ep/main.c:106:int mhi_ep_send_state_change_event(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_state state)\ndrivers/bus/mhi/ep/main.c-107-{\n--\ndrivers/bus/mhi/ep/main.c-117-\ndrivers/bus/mhi/ep/main.c:118:\tret = mhi_ep_send_event(mhi_cntrl, 0, event, 0);\ndrivers/bus/mhi/ep/main.c-119-\tkmem_cache_free(mhi_cntrl-\u003eev_ring_el_cache, event);\n--\ndrivers/bus/mhi/ep/main.c-123-\ndrivers/bus/mhi/ep/main.c:124:int mhi_ep_send_ee_event(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_ee_type exec_env)\ndrivers/bus/mhi/ep/main.c-125-{\n--\ndrivers/bus/mhi/ep/main.c-135-\ndrivers/bus/mhi/ep/main.c:136:\tret = mhi_ep_send_event(mhi_cntrl, 0, event, 0);\ndrivers/bus/mhi/ep/main.c-137-\tkmem_cache_free(mhi_cntrl-\u003eev_ring_el_cache, event);\n--\ndrivers/bus/mhi/ep/main.c-141-\ndrivers/bus/mhi/ep/main.c:142:static int mhi_ep_send_cmd_comp_event(struct mhi_ep_cntrl *mhi_cntrl, enum mhi_ev_ccs code)\ndrivers/bus/mhi/ep/main.c-143-{\ndrivers/bus/mhi/ep/main.c:144:\tstruct mhi_ep_ring *ring = \u0026mhi_cntrl-\u003emhi_cmd-\u003ering;\ndrivers/bus/mhi/ep/main.c-145-\tstruct mhi_ring_element *event;\n--\ndrivers/bus/mhi/ep/main.c-155-\ndrivers/bus/mhi/ep/main.c:156:\tret = mhi_ep_send_event(mhi_cntrl, 0, event, 0);\ndrivers/bus/mhi/ep/main.c-157-\tkmem_cache_free(mhi_cntrl-\u003eev_ring_el_cache, event);\n--\ndrivers/bus/mhi/ep/main.c-161-\ndrivers/bus/mhi/ep/main.c:162:static int mhi_ep_process_cmd_ring(struct mhi_ep_ring *ring, struct mhi_ring_element *el)\ndrivers/bus/mhi/ep/main.c-163-{\ndrivers/bus/mhi/ep/main.c:164:\tstruct mhi_ep_cntrl *mhi_cntrl = ring-\u003emhi_cntrl;\ndrivers/bus/mhi/ep/main.c-165-\tstruct device *dev = \u0026mhi_cntrl-\u003emhi_dev-\u003edev;\ndrivers/bus/mhi/ep/main.c-166-\tstruct mhi_result result = {};\ndrivers/bus/mhi/ep/main.c:167:\tstruct mhi_ep_chan *mhi_chan;\ndrivers/bus/mhi/ep/main.c:168:\tstruct mhi_ep_ring *ch_ring;\ndrivers/bus/mhi/ep/main.c-169-\tu32 tmp, ch_id;\n--\ndrivers/bus/mhi/ep/main.c-189-\t\tif (!ch_ring-\u003estarted) {\ndrivers/bus/mhi/ep/main.c:190:\t\t\tret = mhi_ep_ring_start(mhi_cntrl, ch_ring,\ndrivers/bus/mhi/ep/main.c:191:\t\t\t\t(union mhi_ep_ring_ctx *)\u0026mhi_cntrl-\u003ech_ctx_cache[ch_id]);\ndrivers/bus/mhi/ep/main.c-192-\t\t\tif (ret) {\ndrivers/bus/mhi/ep/main.c-193-\t\t\t\tdev_err(dev, \"Failed to start ring for channel (%u)\\n\", ch_id);\ndrivers/bus/mhi/ep/main.c:194:\t\t\t\tret = mhi_ep_send_cmd_comp_event(mhi_cntrl,\ndrivers/bus/mhi/ep/main.c-195-\t\t\t\t\t\t\tMHI_EV_CC_UNDEFINED_ERR);\n--\ndrivers/bus/mhi/ep/main.c-211-\ndrivers/bus/mhi/ep/main.c:212:\t\tret = mhi_ep_send_cmd_comp_event(mhi_cntrl, MHI_EV_CC_SUCCESS);\ndrivers/bus/mhi/ep/main.c-213-\t\tif (ret) {\n--\ndrivers/bus/mhi/ep/main.c-230-\t\tif (!(ch_id % 2) \u0026\u0026 !mhi_chan-\u003emhi_dev) {\ndrivers/bus/mhi/ep/main.c:231:\t\t\tret = mhi_ep_create_device(mhi_cntrl, ch_id);\ndrivers/bus/mhi/ep/main.c-232-\t\t\tif (ret) {\n--\ndrivers/bus/mhi/ep/main.c-234-\t\t\t\tmutex_lock(\u0026mhi_cntrl-\u003estate_lock);\ndrivers/bus/mhi/ep/main.c:235:\t\t\t\tmhi_ep_handle_syserr(mhi_cntrl);\ndrivers/bus/mhi/ep/main.c-236-\t\t\t\tmutex_unlock(\u0026mhi_cntrl-\u003estate_lock);\n--\ndrivers/bus/mhi/ep/main.c-241-\t\t/* Finally, enable DB for the channel */\ndrivers/bus/mhi/ep/main.c:242:\t\tmhi_ep_mmio_enable_chdb(mhi_cntrl, ch_id);\ndrivers/bus/mhi/ep/main.c-243-\n--\ndrivers/bus/mhi/ep/main.c-253-\t\t/* Disable DB for the channel */\ndrivers/bus/mhi/ep/main.c:254:\t\tmhi_ep_mmio_disable_chdb(mhi_cntrl, ch_id);\ndrivers/bus/mhi/ep/main.c-255-\n\n"
} |
| 27/2 | 2026/10/28 01:45 | llm | patch-evaluator |
2mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 30363 output: 35 thoughts: 502 Thoughts: **Dissecting the `pci-epf-mhi.c` Module**
Okay, let's dive into `drivers/pci/endpoint/functions/pci-epf-mhi.c`. I need to understand its role. Is this the right spot for the PCI endpoint function? Hmm, let's see. My first impression is that it deals with MHI.
Wait a second. I spot `mhi_wwan_ctrl` and `mhi_wwan_dtr` driver registrations:
```c
static struct mhi_driver mhi_wwan_ctrl_driver = {
...
static struct mhi_driver mhi_wwan_dtr_driver = {
...
```
Right, but these are for `mhi_bus_type`. This is host-side, not endpoint-side, as I thought initially. The endpoint side uses `mhi_ep_driver` and `mhi_ep_bus_type`, if my memory serves. Need to confirm that.
Alright, let's double-check the definition of `mhi_driver`. I'll find it in `include/linux/mhi.h`:
```c
int __mhi_driver_register(struct mhi_driver *mhi_drv, struct module *owner);
```
Okay, so it's a driver structure. Now, the `mhi_wwan_ctrl_match_table` is interesting:
```c
static const struct mhi_device_id mhi_wwan_ctrl_match_table[] = {
{ .chan = "DUN", .driver_data = WWAN_PORT_AT },
{ .chan = "DUN2", .driver_data = WWAN_PORT_AT },
{ .chan = "MBIM", .driver_data = WWAN_PORT_MBIM },
{ .chan = "QMI", .driver_data = WWAN_PORT_QMI },
{ .chan = "DIAG", .driver_data = WWAN_PORT_QCDM },
{ .chan = "FIREHOSE", .driver_data = WWAN_PORT_FIREHOSE },
{},
};
```
This defines match criteria, channel names and associated driver data. And similarly, `mhi_wwan_dtr_match_table`:
```c
static const struct mhi_device_id mhi_wwan_dtr_match_table[] = {
{ .chan = "IP_CTRL" },
{},
};
```
I get it. It looks like this module is defining the drivers and match tables for MHI host channels, likely related to WWAN functionality.
My next question is: how is an MHI host channel device actually created? I need to find where `mhi_device_create` is called. Let's search within `drivers/bus/mhi/host/`. That should give me the creation flow.
|
| 28/2 | 2026/10/28 01:47 | tool | grepper |
0mError:no matches Args: {
"Expression": "mhi_device_create",
"PathPrefixes": [
"drivers/bus/mhi/host"
]
}Results: {
"error": "no matches"
} |
| 29/2 | 2026/10/28 01:47 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 31576 output: 45 thoughts: 27 Thoughts: Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person: **Finding the Source of `mhi_device`** Alright, I need to track down where this `mhi_device` is actually brought into existence. My first instinct, given the context, is to zero in on the `drivers/bus/mhi/host/` directory. That's the logical place to start looking for the allocation or creation of this structure, especially since it's associated with the Message Handling Interface (MHI) host driver. I'm thinking, most likely, it's being done during probe, initialization, or perhaps even in a related sub-module within that directory structure. I'll need to use my search tools (likely `grep` or `find` combined with `grep`) to pinpoint the exact location. Specifically, I'll be looking for where the memory for the `mhi_device` struct is allocated and then populated. This is probably a good starting point before I start tracing how it is used within the code. |
| 30/2 | 2026/10/28 01:48 | tool | grepper |
0mArgs:{
"Expression": "kzalloc.*sizeof.*mhi_device|mhi_alloc_device",
"PathPrefixes": [
"drivers/bus/mhi/host"
]
}Results: {
"Output": "drivers/bus/mhi/host/init.c=919=int mhi_register_controller(struct mhi_controller *mhi_cntrl,\n--\ndrivers/bus/mhi/host/init.c-1009-\t/* Register controller with MHI bus */\ndrivers/bus/mhi/host/init.c:1010:\tmhi_dev = mhi_alloc_device(mhi_cntrl);\ndrivers/bus/mhi/host/init.c-1011-\tif (IS_ERR(mhi_dev)) {\n--\ndrivers/bus/mhi/host/init.c=1210=static void mhi_release_device(struct device *dev)\n--\ndrivers/bus/mhi/host/init.c-1228-\ndrivers/bus/mhi/host/init.c:1229:struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl)\ndrivers/bus/mhi/host/init.c-1230-{\n--\ndrivers/bus/mhi/host/internal.h=314=static inline void mhi_debugfs_exit(void)\n--\ndrivers/bus/mhi/host/internal.h-318-\ndrivers/bus/mhi/host/internal.h:319:struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl);\ndrivers/bus/mhi/host/internal.h-320-\n--\ndrivers/bus/mhi/host/main.c=369=void mhi_create_devices(struct mhi_controller *mhi_cntrl)\n--\ndrivers/bus/mhi/host/main.c-380-\t\t\tcontinue;\ndrivers/bus/mhi/host/main.c:381:\t\tmhi_dev = mhi_alloc_device(mhi_cntrl);\ndrivers/bus/mhi/host/main.c-382-\t\tif (IS_ERR(mhi_dev))\n"
} |
| 31/2 | 2026/10/28 01:48 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 32391 output: 35 thoughts: 46 Thoughts: Here's my analysis of the provided information, as though it were my thought process: **Deconstructing the MHI Device Creation** Okay, so we're talking about the mechanism that generates MHI devices. The core function is `mhi_create_devices`. Its primary task, as the name suggests, is to instantiate `mhi_device` objects. The input for this function is defined through configurations on `mhi_cntrl`. This makes sense; the controller likely provides the parameters or resources that define the channels which, in turn, drive the device creation process. Now, the crucial question is, *where* does this `mhi_create_devices` function get invoked? Understanding its call site is absolutely critical to grasping the overall MHI device lifecycle. Determining that location will reveal the entry point for device initialization and how the system triggers the instantiation process. This also provides insight to the system constraints; what conditions must be met for this initialization to be triggered? |
| 32/2 | 2026/10/28 01:49 | tool | grepper |
0mArgs:{
"Expression": "mhi_create_devices",
"PathPrefixes": [
"drivers/bus/mhi/host"
]
}Results: {
"Output": "drivers/bus/mhi/host/internal.h=321=int mhi_destroy_device(struct device *dev, void *data);\ndrivers/bus/mhi/host/internal.h:322:void mhi_create_devices(struct mhi_controller *mhi_cntrl);\ndrivers/bus/mhi/host/internal.h-323-\n--\ndrivers/bus/mhi/host/main.c=366=EXPORT_SYMBOL_GPL(mhi_notify);\n--\ndrivers/bus/mhi/host/main.c-368-/* Bind MHI channels to MHI devices */\ndrivers/bus/mhi/host/main.c:369:void mhi_create_devices(struct mhi_controller *mhi_cntrl)\ndrivers/bus/mhi/host/main.c-370-{\n--\ndrivers/bus/mhi/host/pm.c=394=static int mhi_pm_mission_mode_transition(struct mhi_controller *mhi_cntrl)\n--\ndrivers/bus/mhi/host/pm.c-459-\t */\ndrivers/bus/mhi/host/pm.c:460:\tmhi_create_devices(mhi_cntrl);\ndrivers/bus/mhi/host/pm.c-461-\n--\ndrivers/bus/mhi/host/pm.c=790=void mhi_pm_st_worker(struct work_struct *work)\n--\ndrivers/bus/mhi/host/pm.c-823-\t\t\t */\ndrivers/bus/mhi/host/pm.c:824:\t\t\tmhi_create_devices(mhi_cntrl);\ndrivers/bus/mhi/host/pm.c-825-\t\t\tif (mhi_cntrl-\u003efbc_download)\n--\ndrivers/bus/mhi/host/pm.c-836-\t\t\twrite_unlock_irq(\u0026mhi_cntrl-\u003epm_lock);\ndrivers/bus/mhi/host/pm.c:837:\t\t\tmhi_create_devices(mhi_cntrl);\ndrivers/bus/mhi/host/pm.c-838-\t\t\tmhi_uevent_notify(mhi_cntrl, mhi_cntrl-\u003eee);\n"
} |
| 33/2 | 2026/10/28 01:49 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 33248 output: 22 thoughts: 281 Thoughts: **Investigating MHI Controller Registration** Okay, so `mhi_create_devices` seems to be exclusively tied to state machine transitions within an *active* MHI controller – things like the `mhi_pci_generic.c` code when a Qualcomm modem PCI card is plugged in. But a question is bugging me: Can an MHI controller even be registered without physical PCI hardware? I need to figure out if there are any mock, virtual, or dummy MHI controllers lurking around somewhere in the codebase. Let's start with a comprehensive search for all instances of `mhi_register_controller`. I've already looked at these: 1. `drivers/accel/qaic/mhi_controller.c` - That's the Qualcomm Cloud AI 100 PCIe, which is definitely hardware. 2. `drivers/bus/mhi/host/pci_generic.c` - Qualcomm-based PCIe modems; also hardware. 3. `drivers/net/wireless/ath/ath11k/mhi.c` - Qualcomm PCIe WiFi; hardware again. 4. `drivers/net/wireless/ath/ath12k/mhi.c` - Same Qualcomm PCIe WiFi, so, hardware. But are there *any* others? I need to broaden the search. Ah, wait a minute, what about `pci-epf-mhi.c`? Does *that* register a controller? I should check what that driver actually does. |
| 34/2 | 2026/10/28 01:49 | tool | grepper |
0mArgs:{
"Expression": "pci-epf-mhi"
}Results: {
"Output": "MAINTAINERS=17730=F:\tdrivers/bus/mhi/\nMAINTAINERS:17731:F:\tdrivers/pci/endpoint/functions/pci-epf-mhi.c\nMAINTAINERS-17732-F:\tinclude/linux/mhi.h\n--\ndrivers/pci/endpoint/functions/Makefile=8=obj-$(CONFIG_PCI_EPF_VNTB) \t\t+= pci-epf-vntb.o\ndrivers/pci/endpoint/functions/Makefile:9:obj-$(CONFIG_PCI_EPF_MHI)\t\t+= pci-epf-mhi.o\n"
} |
| 35/2 | 2026/10/28 01:49 | llm | patch-evaluator |
1mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 34054 output: 22 thoughts: 16 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience: **Diving into `pci-epf-mhi.c`** Alright, time to get to it. My immediate thought is to zero in on `pci-epf-mhi.c`. That file, or something related to it, is clearly where the action is. I need to refresh my mental model of the MHI interface and how it's being managed through the PCI endpoint function driver. I'll be looking for potential areas of concern: resource allocation, interrupt handling (especially edge-triggered vs. level-triggered, and how they're masked/unmasked), DMA setup (scatter-gather lists, cache coherency, etc.), and of course, any quirky interaction with the EPF's function drivers. I'll be particularly interested to see if there's any cleverness in handling the various message types or any potential race conditions involving shared data structures between the MHI controller and any function driver clients. Let's see what gems are contained within. |
| 36/2 | 2026/10/28 01:50 | tool | grepper |
0mArgs:{
"Expression": "mhi_ep_register_controller"
}Results: {
"Output": "drivers/bus/mhi/ep/main.c=1406=static int mhi_ep_chan_init(struct mhi_ep_cntrl *mhi_cntrl,\n--\ndrivers/bus/mhi/ep/main.c-1462- */\ndrivers/bus/mhi/ep/main.c:1463:int mhi_ep_register_controller(struct mhi_ep_cntrl *mhi_cntrl,\ndrivers/bus/mhi/ep/main.c-1464-\t\t\t\tconst struct mhi_ep_cntrl_config *config)\n--\ndrivers/bus/mhi/ep/main.c-1588-}\ndrivers/bus/mhi/ep/main.c:1589:EXPORT_SYMBOL_GPL(mhi_ep_register_controller);\ndrivers/bus/mhi/ep/main.c-1590-\n--\ndrivers/pci/endpoint/functions/pci-epf-mhi.c=779=static int pci_epf_mhi_link_up(struct pci_epf *epf)\n--\ndrivers/pci/endpoint/functions/pci-epf-mhi.c-807-\t/* Register the MHI EP controller */\ndrivers/pci/endpoint/functions/pci-epf-mhi.c:808:\tret = mhi_ep_register_controller(mhi_cntrl, info-\u003econfig);\ndrivers/pci/endpoint/functions/pci-epf-mhi.c-809-\tif (ret) {\n--\ninclude/linux/mhi_ep.h=257=void mhi_ep_driver_unregister(struct mhi_ep_driver *mhi_drv);\n--\ninclude/linux/mhi_ep.h-259-/**\ninclude/linux/mhi_ep.h:260: * mhi_ep_register_controller - Register MHI Endpoint controller\ninclude/linux/mhi_ep.h-261- * @mhi_cntrl: MHI Endpoint controller to register\n--\ninclude/linux/mhi_ep.h-265- */\ninclude/linux/mhi_ep.h:266:int mhi_ep_register_controller(struct mhi_ep_cntrl *mhi_cntrl,\ninclude/linux/mhi_ep.h-267-\t\t\t const struct mhi_ep_cntrl_config *config);\n"
} |
| 37/2 | 2026/10/28 01:50 | llm | patch-evaluator |
1mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 34928 output: 33 thoughts: 290 Thoughts: **My Assessment of the MHI Driver and Virtualization Possibilities** Okay, so I'm looking at `pci-epf-mhi.c`. Right, that's for the PCI endpoint *function* – it's acting as the modem or endpoint device, meaning it expects specific PCI endpoint controller hardware. It's registering an EP controller, `mhi_ep_cntrl`, which makes sense. It's not the *host* controller. The host-side driver, `mhi_wwan_ctrl`, that I'm familiar with is a `struct mhi_driver`. Aha! Now I'm wondering if something like syzkaller or QEMU can even create an `mhi_device` in the first place. Let's circle back to that section in the instructions. Ah yes, it's the one about "Structurally unreachable hardware." It mentions things like vendor-specific PCIe switches, SmartNICs, GPU drivers – things that need physical ASIC/PCIe cards and aren't typically emulated in a standard QEMU environment, like `mlxsw`, `pds_core`, `qed`, etc. But wait, what about virtual buses? We're often able to hook into things via virtual buses like virtio, USB gadget, loopback, netlink, binder, or sockets. Can MHI possibly be accessed through one of those? That's the key question. Let's investigate. Can we instantiate MHI via USB? No, MHI is "Modem Host Interface" which makes it plain that it's over PCIe. Okay, let's explore if MHI devices can be created via sysfs through a `new_device` entry, or a similar method. Let's dig into the `mhi_bus_type` structure and see if there are any methods, like `new_device`, `bind`, or anything like that, that would allow for an MHI device to be created. That's the next line of inquiry. |
| 38/2 | 2026/10/28 01:51 | tool | grepper |
0mArgs:{
"Expression": "mhi_bus_type",
"PathPrefixes": [
"drivers/bus/mhi"
]
}Results: {
"Output": "drivers/bus/mhi/host/debugfs.c=131=static int mhi_device_info_show(struct device *dev, void *data)\n--\ndrivers/bus/mhi/host/debugfs.c-134-\ndrivers/bus/mhi/host/debugfs.c:135:\tif (dev-\u003ebus != \u0026mhi_bus_type)\ndrivers/bus/mhi/host/debugfs.c-136-\t\treturn 0;\n--\ndrivers/bus/mhi/host/debugfs.c=406=void mhi_debugfs_init(void)\ndrivers/bus/mhi/host/debugfs.c-407-{\ndrivers/bus/mhi/host/debugfs.c:408:\tmhi_debugfs_root = debugfs_create_dir(mhi_bus_type.name, NULL);\ndrivers/bus/mhi/host/debugfs.c-409-}\n--\ndrivers/bus/mhi/host/init.c=1229=struct mhi_device *mhi_alloc_device(struct mhi_controller *mhi_cntrl)\n--\ndrivers/bus/mhi/host/init.c-1239-\tdevice_initialize(dev);\ndrivers/bus/mhi/host/init.c:1240:\tdev-\u003ebus = \u0026mhi_bus_type;\ndrivers/bus/mhi/host/init.c-1241-\tdev-\u003erelease = mhi_release_device;\n--\ndrivers/bus/mhi/host/init.c=1401=int __mhi_driver_register(struct mhi_driver *mhi_drv, struct module *owner)\n--\ndrivers/bus/mhi/host/init.c-1407-\ndrivers/bus/mhi/host/init.c:1408:\tdriver-\u003ebus = \u0026mhi_bus_type;\ndrivers/bus/mhi/host/init.c-1409-\tdriver-\u003eowner = owner;\n--\ndrivers/bus/mhi/host/init.c=1429=static int mhi_match(struct device *dev, const struct device_driver *drv)\n--\ndrivers/bus/mhi/host/init.c-1450-\ndrivers/bus/mhi/host/init.c:1451:const struct bus_type mhi_bus_type = {\ndrivers/bus/mhi/host/init.c-1452-\t.name = \"mhi\",\n--\ndrivers/bus/mhi/host/init.c=1461=static int __init mhi_init(void)\n--\ndrivers/bus/mhi/host/init.c-1463-\tmhi_debugfs_init();\ndrivers/bus/mhi/host/init.c:1464:\treturn bus_register(\u0026mhi_bus_type);\ndrivers/bus/mhi/host/init.c-1465-}\n--\ndrivers/bus/mhi/host/init.c=1467=static void __exit mhi_exit(void)\n--\ndrivers/bus/mhi/host/init.c-1469-\tmhi_debugfs_exit();\ndrivers/bus/mhi/host/init.c:1470:\tbus_unregister(\u0026mhi_bus_type);\ndrivers/bus/mhi/host/init.c-1471-}\n--\ndrivers/bus/mhi/host/internal.h-11-\ndrivers/bus/mhi/host/internal.h:12:extern const struct bus_type mhi_bus_type;\ndrivers/bus/mhi/host/internal.h-13-\n--\ndrivers/bus/mhi/host/main.c=283=int mhi_destroy_device(struct device *dev, void *data)\n--\ndrivers/bus/mhi/host/main.c-289-\ndrivers/bus/mhi/host/main.c:290:\tif (dev-\u003ebus != \u0026mhi_bus_type)\ndrivers/bus/mhi/host/main.c-291-\t\treturn 0;\n"
} |
| 39/2 | 2026/10/28 01:51 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 36718 output: 41 thoughts: 28 Thoughts: Okay, here's my take on those thoughts, tailored for an expert audience: **Diving into the MHI Bus Initialization** Right, let's get down to brass tacks. I need to refresh my memory on the specifics of how the `mhi_bus_type` is defined. I'll head straight to the source – `drivers/bus/mhi/host/init.c` – that's the logical place to start digging. I'm especially interested in understanding the nuances of that particular bus type's registration and any related initialization details. My goal is to quickly pinpoint how it's handled at boot, so I can see what I'm dealing with. |
| 40/2 | 2026/10/28 01:51 | tool | read-file |
0mArgs:{
"File": "drivers/bus/mhi/host/init.c",
"FirstLine": 1445,
"LineCount": 20
}Results: {
"Contents": "1445:\t\t\t\treturn 1;\n1446:\t\t\t}\n1447:\t\n1448:\t\treturn 0;\n1449:\t};\n1450:\t\n1451:\tconst struct bus_type mhi_bus_type = {\n1452:\t\t.name = \"mhi\",\n1453:\t\t.dev_name = \"mhi\",\n1454:\t\t.match = mhi_match,\n1455:\t\t.uevent = mhi_uevent,\n1456:\t\t.probe = mhi_probe,\n1457:\t\t.remove = mhi_remove,\n1458:\t\t.dev_groups = mhi_dev_groups,\n1459:\t};\n1460:\t\n1461:\tstatic int __init mhi_init(void)\n1462:\t{\n1463:\t\tmhi_debugfs_init();\n1464:\t\treturn bus_register(\u0026mhi_bus_type);\n"
} |
| 41/2 | 2026/10/28 01:51 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 37205 output: 42 thoughts: 670 Thoughts: **My Analysis of the MHI Bus and Device Creation**
Okay, here's what I've got so far. It seems like the `mhi_bus_type` is pretty restrictive. I'm not seeing any mechanisms for userspace to directly instantiate an `mhi_device`. There's no `new_device` or `bind` attribute in the bus type or anything like that. It's becoming clear that devices on this bus are solely brought into existence through `mhi_create_devices()` or `mhi_alloc_device()` in `init.c`. And both of those functions specifically require an active `mhi_controller`.
So, the next obvious question is, what registers an `mhi_controller`? Looking at the code, it's pretty limited. It's being registered by only a few drivers:
1. `pci_generic.c` in `drivers/bus/mhi/host`: This looks like the main entry point, a PCI driver for physical Qualcomm modems – think those SDX24, SDX55, SDX65 types, those with PCI IDs like 0x011a, 0x0304, 0x0306, etc.
2. `qaic` (Qualcomm Cloud AI 100 PCIe accelerator) in `drivers/accel/qaic`: This is pretty straightforward.
3. `ath11k` and `ath12k` in `drivers/net/wireless/ath`: These are for Qualcomm Wi-Fi PCIe chips such as WCN6855, QCN9074, and WCN7850.
Now, I'm trying to figure out if `mhi_wwan_ctrl` could be somehow connected to the QAIC or ath11k/ath12k drivers. But the answer is no, because `qaic` creates QAIC devices and ath11k/ath12k create ath11k/ath12k MHI devices with specific channel names like "WLAN".
Okay, so who *does* use `mhi_wwan_ctrl`? Let's look at the match tables:
The relevant match table code includes this:
```c
static const struct mhi_device_id mhi_wwan_ctrl_match_table[] = {
{ .chan = "DUN", .driver_data = WWAN_PORT_AT },
{ .chan = "DUN2", .driver_data = WWAN_PORT_AT },
{ .chan = "MBIM", .driver_data = WWAN_PORT_MBIM },
{ .chan = "QMI", .driver_data = WWAN_PORT_QMI },
{ .chan = "DIAG", .driver_data = WWAN_PORT_QCDM },
{ .chan = "FIREHOSE", .driver_data = WWAN_PORT_FIREHOSE },
{},
};
```
and:
```c
static const struct mhi_device_id mhi_wwan_dtr_match_table[] = {
{ .chan = "IP_CTRL" },
{},
};
```
These "DUN", "DUN2", "MBIM", "QMI", "DIAG", "FIREHOSE", and "IP\_CTRL" channel names, are defined specifically within the modem configurations within `drivers/bus/mhi/host/pci_generic.c`. Therefore, the `mhi_wwan_ctrl` is a component of the MHI system for the Qualcomm physical modems. It's all linked together through the `pci_generic.c` driver. I should probably verify this by examining that file directly, but I'm pretty certain at this point.
|
| 42/2 | 2026/10/28 01:52 | tool | grepper |
0mArgs:{
"Expression": "\"IP_CTRL\"|\"FIREHOSE\"|\"DUN\"",
"PathPrefixes": [
"drivers/bus/mhi/host"
]
}Results: {
"Output": "drivers/bus/mhi/host/pci_generic.c=316=static const struct mhi_channel_config modem_qcom_v1_mhi_channels[] = {\n--\ndrivers/bus/mhi/host/pci_generic.c-324-\tMHI_CHANNEL_CONFIG_DL(21, \"IPCR\", 8, 0),\ndrivers/bus/mhi/host/pci_generic.c:325:\tMHI_CHANNEL_CONFIG_UL_FP(34, \"FIREHOSE\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:326:\tMHI_CHANNEL_CONFIG_DL_FP(35, \"FIREHOSE\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c-327-\tMHI_CHANNEL_CONFIG_UL(46, \"IP_SW0\", 64, 2),\n--\ndrivers/bus/mhi/host/pci_generic.c=437=static const struct mhi_channel_config mhi_quectel_em1xx_channels[] = {\n--\ndrivers/bus/mhi/host/pci_generic.c-445-\tMHI_CHANNEL_CONFIG_DL(13, \"MBIM\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:446:\tMHI_CHANNEL_CONFIG_UL(32, \"DUN\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:447:\tMHI_CHANNEL_CONFIG_DL(33, \"DUN\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c-448-\t/* The EDL firmware is a flash-programmer exposing firehose protocol */\ndrivers/bus/mhi/host/pci_generic.c:449:\tMHI_CHANNEL_CONFIG_UL_FP(34, \"FIREHOSE\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:450:\tMHI_CHANNEL_CONFIG_DL_FP(35, \"FIREHOSE\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c-451-\tMHI_CHANNEL_CONFIG_HW_UL(100, \"IP_HW0_MBIM\", 128, 2),\n--\ndrivers/bus/mhi/host/pci_generic.c=491=static const struct mhi_channel_config mhi_foxconn_sdx55_channels[] = {\n--\ndrivers/bus/mhi/host/pci_generic.c-499-\tMHI_CHANNEL_CONFIG_DL(13, \"MBIM\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:500:\tMHI_CHANNEL_CONFIG_UL(32, \"DUN\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:501:\tMHI_CHANNEL_CONFIG_DL(33, \"DUN\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:502:\tMHI_CHANNEL_CONFIG_UL_FP(34, \"FIREHOSE\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:503:\tMHI_CHANNEL_CONFIG_DL_FP(35, \"FIREHOSE\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c-504-\tMHI_CHANNEL_CONFIG_HW_UL(100, \"IP_HW0_MBIM\", 128, 2),\n--\ndrivers/bus/mhi/host/pci_generic.c=508=static const struct mhi_channel_config mhi_foxconn_sdx61_channels[] = {\n--\ndrivers/bus/mhi/host/pci_generic.c-516-\tMHI_CHANNEL_CONFIG_DL(13, \"MBIM\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:517:\tMHI_CHANNEL_CONFIG_UL(32, \"DUN\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:518:\tMHI_CHANNEL_CONFIG_DL(33, \"DUN\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:519:\tMHI_CHANNEL_CONFIG_UL_FP(34, \"FIREHOSE\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:520:\tMHI_CHANNEL_CONFIG_DL_FP(35, \"FIREHOSE\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c-521-\tMHI_CHANNEL_CONFIG_UL(50, \"NMEA\", 32, 0),\n--\ndrivers/bus/mhi/host/pci_generic.c=726=static const struct mhi_channel_config mhi_sierra_em919x_channels[] = {\n--\ndrivers/bus/mhi/host/pci_generic.c-734-\tMHI_CHANNEL_CONFIG_DL(15, \"QMI\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:735:\tMHI_CHANNEL_CONFIG_UL(32, \"DUN\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:736:\tMHI_CHANNEL_CONFIG_DL(33, \"DUN\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c-737-\tMHI_CHANNEL_CONFIG_HW_UL(100, \"IP_HW0\", 512, 1),\n--\ndrivers/bus/mhi/host/pci_generic.c=802=static const struct mhi_channel_config mhi_telit_fn990_channels[] = {\n--\ndrivers/bus/mhi/host/pci_generic.c-808-\tMHI_CHANNEL_CONFIG_DL(13, \"MBIM\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:809:\tMHI_CHANNEL_CONFIG_UL(32, \"DUN\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:810:\tMHI_CHANNEL_CONFIG_DL(33, \"DUN\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c-811-\tMHI_CHANNEL_CONFIG_UL(92, \"DUN2\", 32, 1),\n--\ndrivers/bus/mhi/host/pci_generic.c=853=static const struct mhi_channel_config mhi_telit_fn920c04_channels[] = {\n--\ndrivers/bus/mhi/host/pci_generic.c-859-\tMHI_CHANNEL_CONFIG_DL(15, \"QMI\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:860:\tMHI_CHANNEL_CONFIG_UL(32, \"DUN\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:861:\tMHI_CHANNEL_CONFIG_DL(33, \"DUN\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:862:\tMHI_CHANNEL_CONFIG_UL_FP(34, \"FIREHOSE\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c:863:\tMHI_CHANNEL_CONFIG_DL_FP(35, \"FIREHOSE\", 32, 0),\ndrivers/bus/mhi/host/pci_generic.c-864-\tMHI_CHANNEL_CONFIG_UL(92, \"DUN2\", 32, 1),\n"
} |
| 43/2 | 2026/10/28 01:52 | llm | patch-evaluator |
2mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 40807 output: 21 thoughts: 310 Thoughts: **My Assessment of the `mhi_wwan_ctrl` Module and its Context** Okay, so `mhi_wwan_ctrl` is *specifically* tailored for MHI channels that are brought into existence by Qualcomm-based PCIe modems, as the code in `pci_generic.c` clearly dictates. The whole point of it is to handle WWAN traffic over those MHI-connected PCIe devices. My immediate question is: are there *any* scenarios outside of this hardware ecosystem where this module would even be relevant? Is there some kind of virtual device, software emulator, or something running in QEMU that might create these MHI channels without the underlying Qualcomm hardware? Let's verify. First, QEMU is a good starting point. Can QEMU emulate a Qualcomm PCIe modem, something like a Telit FN980 or a Foxconn SDX55? No. QEMU doesn't have a device model for that specific hardware, meaning no MHI channels will be created in that environment. What about USB? No, MHI, as I recall, is a PCIe protocol, so it's not a USB thing. It's PCIe all the way. Wait, the WWAN subsystem itself is important here. I should probably think about this more broadly. The WWAN core provides the usual suspects – `wwan_create_port`, `wwan_register_ops`, and the like. Now, I do remember `wwan_hwsim`, which is the WWAN hardware simulator. But wait... as far as I can see, `wwan_hwsim` just registers its *own* port operations (`wwan_hwsim_at_emul_port_ops` and `wwan_hwsim_nmea_emul_port_ops`). This means it directly creates the port operations, and it bypasses `mhi_wwan_ctrl` entirely. No interaction there. I need to confirm this. I need to go through the `drivers/net/wwan` directory, and the *entire* kernel source. Just to be sure, I need to search the entire source tree for any references to `mhi_wwan_ctrl`. |
| 44/2 | 2026/10/28 01:54 | tool | grepper |
0mArgs:{
"Expression": "mhi_wwan_ctrl"
}Results: {
"Output": "drivers/net/wwan/Kconfig=40=config MHI_WWAN_CTRL\n--\ndrivers/net/wwan/Kconfig-50-\t To compile this driver as a module, choose M here: the module will be\ndrivers/net/wwan/Kconfig:51:\t called mhi_wwan_ctrl.\ndrivers/net/wwan/Kconfig-52-\n--\ndrivers/net/wwan/Makefile=9=obj-$(CONFIG_WWAN_HWSIM) += wwan_hwsim.o\ndrivers/net/wwan/Makefile-10-\ndrivers/net/wwan/Makefile:11:obj-$(CONFIG_MHI_WWAN_CTRL) += mhi_wwan_ctrl.o\ndrivers/net/wwan/Makefile-12-obj-$(CONFIG_MHI_WWAN_MBIM) += mhi_wwan_mbim.o\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c=108=static void __mhi_skb_destructor(struct sk_buff *skb)\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-113-\ndrivers/net/wwan/mhi_wwan_ctrl.c:114:static void mhi_wwan_ctrl_refill_work(struct work_struct *work)\ndrivers/net/wwan/mhi_wwan_ctrl.c-115-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-143-/* Signal the modem's DTR/RTS lines over its own controller's IP_CTRL channel */\ndrivers/net/wwan/mhi_wwan_ctrl.c:144:static int mhi_wwan_ctrl_send_dtr(struct mhi_wwan_dev *mhiwwan, unsigned int mdmbits)\ndrivers/net/wwan/mhi_wwan_ctrl.c-145-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-193- */\ndrivers/net/wwan/mhi_wwan_ctrl.c:194:static void mhi_wwan_ctrl_dtr_work(struct work_struct *work)\ndrivers/net/wwan/mhi_wwan_ctrl.c-195-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-199-\ndrivers/net/wwan/mhi_wwan_ctrl.c:200:\tret = mhi_wwan_ctrl_send_dtr(mhiwwan, READ_ONCE(mhiwwan-\u003edtr_mdmbits));\ndrivers/net/wwan/mhi_wwan_ctrl.c-201-\tif (ret == -EAGAIN || ret == -ENOMEM)\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-208-\ndrivers/net/wwan/mhi_wwan_ctrl.c:209:static void mhi_wwan_ctrl_dtr_rts(struct wwan_port *port, unsigned int mdmbits)\ndrivers/net/wwan/mhi_wwan_ctrl.c-210-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-224-\ndrivers/net/wwan/mhi_wwan_ctrl.c:225:static int mhi_wwan_ctrl_start(struct wwan_port *port)\ndrivers/net/wwan/mhi_wwan_ctrl.c-226-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-240-\t\tset_bit(MHI_WWAN_RX_REFILL, \u0026mhiwwan-\u003eflags);\ndrivers/net/wwan/mhi_wwan_ctrl.c:241:\t\tmhi_wwan_ctrl_refill_work(\u0026mhiwwan-\u003erx_refill);\ndrivers/net/wwan/mhi_wwan_ctrl.c-242-\t}\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-246-\ndrivers/net/wwan/mhi_wwan_ctrl.c:247:static void mhi_wwan_ctrl_stop(struct wwan_port *port)\ndrivers/net/wwan/mhi_wwan_ctrl.c-248-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-262-\ndrivers/net/wwan/mhi_wwan_ctrl.c:263:static int mhi_wwan_ctrl_tx(struct wwan_port *port, struct sk_buff *skb)\ndrivers/net/wwan/mhi_wwan_ctrl.c-264-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c=284=static const struct wwan_port_ops wwan_pops = {\ndrivers/net/wwan/mhi_wwan_ctrl.c:285:\t.start = mhi_wwan_ctrl_start,\ndrivers/net/wwan/mhi_wwan_ctrl.c:286:\t.stop = mhi_wwan_ctrl_stop,\ndrivers/net/wwan/mhi_wwan_ctrl.c:287:\t.tx = mhi_wwan_ctrl_tx,\ndrivers/net/wwan/mhi_wwan_ctrl.c:288:\t.dtr_rts = mhi_wwan_ctrl_dtr_rts,\ndrivers/net/wwan/mhi_wwan_ctrl.c-289-};\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c=311=static void mhi_dl_xfer_cb(struct mhi_device *mhi_dev,\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-335-\ndrivers/net/wwan/mhi_wwan_ctrl.c:336:static int mhi_wwan_ctrl_probe(struct mhi_device *mhi_dev,\ndrivers/net/wwan/mhi_wwan_ctrl.c-337-\t\t\t const struct mhi_device_id *id)\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-348-\tmhiwwan-\u003emtu = MHI_WWAN_MAX_MTU;\ndrivers/net/wwan/mhi_wwan_ctrl.c:349:\tINIT_WORK(\u0026mhiwwan-\u003erx_refill, mhi_wwan_ctrl_refill_work);\ndrivers/net/wwan/mhi_wwan_ctrl.c:350:\tINIT_DELAYED_WORK(\u0026mhiwwan-\u003edtr_work, mhi_wwan_ctrl_dtr_work);\ndrivers/net/wwan/mhi_wwan_ctrl.c-351-\tspin_lock_init(\u0026mhiwwan-\u003etx_lock);\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-373-\ndrivers/net/wwan/mhi_wwan_ctrl.c:374:static void mhi_wwan_ctrl_remove(struct mhi_device *mhi_dev)\ndrivers/net/wwan/mhi_wwan_ctrl.c-375-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c=474=static void mhi_wwan_dtr_remove(struct mhi_device *mhi_dev)\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-490-\ndrivers/net/wwan/mhi_wwan_ctrl.c:491:static const struct mhi_device_id mhi_wwan_ctrl_match_table[] = {\ndrivers/net/wwan/mhi_wwan_ctrl.c-492-\t{ .chan = \"DUN\", .driver_data = WWAN_PORT_AT },\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-500-};\ndrivers/net/wwan/mhi_wwan_ctrl.c:501:MODULE_DEVICE_TABLE(mhi, mhi_wwan_ctrl_match_table);\ndrivers/net/wwan/mhi_wwan_ctrl.c-502-\ndrivers/net/wwan/mhi_wwan_ctrl.c:503:static struct mhi_driver mhi_wwan_ctrl_driver = {\ndrivers/net/wwan/mhi_wwan_ctrl.c:504:\t.id_table = mhi_wwan_ctrl_match_table,\ndrivers/net/wwan/mhi_wwan_ctrl.c:505:\t.remove = mhi_wwan_ctrl_remove,\ndrivers/net/wwan/mhi_wwan_ctrl.c:506:\t.probe = mhi_wwan_ctrl_probe,\ndrivers/net/wwan/mhi_wwan_ctrl.c-507-\t.ul_xfer_cb = mhi_ul_xfer_cb,\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-509-\t.driver = {\ndrivers/net/wwan/mhi_wwan_ctrl.c:510:\t\t.name = \"mhi_wwan_ctrl\",\ndrivers/net/wwan/mhi_wwan_ctrl.c-511-\t},\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c=520=static struct mhi_driver mhi_wwan_dtr_driver = {\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-530-\ndrivers/net/wwan/mhi_wwan_ctrl.c:531:static int __init mhi_wwan_ctrl_init(void)\ndrivers/net/wwan/mhi_wwan_ctrl.c-532-{\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-538-\ndrivers/net/wwan/mhi_wwan_ctrl.c:539:\tret = mhi_driver_register(\u0026mhi_wwan_ctrl_driver);\ndrivers/net/wwan/mhi_wwan_ctrl.c-540-\tif (ret)\n--\ndrivers/net/wwan/mhi_wwan_ctrl.c-544-}\ndrivers/net/wwan/mhi_wwan_ctrl.c:545:module_init(mhi_wwan_ctrl_init);\ndrivers/net/wwan/mhi_wwan_ctrl.c-546-\ndrivers/net/wwan/mhi_wwan_ctrl.c:547:static void __exit mhi_wwan_ctrl_exit(void)\ndrivers/net/wwan/mhi_wwan_ctrl.c-548-{\ndrivers/net/wwan/mhi_wwan_ctrl.c:549:\tmhi_driver_unregister(\u0026mhi_wwan_ctrl_driver);\ndrivers/net/wwan/mhi_wwan_ctrl.c-550-\tmhi_driver_unregister(\u0026mhi_wwan_dtr_driver);\ndrivers/net/wwan/mhi_wwan_ctrl.c-551-}\ndrivers/net/wwan/mhi_wwan_ctrl.c:552:module_exit(mhi_wwan_ctrl_exit);\ndrivers/net/wwan/mhi_wwan_ctrl.c-553-\n"
} |
| 45/2 | 2026/10/28 01:54 | llm | patch-evaluator |
0mModel:gemini-3.8-flash Args: null Results: null Tokens: input: 44489 output: 153 thoughts: 1066 Thoughts: **Triage Analysis: mhi_wwan_ctrl Driver Patch** Alright, let's break this down. First, I'm looking at these patch changes, specifically within `drivers/net/wwan/mhi_wwan_ctrl.c`. The modified functions are `mhi_wwan_ctrl_dtr_rts` and `mhi_wwan_ctrl_stop`. My immediate thought is to determine if this code is even *reachable* in a typical fuzzing setup. I have to assess if fuzzing this code is worthwhile. Based on the code changes, it appears we're dealing with DTR/RTS (Data Terminal Ready/Request to Send) control, and modem shutdown procedures. The driver itself, `mhi_wwan_ctrl`, strongly suggests we're working with a Modem Host Interface and a WWAN (Wireless Wide Area Network) modem. Specifically, a Qualcomm-based PCIe modem as the filename suggests. Now, considering the triage guidelines, specifically Sections 1 and 2, my focus is on reachability. The critical question is, does this driver rely on hardware that *isn't* emulated in standard fuzzing environments like QEMU or GCE? The answer is a resounding yes. Qualcomm MHI modems require physical PCIe hardware or a very specific emulated setup that isn't provided by the common virtual machines used for fuzzing. Without this specific modem hardware, `mhi_wwan_ctrl_probe()` doesn't get called, the WWAN port never gets initialized, and neither `mhi_wwan_ctrl_dtr_rts` nor `mhi_wwan_ctrl_stop` can ever be executed. Therefore, this modified code is, for all intents and purposes, structurally unreachable in a standard fuzzing context. Thus, it's not worth fuzzing. I can confidently set WorthFuzzing to false. There are no focus symbols needed, and no specific configuration options that would change this fact. My reasoning is clear, concise, and backed by the nature of the driver's underlying hardware dependency. I've double-checked all aspects. I can now move to the next step and call set-results. |
| 46/2 | 2026/10/28 01:55 | tool | set-results |
0mArgs:{
"EnableConfigs": [],
"FocusSymbols": [],
"Reasoning": "The patch modifies `mhi_wwan_ctrl_dtr_rts` and `mhi_wwan_ctrl_stop` in `drivers/net/wwan/mhi_wwan_ctrl.c`. This is an MHI (Modem Host Interface) driver for Qualcomm-based PCIe modems (such as SDX24/SDX55/SDX65). It requires physical Qualcomm PCIe modem hardware and cannot be emulated or probed in standard virtualized fuzzing environments (QEMU/GCE), making the modified code structurally unreachable.",
"WorthFuzzing": false
}Results: {
"EnableConfigs": null,
"FocusSymbols": [],
"Reasoning": "The patch modifies `mhi_wwan_ctrl_dtr_rts` and `mhi_wwan_ctrl_stop` in `drivers/net/wwan/mhi_wwan_ctrl.c`. This is an MHI (Modem Host Interface) driver for Qualcomm-based PCIe modems (such as SDX24/SDX55/SDX65). It requires physical Qualcomm PCIe modem hardware and cannot be emulated or probed in standard virtualized fuzzing environments (QEMU/GCE), making the modified code structurally unreachable.",
"WorthFuzzing": false
} |
| 47/1 | 2026/10/28 01:55 | action | If |
0mArgs:{
"WorthFuzzing": false
}Results: null |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|