AI Trajectory


Trajectory: (Expand/Collapse All)
Seq Timestamp Type Name Duration
0/0 2026/07/13 08:03 flow patch-triage
1m Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch modifies the ath12k driver, which is a hardware-specific driver for Qualcomm Wi-Fi 7 devices. It requires a physical PCI or AHB device and complex firmware loading via MHI to function. It cannot be reached in virtualized environments like GCE or QEMU, even with software-emulated hardware like mac80211_hwsim.",
  "WorthFuzzing": false
}

1/1 2026/07/13 08:03 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 3d31ed18d419987169647c3b73bcb0cc005aa845\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Mon Jul 13 08:03:11 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c\nindex 0e7c732f822265..cf9c5b068fa671 100644\n--- a/drivers/net/wireless/ath/ath12k/core.c\n+++ b/drivers/net/wireless/ath/ath12k/core.c\n@@ -1547,6 +1547,8 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)\n \t\t}\n \n \t\twiphy_unlock(ah-\u003ehw-\u003ewiphy);\n+\n+\t\tcomplete(\u0026ah-\u003epeer_ml_id_done);\n \t}\n \n \twake_up(\u0026ab-\u003ewmi_ab.tx_credits_wq);\ndiff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h\nindex fc5127b5c1a37f..30726e580833e1 100644\n--- a/drivers/net/wireless/ath/ath12k/core.h\n+++ b/drivers/net/wireless/ath/ath12k/core.h\n@@ -72,6 +72,7 @@\n \n #define ATH12K_MAX_MLO_PEERS            256\n #define ATH12K_MLO_PEER_ID_INVALID      0xFFFF\n+#define ATH12K_MLO_PEER_ID_PENDING      0xFFFE\n \n #define ATH12K_INVALID_RSSI_FULL -1\n #define ATH12K_INVALID_RSSI_EMPTY -128\n@@ -793,6 +794,8 @@ struct ath12k_hw {\n \tenum ath12k_hw_state state;\n \tbool regd_updated;\n \tbool use_6ghz_regd;\n+\tbool host_alloc_ml_id;\n+\tstruct completion peer_ml_id_done;\n \n \tu8 num_radio;\n \ndiff --git a/drivers/net/wireless/ath/ath12k/dp_htt.c b/drivers/net/wireless/ath/ath12k/dp_htt.c\nindex 52e10059c6d5a8..68968f96b4f1b3 100644\n--- a/drivers/net/wireless/ath/ath12k/dp_htt.c\n+++ b/drivers/net/wireless/ath/ath12k/dp_htt.c\n@@ -6,6 +6,7 @@\n \n #include \"core.h\"\n #include \"peer.h\"\n+#include \"dp_peer.h\"\n #include \"htc.h\"\n #include \"dp_htt.h\"\n #include \"debugfs_htt_stats.h\"\n@@ -575,6 +576,51 @@ static void ath12k_htt_mlo_offset_event_handler(struct ath12k_base *ab,\n \trcu_read_unlock();\n }\n \n+static void ath12k_dp_htt_mlo_peer_map_handler(struct ath12k_base *ab,\n+\t\t\t\t\t       struct sk_buff *skb)\n+{\n+\tstruct htt_resp_msg *resp = (struct htt_resp_msg *)skb-\u003edata;\n+\tstruct htt_t2h_mlo_peer_map_event *ev = \u0026resp-\u003emlo_peer_map_ev;\n+\tu16 raw_peer_id, peer_id, addr_h16;\n+\tu8 peer_addr[ETH_ALEN];\n+\tint ret;\n+\n+\tif (skb-\u003elen \u003c sizeof(*ev)) {\n+\t\tath12k_warn(ab, \"unexpected htt mlo peer map event len %u\\n\",\n+\t\t\t    skb-\u003elen);\n+\t\treturn;\n+\t}\n+\n+\traw_peer_id = le32_get_bits(ev-\u003einfo0,\n+\t\t\t\t    HTT_T2H_MLO_PEER_MAP_INFO0_MLO_PEER_ID);\n+\tpeer_id = raw_peer_id | ATH12K_PEER_ML_ID_VALID;\n+\n+\taddr_h16 = le32_get_bits(ev-\u003einfo1,\n+\t\t\t\t HTT_T2H_MLO_PEER_MAP_INFO1_MAC_ADDR_H16);\n+\tath12k_dp_get_mac_addr(le32_to_cpu(ev-\u003emac_addr_l32), addr_h16,\n+\t\t\t       peer_addr);\n+\n+\tath12k_dbg(ab, ATH12K_DBG_DP_HTT, \"htt mlo peer map peer %pM id %u\\n\",\n+\t\t   peer_addr, peer_id);\n+\n+\t/*\n+\t * Fix up the dp_peer entry created with ATH12K_MLO_PEER_ID_PENDING\n+\t * earlier; on chips with host_alloc_ml_id == false this is the only\n+\t * point at which the host learns the firmware-assigned ID. Chips\n+\t * that allocate the ID on the host also receive this event but the\n+\t * firmware-reported ID matches the host-allocated one, so there is\n+\t * nothing to fix up.\n+\t */\n+\tif (!ab-\u003ehw_params-\u003ehost_alloc_ml_id) {\n+\t\tret = ath12k_dp_peer_fixup_peer_id(ab, peer_addr,\n+\t\t\t\t\t\t   peer_id);\n+\t\tif (ret)\n+\t\t\tath12k_warn(ab,\n+\t\t\t\t    \"failed to fix up peer id %u for dp peer %pM: %d\\n\",\n+\t\t\t\t    peer_id, peer_addr, ret);\n+\t}\n+}\n+\n void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,\n \t\t\t\t       struct sk_buff *skb)\n {\n@@ -659,6 +705,9 @@ void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,\n \tcase HTT_T2H_MSG_TYPE_MLO_TIMESTAMP_OFFSET_IND:\n \t\tath12k_htt_mlo_offset_event_handler(ab, skb);\n \t\tbreak;\n+\tcase HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP:\n+\t\tath12k_dp_htt_mlo_peer_map_handler(ab, skb);\n+\t\tbreak;\n \tdefault:\n \t\tath12k_dbg(ab, ATH12K_DBG_DP_HTT, \"dp_htt event %d not handled\\n\",\n \t\t\t   type);\ndiff --git a/drivers/net/wireless/ath/ath12k/dp_htt.h b/drivers/net/wireless/ath/ath12k/dp_htt.h\nindex 987689f11cda45..2db7fb27c03619 100644\n--- a/drivers/net/wireless/ath/ath12k/dp_htt.h\n+++ b/drivers/net/wireless/ath/ath12k/dp_htt.h\n@@ -930,6 +930,7 @@ enum htt_t2h_msg_type {\n \tHTT_T2H_MSG_TYPE_EXT_STATS_CONF = 0x1c,\n \tHTT_T2H_MSG_TYPE_BKPRESSURE_EVENT_IND = 0x24,\n \tHTT_T2H_MSG_TYPE_MLO_TIMESTAMP_OFFSET_IND = 0x28,\n+\tHTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP = 0x29,\n \tHTT_T2H_MSG_TYPE_PEER_MAP3\t= 0x2b,\n \tHTT_T2H_MSG_TYPE_VDEV_TXRX_STATS_PERIODIC_IND = 0x2c,\n };\n@@ -974,11 +975,22 @@ struct htt_t2h_peer_unmap_event {\n \t__le32 info1;\n } __packed;\n \n+#define HTT_T2H_MLO_PEER_MAP_INFO0_MLO_PEER_ID\t\tGENMASK(23, 8)\n+#define HTT_T2H_MLO_PEER_MAP_INFO1_MAC_ADDR_H16\t\tGENMASK(15, 0)\n+\n+struct htt_t2h_mlo_peer_map_event {\n+\t__le32 info0;\n+\t__le32 mac_addr_l32;\n+\t__le32 info1;\n+\t__le32 reserved[5];\n+} __packed;\n+\n struct htt_resp_msg {\n \tunion {\n \t\tstruct htt_t2h_version_conf_msg version_msg;\n \t\tstruct htt_t2h_peer_map_event peer_map_ev;\n \t\tstruct htt_t2h_peer_unmap_event peer_unmap_ev;\n+\t\tstruct htt_t2h_mlo_peer_map_event mlo_peer_map_ev;\n \t};\n } __packed;\n \ndiff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c\nindex 47d009a0d61fef..09142dcb74f98f 100644\n--- a/drivers/net/wireless/ath/ath12k/dp_peer.c\n+++ b/drivers/net/wireless/ath/ath12k/dp_peer.c\n@@ -472,7 +472,9 @@ int ath12k_dp_peer_create(struct ath12k_dp_hw *dp_hw, u8 *addr,\n \tdp_peer-\u003eis_mlo = params-\u003eis_mlo;\n \n \t/*\n-\t * For MLO client, the host assigns the ML peer ID, so set peer_id in dp_peer\n+\t * For MLO client, the ML peer ID, either known or PENDING, needs to be\n+\t * initialized here since the following logic depends on it.\n+\t *\n \t * For non-MLO client, host gets link peer ID from firmware and will be\n \t * assigned at the time of link peer creation\n \t */\n@@ -488,13 +490,17 @@ int ath12k_dp_peer_create(struct ath12k_dp_hw *dp_hw, u8 *addr,\n \tlist_add(\u0026dp_peer-\u003elist, \u0026dp_hw-\u003edp_peers_list);\n \n \t/*\n-\t * For MLO client, the peer_id for ath12k_dp_peer is allocated by host\n-\t * and that peer_id is known at this point, and hence this ath12k_dp_peer\n-\t * can be added to the RCU table using the peer_id.\n-\t * For non-MLO client, this addition to RCU table shall be done at the\n-\t * time of assignment of ath12k_dp_link_peer to ath12k_dp_peer.\n+\t * For an MLO client whose ML peer ID is allocated by the host, the\n+\t * peer_id is known here and the dp_peer can be added to the RCU\n+\t * table using it. For an MLO client on chips where the firmware\n+\t * allocates the ID, peer_id is ATH12K_MLO_PEER_ID_PENDING and the\n+\t * RCU table publish is deferred to the\n+\t * HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP handler. For a non-MLO client\n+\t * the publish happens later, at the time of assignment of\n+\t * ath12k_dp_link_peer to ath12k_dp_peer.\n \t */\n-\tif (dp_peer-\u003eis_mlo)\n+\tif (dp_peer-\u003eis_mlo \u0026\u0026\n+\t    dp_peer-\u003epeer_id != ATH12K_MLO_PEER_ID_PENDING)\n \t\trcu_assign_pointer(dp_hw-\u003edp_peers[dp_peer-\u003epeer_id], dp_peer);\n \n \tspin_unlock_bh(\u0026dp_hw-\u003epeer_lock);\n@@ -515,7 +521,8 @@ void ath12k_dp_peer_delete(struct ath12k_dp_hw *dp_hw, u8 *addr,\n \t\treturn;\n \t}\n \n-\tif (dp_peer-\u003eis_mlo)\n+\tif (dp_peer-\u003eis_mlo \u0026\u0026\n+\t    dp_peer-\u003epeer_id != ATH12K_MLO_PEER_ID_PENDING)\n \t\trcu_assign_pointer(dp_hw-\u003edp_peers[dp_peer-\u003epeer_id], NULL);\n \n \tlist_del(\u0026dp_peer-\u003elist);\n@@ -688,3 +695,55 @@ void ath12k_dp_link_peer_reset_rx_stats(struct ath12k_dp *dp, const u8 *addr)\n \tif (rx_stats)\n \t\tmemset(rx_stats, 0, sizeof(*rx_stats));\n }\n+\n+int ath12k_dp_peer_fixup_peer_id(struct ath12k_base *ab,\n+\t\t\t\t const u8 *peer_addr, u16 peer_id)\n+{\n+\tstruct ath12k_dp_link_peer *link_peer;\n+\tstruct ath12k_dp_peer *dp_peer = NULL;\n+\tstruct ath12k_hw_group *ag = ab-\u003eag;\n+\tstruct ath12k_dp_hw *dp_hw = NULL;\n+\tstruct ath12k_hw *ah;\n+\tint i;\n+\n+\tif (peer_id \u003e= (ATH12K_PEER_ML_ID_VALID | ATH12K_MAX_MLO_PEERS))\n+\t\treturn -EINVAL;\n+\n+\tfor (i = 0; i \u003c ag-\u003enum_hw; i++) {\n+\t\tah = ag-\u003eah[i];\n+\t\tif (!ah)\n+\t\t\tcontinue;\n+\n+\t\tspin_lock_bh(\u0026ah-\u003edp_hw.peer_lock);\n+\t\tdp_peer = ath12k_dp_peer_find_by_addr(\u0026ah-\u003edp_hw,\n+\t\t\t\t\t\t      (u8 *)peer_addr);\n+\t\tif (dp_peer) {\n+\t\t\tdp_hw = \u0026ah-\u003edp_hw;\n+\t\t\tbreak;\n+\t\t}\n+\t\tspin_unlock_bh(\u0026ah-\u003edp_hw.peer_lock);\n+\t}\n+\n+\tif (!dp_peer)\n+\t\treturn -ENOENT;\n+\n+\t/* dp_hw-\u003epeer_lock is held */\n+\n+\tdp_peer-\u003epeer_id = peer_id;\n+\trcu_assign_pointer(dp_hw-\u003edp_peers[peer_id], dp_peer);\n+\n+\tfor (i = 0; i \u003c ATH12K_NUM_MAX_LINKS; i++) {\n+\t\tlink_peer = rcu_dereference_protected(dp_peer-\u003elink_peers[i],\n+\t\t\t\t\t\t      lockdep_is_held(\u0026dp_hw-\u003epeer_lock));\n+\t\tif (link_peer)\n+\t\t\tlink_peer-\u003eml_id = peer_id;\n+\t}\n+\n+\tath12k_sta_to_ahsta(dp_peer-\u003esta)-\u003eml_peer_id = peer_id;\n+\n+\tspin_unlock_bh(\u0026dp_hw-\u003epeer_lock);\n+\n+\tcomplete(\u0026ah-\u003epeer_ml_id_done);\n+\n+\treturn 0;\n+}\ndiff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h\nindex f5067e66f1e182..9842671b547590 100644\n--- a/drivers/net/wireless/ath/ath12k/dp_peer.h\n+++ b/drivers/net/wireless/ath/ath12k/dp_peer.h\n@@ -180,4 +180,6 @@ struct ath12k_dp_peer *ath12k_dp_peer_find_by_peerid(struct ath12k_pdev_dp *dp_p\n struct ath12k_dp_link_peer *\n ath12k_dp_link_peer_find_by_peerid(struct ath12k_pdev_dp *dp_pdev, u16 peer_id);\n void ath12k_dp_link_peer_free(struct ath12k_dp_link_peer *peer);\n+int ath12k_dp_peer_fixup_peer_id(struct ath12k_base *ab, const u8 *peer_addr,\n+\t\t\t\t u16 peer_id);\n #endif\ndiff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h\nindex d135b29363788b..8091501cf742af 100644\n--- a/drivers/net/wireless/ath/ath12k/hw.h\n+++ b/drivers/net/wireless/ath/ath12k/hw.h\n@@ -232,6 +232,8 @@ struct ath12k_hw_params {\n \t\tu32 max_client_dbs;\n \t\tu32 max_client_dbs_sbs;\n \t} client;\n+\n+\tbool host_alloc_ml_id;\n };\n \n struct ath12k_hw_ops {\ndiff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c\nindex 490c134c1f290b..ae874114dc518f 100644\n--- a/drivers/net/wireless/ath/ath12k/mac.c\n+++ b/drivers/net/wireless/ath/ath12k/mac.c\n@@ -1278,13 +1278,17 @@ void ath12k_mac_dp_peer_cleanup(struct ath12k_hw *ah)\n \tstruct ath12k_dp_peer *dp_peer, *tmp;\n \tstruct ath12k_dp_hw *dp_hw = \u0026ah-\u003edp_hw;\n \n+\tlockdep_assert_wiphy(ah-\u003ehw-\u003ewiphy);\n+\n \tINIT_LIST_HEAD(\u0026peers);\n \n \tspin_lock_bh(\u0026dp_hw-\u003epeer_lock);\n \tlist_for_each_entry_safe(dp_peer, tmp, \u0026dp_hw-\u003edp_peers_list, list) {\n \t\tif (dp_peer-\u003eis_mlo) {\n-\t\t\trcu_assign_pointer(dp_hw-\u003edp_peers[dp_peer-\u003epeer_id], NULL);\n-\t\t\tclear_bit(dp_peer-\u003epeer_id, ah-\u003efree_ml_peer_id_map);\n+\t\t\tif (dp_peer-\u003epeer_id != ATH12K_MLO_PEER_ID_PENDING)\n+\t\t\t\trcu_assign_pointer(dp_hw-\u003edp_peers[dp_peer-\u003epeer_id],\n+\t\t\t\t\t\t   NULL);\n+\t\t\tath12k_peer_ml_free(ah, ath12k_sta_to_ahsta(dp_peer-\u003esta));\n \t\t}\n \n \t\tlist_move(\u0026dp_peer-\u003elist, \u0026peers);\n@@ -3527,11 +3531,16 @@ static void ath12k_peer_assoc_h_mlo(struct ath12k_link_sta *arsta,\n \tstruct ath12k_sta *ahsta = arsta-\u003eahsta;\n \tstruct ath12k_link_sta *arsta_p;\n \tstruct ath12k_link_vif *arvif;\n+\tstruct ath12k_hw *ah = arsta-\u003earvif-\u003ear-\u003eah;\n \tunsigned long links;\n \tu8 link_id;\n \tint i;\n \n-\tif (!sta-\u003emlo || ahsta-\u003eml_peer_id == ATH12K_MLO_PEER_ID_INVALID)\n+\tif (!sta-\u003emlo)\n+\t\treturn;\n+\n+\tif (ah-\u003ehost_alloc_ml_id \u0026\u0026\n+\t    ahsta-\u003eml_peer_id == ATH12K_MLO_PEER_ID_INVALID)\n \t\treturn;\n \n \tml-\u003eenabled = true;\n@@ -3539,12 +3548,25 @@ static void ath12k_peer_assoc_h_mlo(struct ath12k_link_sta *arsta,\n \n \t/* For now considering the primary umac based on assoc link */\n \tml-\u003eprimary_umac = arsta-\u003eis_assoc_link;\n-\tml-\u003epeer_id_valid = true;\n+\t/*\n+\t * Only chips that allocate the MLD peer ID on the host send a valid\n+\t * ml_peer_id in WMI_PEER_ASSOC_CMDID. For chips where the firmware\n+\t * picks the ID, leave peer_id_valid false to avoid unexpected issues.\n+\t */\n+\tml-\u003epeer_id_valid = ah-\u003ehost_alloc_ml_id;\n \tml-\u003elogical_link_idx_valid = true;\n \n \tether_addr_copy(ml-\u003emld_addr, sta-\u003eaddr);\n \tml-\u003elogical_link_idx = arsta-\u003elink_idx;\n-\tml-\u003eml_peer_id = ahsta-\u003eml_peer_id;\n+\t/*\n+\t * WMI_MLO_PEER_ASSOC_PARAMS expects the raw ML peer ID without\n+\t * the host-side ATH12K_PEER_ML_ID_VALID bookkeeping bit. For chips\n+\t * where the firmware allocates the ID, the field is unused (the\n+\t * firmware always allocates regardless of the value here); send 0\n+\t * to make that intent explicit.\n+\t */\n+\tml-\u003eml_peer_id = ah-\u003ehost_alloc_ml_id ?\n+\t\t\t (ahsta-\u003eml_peer_id \u0026 ~ATH12K_PEER_ML_ID_VALID) : 0;\n \tml-\u003eieee_link_id = arsta-\u003elink_id;\n \tml-\u003enum_partner_links = 0;\n \tml-\u003eeml_cap = sta-\u003eeml_cap;\n@@ -3591,8 +3613,6 @@ static void ath12k_peer_assoc_prepare(struct ath12k *ar,\n \n \tmemset(arg, 0, sizeof(*arg));\n \n-\treinit_completion(\u0026ar-\u003epeer_assoc_done);\n-\n \targ-\u003epeer_new_assoc = !reassoc;\n \tath12k_peer_assoc_h_basic(ar, arvif, arsta, arg);\n \tath12k_peer_assoc_h_crypto(ar, arvif, arsta, arg);\n@@ -3832,6 +3852,52 @@ static u32 ath12k_mac_ieee80211_sta_bw_to_wmi(struct ath12k *ar,\n \treturn bw;\n }\n \n+static int ath12k_mac_peer_assoc(struct ath12k *ar,\n+\t\t\t\t struct ath12k_wmi_peer_assoc_arg *peer_arg)\n+{\n+\tstruct ath12k_hw *ah = ath12k_ar_to_ah(ar);\n+\tint ret;\n+\n+\treinit_completion(\u0026ar-\u003epeer_assoc_done);\n+\treinit_completion(\u0026ah-\u003epeer_ml_id_done);\n+\n+\tret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);\n+\tif (ret) {\n+\t\tath12k_warn(ar-\u003eab, \"failed to run peer assoc for %pM vdev %i: %d\\n\",\n+\t\t\t    peer_arg-\u003epeer_mac, peer_arg-\u003evdev_id, ret);\n+\t\treturn ret;\n+\t}\n+\n+\tif (!wait_for_completion_timeout(\u0026ar-\u003epeer_assoc_done, 1 * HZ)) {\n+\t\tath12k_warn(ar-\u003eab, \"failed to get peer assoc conf event for %pM vdev %i\\n\",\n+\t\t\t    peer_arg-\u003epeer_mac, peer_arg-\u003evdev_id);\n+\t\treturn -ETIMEDOUT;\n+\t}\n+\n+\t/*\n+\t * For devices where the firmware allocates the MLD peer ID, the host\n+\t * learns the real ID only from the MLO_RX_PEER_MAP HTT event, which is\n+\t * handled in a softirq (BH workqueue) context that cannot take the\n+\t * wiphy lock. Block here, while still holding the wiphy lock, until\n+\t * that event has fixed up the ID. This serialises the fixup against\n+\t * all other wiphy-locked ml_peer_id accesses.\n+\t *\n+\t * The firmware sends the event only once, in response to the assoc-link\n+\t * peer assoc, so block only for that link.\n+\t */\n+\tif (!ah-\u003ehost_alloc_ml_id \u0026\u0026\n+\t    peer_arg-\u003eis_assoc \u0026\u0026\n+\t    peer_arg-\u003eml.enabled \u0026\u0026\n+\t    peer_arg-\u003eml.assoc_link \u0026\u0026\n+\t    !wait_for_completion_timeout(\u0026ah-\u003epeer_ml_id_done, 1 * HZ)) {\n+\t\tath12k_warn(ar-\u003eab, \"failed to get MLO peer map event for %pM vdev %i\\n\",\n+\t\t\t    peer_arg-\u003epeer_mac, peer_arg-\u003evdev_id);\n+\t\treturn -ETIMEDOUT;\n+\t}\n+\n+\treturn 0;\n+}\n+\n static void ath12k_bss_assoc(struct ath12k *ar,\n \t\t\t     struct ath12k_link_vif *arvif,\n \t\t\t     struct ieee80211_bss_conf *bss_conf)\n@@ -3912,18 +3978,10 @@ static void ath12k_bss_assoc(struct ath12k *ar,\n \t}\n \n \tpeer_arg-\u003eis_assoc = true;\n-\tret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);\n-\tif (ret) {\n-\t\tath12k_warn(ar-\u003eab, \"failed to run peer assoc for %pM vdev %i: %d\\n\",\n-\t\t\t    bss_conf-\u003ebssid, arvif-\u003evdev_id, ret);\n-\t\treturn;\n-\t}\n \n-\tif (!wait_for_completion_timeout(\u0026ar-\u003epeer_assoc_done, 1 * HZ)) {\n-\t\tath12k_warn(ar-\u003eab, \"failed to get peer assoc conf event for %pM vdev %i\\n\",\n-\t\t\t    bss_conf-\u003ebssid, arvif-\u003evdev_id);\n+\tret = ath12k_mac_peer_assoc(ar, peer_arg);\n+\tif (ret)\n \t\treturn;\n-\t}\n \n \tret = ath12k_setup_peer_smps(ar, arvif, bss_conf-\u003ebssid,\n \t\t\t\t     \u0026link_sta-\u003eht_cap, \u0026link_sta-\u003ehe_6ghz_capa);\n@@ -6477,18 +6535,10 @@ static int ath12k_mac_station_assoc(struct ath12k *ar,\n \t}\n \n \tpeer_arg-\u003eis_assoc = true;\n-\tret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);\n-\tif (ret) {\n-\t\tath12k_warn(ar-\u003eab, \"failed to run peer assoc for STA %pM vdev %i: %d\\n\",\n-\t\t\t    arsta-\u003eaddr, arvif-\u003evdev_id, ret);\n-\t\treturn ret;\n-\t}\n \n-\tif (!wait_for_completion_timeout(\u0026ar-\u003epeer_assoc_done, 1 * HZ)) {\n-\t\tath12k_warn(ar-\u003eab, \"failed to get peer assoc conf event for %pM vdev %i\\n\",\n-\t\t\t    arsta-\u003eaddr, arvif-\u003evdev_id);\n-\t\treturn -ETIMEDOUT;\n-\t}\n+\tret = ath12k_mac_peer_assoc(ar, peer_arg);\n+\tif (ret)\n+\t\treturn ret;\n \n \tnum_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask);\n \tnum_he_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask);\n@@ -6837,14 +6887,8 @@ static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk)\n \t\t\t\t\t\t  peer_arg, true);\n \n \t\t\tpeer_arg-\u003eis_assoc = false;\n-\t\t\terr = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);\n-\t\t\tif (err)\n-\t\t\t\tath12k_warn(ar-\u003eab, \"failed to run peer assoc for STA %pM vdev %i: %d\\n\",\n-\t\t\t\t\t    arsta-\u003eaddr, arvif-\u003evdev_id, err);\n \n-\t\t\tif (!wait_for_completion_timeout(\u0026ar-\u003epeer_assoc_done, 1 * HZ))\n-\t\t\t\tath12k_warn(ar-\u003eab, \"failed to get peer assoc conf event for %pM vdev %i\\n\",\n-\t\t\t\t\t    arsta-\u003eaddr, arvif-\u003evdev_id);\n+\t\t\tath12k_mac_peer_assoc(ar, peer_arg);\n \t\t}\n \t}\n }\n@@ -7262,10 +7306,8 @@ static void ath12k_mac_ml_station_remove(struct ath12k_vif *ahvif,\n \t\tath12k_mac_free_unassign_link_sta(ah, ahsta, link_id);\n \t}\n \n-\tif (sta-\u003emlo) {\n-\t\tclear_bit(ahsta-\u003eml_peer_id, ah-\u003efree_ml_peer_id_map);\n-\t\tahsta-\u003eml_peer_id = ATH12K_MLO_PEER_ID_INVALID;\n-\t}\n+\tif (sta-\u003emlo)\n+\t\tath12k_peer_ml_free(ah, ahsta);\n }\n \n static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw,\n@@ -7729,15 +7771,23 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,\n \t\t/* ML sta */\n \t\tif (sta-\u003emlo \u0026\u0026 !ahsta-\u003elinks_map \u0026\u0026\n \t\t    (hweight16(sta-\u003evalid_links) == 1)) {\n-\t\t\tahsta-\u003eml_peer_id = ath12k_peer_ml_alloc(ah);\n-\t\t\tif (ahsta-\u003eml_peer_id == ATH12K_MLO_PEER_ID_INVALID) {\n-\t\t\t\tath12k_hw_warn(ah, \"unable to allocate ML peer id for sta %pM\",\n-\t\t\t\t\t       sta-\u003eaddr);\n-\t\t\t\tgoto exit;\n+\t\t\tif (ah-\u003ehost_alloc_ml_id) {\n+\t\t\t\tahsta-\u003eml_peer_id = ath12k_peer_ml_alloc(ah);\n+\t\t\t\tif (ahsta-\u003eml_peer_id == ATH12K_MLO_PEER_ID_INVALID) {\n+\t\t\t\t\tath12k_hw_warn(ah, \"unable to allocate ML peer id for sta %pM\",\n+\t\t\t\t\t\t       sta-\u003eaddr);\n+\t\t\t\t\tgoto exit;\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\t/*\n+\t\t\t\t * firmware allocates the ML peer ID and notifies\n+\t\t\t\t * the host via HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP\n+\t\t\t\t */\n+\t\t\t\tahsta-\u003eml_peer_id = ATH12K_MLO_PEER_ID_PENDING;\n \t\t\t}\n \n \t\t\tdp_params.is_mlo = true;\n-\t\t\tdp_params.peer_id = ahsta-\u003eml_peer_id | ATH12K_PEER_ML_ID_VALID;\n+\t\t\tdp_params.peer_id = ahsta-\u003eml_peer_id;\n \t\t}\n \n \t\tdp_params.sta = sta;\n@@ -7874,10 +7924,8 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,\n peer_delete:\n \tath12k_dp_peer_delete(\u0026ah-\u003edp_hw, sta-\u003eaddr, sta);\n ml_peer_id_clear:\n-\tif (sta-\u003emlo) {\n-\t\tclear_bit(ahsta-\u003eml_peer_id, ah-\u003efree_ml_peer_id_map);\n-\t\tahsta-\u003eml_peer_id = ATH12K_MLO_PEER_ID_INVALID;\n-\t}\n+\tif (sta-\u003emlo)\n+\t\tath12k_peer_ml_free(ah, ahsta);\n exit:\n \t/* update the state if everything went well */\n \tif (!ret)\n@@ -15307,6 +15355,7 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_hw_group *ag,\n \tah-\u003enum_radio = num_pdev_map;\n \n \tmutex_init(\u0026ah-\u003ehw_mutex);\n+\tinit_completion(\u0026ah-\u003epeer_ml_id_done);\n \n \tspin_lock_init(\u0026ah-\u003edp_hw.peer_lock);\n \tINIT_LIST_HEAD(\u0026ah-\u003edp_hw.dp_peers_list);\n@@ -15381,8 +15430,9 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag)\n \tint mac_id, device_id, total_radio, num_hw;\n \tstruct ath12k_base *ab;\n \tstruct ath12k_hw *ah;\n-\tint ret, i, j;\n+\tbool conf = false;\n \tu8 radio_per_hw;\n+\tint ret, i, j;\n \n \ttotal_radio = 0;\n \tfor (i = 0; i \u003c ag-\u003enum_devices; i++) {\n@@ -15422,6 +15472,19 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag)\n \t\t\t}\n \n \t\t\tab = ag-\u003eab[device_id];\n+\n+\t\t\t/*\n+\t\t\t * the assumption is all devices within an ah\n+\t\t\t * share the same host_alloc_ml_id configuration\n+\t\t\t */\n+\t\t\tif (j == 0) {\n+\t\t\t\tconf = ab-\u003ehw_params-\u003ehost_alloc_ml_id;\n+\t\t\t} else if (conf != ab-\u003ehw_params-\u003ehost_alloc_ml_id) {\n+\t\t\t\tath12k_warn(ab, \"inconsistent ML ID config within ah, device 0 uses %s allocated ID, while device %u doesn't\\n\",\n+\t\t\t\t\t    conf ? \"host\" : \"firmware\", device_id);\n+\t\t\t\tgoto err;\n+\t\t\t}\n+\n \t\t\tpdev_map[j].ab = ab;\n \t\t\tpdev_map[j].pdev_idx = mac_id;\n \t\t\tmac_id++;\n@@ -15446,6 +15509,7 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag)\n \t\t}\n \n \t\tah-\u003edev = ab-\u003edev;\n+\t\tah-\u003ehost_alloc_ml_id = conf;\n \n \t\tag-\u003eah[i] = ah;\n \t\tag-\u003enum_hw++;\ndiff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c\nindex c222bdaa333c52..25e4b79f11d63b 100644\n--- a/drivers/net/wireless/ath/ath12k/peer.c\n+++ b/drivers/net/wireless/ath/ath12k/peer.c\n@@ -230,7 +230,16 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,\n \t\t/* Fill ML info into created peer */\n \t\tif (sta-\u003emlo) {\n \t\t\tml_peer_id = ahsta-\u003eml_peer_id;\n-\t\t\tpeer-\u003eml_id = ml_peer_id | ATH12K_PEER_ML_ID_VALID;\n+\t\t\t/*\n+\t\t\t * For chips where firmware allocates the ML peer ID,\n+\t\t\t * ml_peer_id is ATH12K_MLO_PEER_ID_PENDING here. The\n+\t\t\t * MLO_RX_PEER_MAP HTT event handler fixes up\n+\t\t\t * peer-\u003eml_id once the ID is known.\n+\t\t\t */\n+\t\t\tif (ml_peer_id == ATH12K_MLO_PEER_ID_PENDING)\n+\t\t\t\tpeer-\u003eml_id = ATH12K_MLO_PEER_ID_INVALID;\n+\t\t\telse\n+\t\t\t\tpeer-\u003eml_id = ml_peer_id;\n \t\t\tether_addr_copy(peer-\u003eml_addr, sta-\u003eaddr);\n \n \t\t\t/* the assoc link is considered primary for now */\n@@ -276,9 +285,25 @@ u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah)\n \t}\n \n \tif (ml_peer_id == ATH12K_MAX_MLO_PEERS)\n-\t\tml_peer_id = ATH12K_MLO_PEER_ID_INVALID;\n+\t\treturn ATH12K_MLO_PEER_ID_INVALID;\n \n-\treturn ml_peer_id;\n+\treturn ml_peer_id | ATH12K_PEER_ML_ID_VALID;\n+}\n+\n+void ath12k_peer_ml_free(struct ath12k_hw *ah, struct ath12k_sta *ahsta)\n+{\n+\tlockdep_assert_wiphy(ah-\u003ehw-\u003ewiphy);\n+\n+\t/*\n+\t * Only devices that allocate the ID on the host own a slot in\n+\t * free_ml_peer_id_map.\n+\t */\n+\tif (ah-\u003ehost_alloc_ml_id \u0026\u0026\n+\t    (ahsta-\u003eml_peer_id \u003c\n+\t     (ATH12K_MAX_MLO_PEERS | ATH12K_PEER_ML_ID_VALID)))\n+\t\tclear_bit(ahsta-\u003eml_peer_id \u0026 ~ATH12K_PEER_ML_ID_VALID,\n+\t\t\t  ah-\u003efree_ml_peer_id_map);\n+\tahsta-\u003eml_peer_id = ATH12K_MLO_PEER_ID_INVALID;\n }\n \n int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta)\ndiff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h\nindex 49d89796bc46e2..0f7f25b8e89c03 100644\n--- a/drivers/net/wireless/ath/ath12k/peer.h\n+++ b/drivers/net/wireless/ath/ath12k/peer.h\n@@ -26,4 +26,5 @@ int ath12k_link_sta_rhash_add(struct ath12k_base *ab, struct ath12k_link_sta *ar\n struct ath12k_link_sta *ath12k_link_sta_find_by_addr(struct ath12k_base *ab,\n \t\t\t\t\t\t     const u8 *addr);\n u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah);\n+void ath12k_peer_ml_free(struct ath12k_hw *ah, struct ath12k_sta *ahsta);\n #endif /* _PEER_H_ */\ndiff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c\nindex e5bf9d2181040d..0c277f51d99c1a 100644\n--- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c\n+++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c\n@@ -439,6 +439,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {\n \t\t\t.max_client_dbs = 128,\n \t\t\t.max_client_dbs_sbs = 128,\n \t\t},\n+\n+\t\t.host_alloc_ml_id = true,\n \t},\n \t{\n \t\t.name = \"wcn7850 hw2.0\",\n@@ -530,6 +532,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {\n \t\t\t.max_client_dbs = 128,\n \t\t\t.max_client_dbs_sbs = 128,\n \t\t},\n+\n+\t\t.host_alloc_ml_id = false,\n \t},\n \t{\n \t\t.name = \"qcn9274 hw2.0\",\n@@ -617,6 +621,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {\n \t\t\t.max_client_dbs = 128,\n \t\t\t.max_client_dbs_sbs = 128,\n \t\t},\n+\n+\t\t.host_alloc_ml_id = true,\n \t},\n \t{\n \t\t.name = \"ipq5332 hw1.0\",\n@@ -697,6 +703,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {\n \t\t\t.max_client_dbs = 128,\n \t\t\t.max_client_dbs_sbs = 128,\n \t\t},\n+\n+\t\t.host_alloc_ml_id = true,\n \t},\n \t{\n \t\t.name = \"qcc2072 hw1.0\",\n@@ -789,6 +797,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {\n \t\t\t.max_client_dbs = 128,\n \t\t\t.max_client_dbs_sbs = 128,\n \t\t},\n+\n+\t\t.host_alloc_ml_id = false,\n \t},\n \t{\n \t\t.name = \"ipq5424 hw1.0\",\n@@ -873,6 +883,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {\n \t\t\t.max_client_dbs = 128,\n \t\t\t.max_client_dbs_sbs = 128,\n \t\t},\n+\n+\t\t.host_alloc_ml_id = true,\n \t},\n };\n \n"
}

2/1 2026/07/13 08:03 agent patch-evaluator
1m Model:
gemini-3.1-pro-preview

Args:
null

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch modifies the ath12k driver, which is a hardware-specific driver for Qualcomm Wi-Fi 7 devices. It requires a physical PCI or AHB device and complex firmware loading via MHI to function. It cannot be reached in virtualized environments like GCE or QEMU, even with software-emulated hardware like mac80211_hwsim.",
  "WorthFuzzing": false
}

Instruction:
You are an expert Linux kernel maintainer.
Your job is to review a provided patch series and determine
if it makes functional changes to the kernel that should be fuzzed.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively
use your code access tools to examine the actual source code and confirm any assumptions.

Return WorthFuzzing=false if the patch only contains:
- Modifications to Documentation/, Kconfig files, or code comments.
- Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints.
- Changes to numeric constants or macros that do not functionally alter execution flow.
- Code paths that are impossible to reach in virtualized environments like GCE or QEMU,
even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim).

If it modifies reachable core kernel logic, drivers, or architectures, use your code search
tools to verify the code can be executed, then return WorthFuzzing=true.

When returning WorthFuzzing=true, you MUST ALSO:
1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols.
   Avoid listing generic hot-path functions to prevent skewed test distributions.
2. Identify any specific CONFIG_ options required to properly test this new/modified feature.
   Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions.
   Do not list too generic configs (we already have them enabled). Only list those that
   specifically cover the modified code. List them in the EnableConfigs output array,
   and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.

Prompt:
For your convenience, here is the diff of the changes:
commit 3d31ed18d419987169647c3b73bcb0cc005aa845
Author: syz-cluster <triage@syzkaller.com>
Date:   Mon Jul 13 08:03:11 2026 +0000

    syz-cluster: applied patch under review

diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index 0e7c732f822265..cf9c5b068fa671 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -1547,6 +1547,8 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
 		}
 
 		wiphy_unlock(ah->hw->wiphy);
+
+		complete(&ah->peer_ml_id_done);
 	}
 
 	wake_up(&ab->wmi_ab.tx_credits_wq);
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index fc5127b5c1a37f..30726e580833e1 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -72,6 +72,7 @@
 
 #define ATH12K_MAX_MLO_PEERS            256
 #define ATH12K_MLO_PEER_ID_INVALID      0xFFFF
+#define ATH12K_MLO_PEER_ID_PENDING      0xFFFE
 
 #define ATH12K_INVALID_RSSI_FULL -1
 #define ATH12K_INVALID_RSSI_EMPTY -128
@@ -793,6 +794,8 @@ struct ath12k_hw {
 	enum ath12k_hw_state state;
 	bool regd_updated;
 	bool use_6ghz_regd;
+	bool host_alloc_ml_id;
+	struct completion peer_ml_id_done;
 
 	u8 num_radio;
 
diff --git a/drivers/net/wireless/ath/ath12k/dp_htt.c b/drivers/net/wireless/ath/ath12k/dp_htt.c
index 52e10059c6d5a8..68968f96b4f1b3 100644
--- a/drivers/net/wireless/ath/ath12k/dp_htt.c
+++ b/drivers/net/wireless/ath/ath12k/dp_htt.c
@@ -6,6 +6,7 @@
 
 #include "core.h"
 #include "peer.h"
+#include "dp_peer.h"
 #include "htc.h"
 #include "dp_htt.h"
 #include "debugfs_htt_stats.h"
@@ -575,6 +576,51 @@ static void ath12k_htt_mlo_offset_event_handler(struct ath12k_base *ab,
 	rcu_read_unlock();
 }
 
+static void ath12k_dp_htt_mlo_peer_map_handler(struct ath12k_base *ab,
+					       struct sk_buff *skb)
+{
+	struct htt_resp_msg *resp = (struct htt_resp_msg *)skb->data;
+	struct htt_t2h_mlo_peer_map_event *ev = &resp->mlo_peer_map_ev;
+	u16 raw_peer_id, peer_id, addr_h16;
+	u8 peer_addr[ETH_ALEN];
+	int ret;
+
+	if (skb->len < sizeof(*ev)) {
+		ath12k_warn(ab, "unexpected htt mlo peer map event len %u\n",
+			    skb->len);
+		return;
+	}
+
+	raw_peer_id = le32_get_bits(ev->info0,
+				    HTT_T2H_MLO_PEER_MAP_INFO0_MLO_PEER_ID);
+	peer_id = raw_peer_id | ATH12K_PEER_ML_ID_VALID;
+
+	addr_h16 = le32_get_bits(ev->info1,
+				 HTT_T2H_MLO_PEER_MAP_INFO1_MAC_ADDR_H16);
+	ath12k_dp_get_mac_addr(le32_to_cpu(ev->mac_addr_l32), addr_h16,
+			       peer_addr);
+
+	ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "htt mlo peer map peer %pM id %u\n",
+		   peer_addr, peer_id);
+
+	/*
+	 * Fix up the dp_peer entry created with ATH12K_MLO_PEER_ID_PENDING
+	 * earlier; on chips with host_alloc_ml_id == false this is the only
+	 * point at which the host learns the firmware-assigned ID. Chips
+	 * that allocate the ID on the host also receive this event but the
+	 * firmware-reported ID matches the host-allocated one, so there is
+	 * nothing to fix up.
+	 */
+	if (!ab->hw_params->host_alloc_ml_id) {
+		ret = ath12k_dp_peer_fixup_peer_id(ab, peer_addr,
+						   peer_id);
+		if (ret)
+			ath12k_warn(ab,
+				    "failed to fix up peer id %u for dp peer %pM: %d\n",
+				    peer_id, peer_addr, ret);
+	}
+}
+
 void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,
 				       struct sk_buff *skb)
 {
@@ -659,6 +705,9 @@ void ath12k_dp_htt_htc_t2h_msg_handler(struct ath12k_base *ab,
 	case HTT_T2H_MSG_TYPE_MLO_TIMESTAMP_OFFSET_IND:
 		ath12k_htt_mlo_offset_event_handler(ab, skb);
 		break;
+	case HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP:
+		ath12k_dp_htt_mlo_peer_map_handler(ab, skb);
+		break;
 	default:
 		ath12k_dbg(ab, ATH12K_DBG_DP_HTT, "dp_htt event %d not handled\n",
 			   type);
diff --git a/drivers/net/wireless/ath/ath12k/dp_htt.h b/drivers/net/wireless/ath/ath12k/dp_htt.h
index 987689f11cda45..2db7fb27c03619 100644
--- a/drivers/net/wireless/ath/ath12k/dp_htt.h
+++ b/drivers/net/wireless/ath/ath12k/dp_htt.h
@@ -930,6 +930,7 @@ enum htt_t2h_msg_type {
 	HTT_T2H_MSG_TYPE_EXT_STATS_CONF = 0x1c,
 	HTT_T2H_MSG_TYPE_BKPRESSURE_EVENT_IND = 0x24,
 	HTT_T2H_MSG_TYPE_MLO_TIMESTAMP_OFFSET_IND = 0x28,
+	HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP = 0x29,
 	HTT_T2H_MSG_TYPE_PEER_MAP3	= 0x2b,
 	HTT_T2H_MSG_TYPE_VDEV_TXRX_STATS_PERIODIC_IND = 0x2c,
 };
@@ -974,11 +975,22 @@ struct htt_t2h_peer_unmap_event {
 	__le32 info1;
 } __packed;
 
+#define HTT_T2H_MLO_PEER_MAP_INFO0_MLO_PEER_ID		GENMASK(23, 8)
+#define HTT_T2H_MLO_PEER_MAP_INFO1_MAC_ADDR_H16		GENMASK(15, 0)
+
+struct htt_t2h_mlo_peer_map_event {
+	__le32 info0;
+	__le32 mac_addr_l32;
+	__le32 info1;
+	__le32 reserved[5];
+} __packed;
+
 struct htt_resp_msg {
 	union {
 		struct htt_t2h_version_conf_msg version_msg;
 		struct htt_t2h_peer_map_event peer_map_ev;
 		struct htt_t2h_peer_unmap_event peer_unmap_ev;
+		struct htt_t2h_mlo_peer_map_event mlo_peer_map_ev;
 	};
 } __packed;
 
diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.c b/drivers/net/wireless/ath/ath12k/dp_peer.c
index 47d009a0d61fef..09142dcb74f98f 100644
--- a/drivers/net/wireless/ath/ath12k/dp_peer.c
+++ b/drivers/net/wireless/ath/ath12k/dp_peer.c
@@ -472,7 +472,9 @@ int ath12k_dp_peer_create(struct ath12k_dp_hw *dp_hw, u8 *addr,
 	dp_peer->is_mlo = params->is_mlo;
 
 	/*
-	 * For MLO client, the host assigns the ML peer ID, so set peer_id in dp_peer
+	 * For MLO client, the ML peer ID, either known or PENDING, needs to be
+	 * initialized here since the following logic depends on it.
+	 *
 	 * For non-MLO client, host gets link peer ID from firmware and will be
 	 * assigned at the time of link peer creation
 	 */
@@ -488,13 +490,17 @@ int ath12k_dp_peer_create(struct ath12k_dp_hw *dp_hw, u8 *addr,
 	list_add(&dp_peer->list, &dp_hw->dp_peers_list);
 
 	/*
-	 * For MLO client, the peer_id for ath12k_dp_peer is allocated by host
-	 * and that peer_id is known at this point, and hence this ath12k_dp_peer
-	 * can be added to the RCU table using the peer_id.
-	 * For non-MLO client, this addition to RCU table shall be done at the
-	 * time of assignment of ath12k_dp_link_peer to ath12k_dp_peer.
+	 * For an MLO client whose ML peer ID is allocated by the host, the
+	 * peer_id is known here and the dp_peer can be added to the RCU
+	 * table using it. For an MLO client on chips where the firmware
+	 * allocates the ID, peer_id is ATH12K_MLO_PEER_ID_PENDING and the
+	 * RCU table publish is deferred to the
+	 * HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP handler. For a non-MLO client
+	 * the publish happens later, at the time of assignment of
+	 * ath12k_dp_link_peer to ath12k_dp_peer.
 	 */
-	if (dp_peer->is_mlo)
+	if (dp_peer->is_mlo &&
+	    dp_peer->peer_id != ATH12K_MLO_PEER_ID_PENDING)
 		rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], dp_peer);
 
 	spin_unlock_bh(&dp_hw->peer_lock);
@@ -515,7 +521,8 @@ void ath12k_dp_peer_delete(struct ath12k_dp_hw *dp_hw, u8 *addr,
 		return;
 	}
 
-	if (dp_peer->is_mlo)
+	if (dp_peer->is_mlo &&
+	    dp_peer->peer_id != ATH12K_MLO_PEER_ID_PENDING)
 		rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], NULL);
 
 	list_del(&dp_peer->list);
@@ -688,3 +695,55 @@ void ath12k_dp_link_peer_reset_rx_stats(struct ath12k_dp *dp, const u8 *addr)
 	if (rx_stats)
 		memset(rx_stats, 0, sizeof(*rx_stats));
 }
+
+int ath12k_dp_peer_fixup_peer_id(struct ath12k_base *ab,
+				 const u8 *peer_addr, u16 peer_id)
+{
+	struct ath12k_dp_link_peer *link_peer;
+	struct ath12k_dp_peer *dp_peer = NULL;
+	struct ath12k_hw_group *ag = ab->ag;
+	struct ath12k_dp_hw *dp_hw = NULL;
+	struct ath12k_hw *ah;
+	int i;
+
+	if (peer_id >= (ATH12K_PEER_ML_ID_VALID | ATH12K_MAX_MLO_PEERS))
+		return -EINVAL;
+
+	for (i = 0; i < ag->num_hw; i++) {
+		ah = ag->ah[i];
+		if (!ah)
+			continue;
+
+		spin_lock_bh(&ah->dp_hw.peer_lock);
+		dp_peer = ath12k_dp_peer_find_by_addr(&ah->dp_hw,
+						      (u8 *)peer_addr);
+		if (dp_peer) {
+			dp_hw = &ah->dp_hw;
+			break;
+		}
+		spin_unlock_bh(&ah->dp_hw.peer_lock);
+	}
+
+	if (!dp_peer)
+		return -ENOENT;
+
+	/* dp_hw->peer_lock is held */
+
+	dp_peer->peer_id = peer_id;
+	rcu_assign_pointer(dp_hw->dp_peers[peer_id], dp_peer);
+
+	for (i = 0; i < ATH12K_NUM_MAX_LINKS; i++) {
+		link_peer = rcu_dereference_protected(dp_peer->link_peers[i],
+						      lockdep_is_held(&dp_hw->peer_lock));
+		if (link_peer)
+			link_peer->ml_id = peer_id;
+	}
+
+	ath12k_sta_to_ahsta(dp_peer->sta)->ml_peer_id = peer_id;
+
+	spin_unlock_bh(&dp_hw->peer_lock);
+
+	complete(&ah->peer_ml_id_done);
+
+	return 0;
+}
diff --git a/drivers/net/wireless/ath/ath12k/dp_peer.h b/drivers/net/wireless/ath/ath12k/dp_peer.h
index f5067e66f1e182..9842671b547590 100644
--- a/drivers/net/wireless/ath/ath12k/dp_peer.h
+++ b/drivers/net/wireless/ath/ath12k/dp_peer.h
@@ -180,4 +180,6 @@ struct ath12k_dp_peer *ath12k_dp_peer_find_by_peerid(struct ath12k_pdev_dp *dp_p
 struct ath12k_dp_link_peer *
 ath12k_dp_link_peer_find_by_peerid(struct ath12k_pdev_dp *dp_pdev, u16 peer_id);
 void ath12k_dp_link_peer_free(struct ath12k_dp_link_peer *peer);
+int ath12k_dp_peer_fixup_peer_id(struct ath12k_base *ab, const u8 *peer_addr,
+				 u16 peer_id);
 #endif
diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h
index d135b29363788b..8091501cf742af 100644
--- a/drivers/net/wireless/ath/ath12k/hw.h
+++ b/drivers/net/wireless/ath/ath12k/hw.h
@@ -232,6 +232,8 @@ struct ath12k_hw_params {
 		u32 max_client_dbs;
 		u32 max_client_dbs_sbs;
 	} client;
+
+	bool host_alloc_ml_id;
 };
 
 struct ath12k_hw_ops {
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 490c134c1f290b..ae874114dc518f 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -1278,13 +1278,17 @@ void ath12k_mac_dp_peer_cleanup(struct ath12k_hw *ah)
 	struct ath12k_dp_peer *dp_peer, *tmp;
 	struct ath12k_dp_hw *dp_hw = &ah->dp_hw;
 
+	lockdep_assert_wiphy(ah->hw->wiphy);
+
 	INIT_LIST_HEAD(&peers);
 
 	spin_lock_bh(&dp_hw->peer_lock);
 	list_for_each_entry_safe(dp_peer, tmp, &dp_hw->dp_peers_list, list) {
 		if (dp_peer->is_mlo) {
-			rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id], NULL);
-			clear_bit(dp_peer->peer_id, ah->free_ml_peer_id_map);
+			if (dp_peer->peer_id != ATH12K_MLO_PEER_ID_PENDING)
+				rcu_assign_pointer(dp_hw->dp_peers[dp_peer->peer_id],
+						   NULL);
+			ath12k_peer_ml_free(ah, ath12k_sta_to_ahsta(dp_peer->sta));
 		}
 
 		list_move(&dp_peer->list, &peers);
@@ -3527,11 +3531,16 @@ static void ath12k_peer_assoc_h_mlo(struct ath12k_link_sta *arsta,
 	struct ath12k_sta *ahsta = arsta->ahsta;
 	struct ath12k_link_sta *arsta_p;
 	struct ath12k_link_vif *arvif;
+	struct ath12k_hw *ah = arsta->arvif->ar->ah;
 	unsigned long links;
 	u8 link_id;
 	int i;
 
-	if (!sta->mlo || ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID)
+	if (!sta->mlo)
+		return;
+
+	if (ah->host_alloc_ml_id &&
+	    ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID)
 		return;
 
 	ml->enabled = true;
@@ -3539,12 +3548,25 @@ static void ath12k_peer_assoc_h_mlo(struct ath12k_link_sta *arsta,
 
 	/* For now considering the primary umac based on assoc link */
 	ml->primary_umac = arsta->is_assoc_link;
-	ml->peer_id_valid = true;
+	/*
+	 * Only chips that allocate the MLD peer ID on the host send a valid
+	 * ml_peer_id in WMI_PEER_ASSOC_CMDID. For chips where the firmware
+	 * picks the ID, leave peer_id_valid false to avoid unexpected issues.
+	 */
+	ml->peer_id_valid = ah->host_alloc_ml_id;
 	ml->logical_link_idx_valid = true;
 
 	ether_addr_copy(ml->mld_addr, sta->addr);
 	ml->logical_link_idx = arsta->link_idx;
-	ml->ml_peer_id = ahsta->ml_peer_id;
+	/*
+	 * WMI_MLO_PEER_ASSOC_PARAMS expects the raw ML peer ID without
+	 * the host-side ATH12K_PEER_ML_ID_VALID bookkeeping bit. For chips
+	 * where the firmware allocates the ID, the field is unused (the
+	 * firmware always allocates regardless of the value here); send 0
+	 * to make that intent explicit.
+	 */
+	ml->ml_peer_id = ah->host_alloc_ml_id ?
+			 (ahsta->ml_peer_id & ~ATH12K_PEER_ML_ID_VALID) : 0;
 	ml->ieee_link_id = arsta->link_id;
 	ml->num_partner_links = 0;
 	ml->eml_cap = sta->eml_cap;
@@ -3591,8 +3613,6 @@ static void ath12k_peer_assoc_prepare(struct ath12k *ar,
 
 	memset(arg, 0, sizeof(*arg));
 
-	reinit_completion(&ar->peer_assoc_done);
-
 	arg->peer_new_assoc = !reassoc;
 	ath12k_peer_assoc_h_basic(ar, arvif, arsta, arg);
 	ath12k_peer_assoc_h_crypto(ar, arvif, arsta, arg);
@@ -3832,6 +3852,52 @@ static u32 ath12k_mac_ieee80211_sta_bw_to_wmi(struct ath12k *ar,
 	return bw;
 }
 
+static int ath12k_mac_peer_assoc(struct ath12k *ar,
+				 struct ath12k_wmi_peer_assoc_arg *peer_arg)
+{
+	struct ath12k_hw *ah = ath12k_ar_to_ah(ar);
+	int ret;
+
+	reinit_completion(&ar->peer_assoc_done);
+	reinit_completion(&ah->peer_ml_id_done);
+
+	ret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);
+	if (ret) {
+		ath12k_warn(ar->ab, "failed to run peer assoc for %pM vdev %i: %d\n",
+			    peer_arg->peer_mac, peer_arg->vdev_id, ret);
+		return ret;
+	}
+
+	if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
+		ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
+			    peer_arg->peer_mac, peer_arg->vdev_id);
+		return -ETIMEDOUT;
+	}
+
+	/*
+	 * For devices where the firmware allocates the MLD peer ID, the host
+	 * learns the real ID only from the MLO_RX_PEER_MAP HTT event, which is
+	 * handled in a softirq (BH workqueue) context that cannot take the
+	 * wiphy lock. Block here, while still holding the wiphy lock, until
+	 * that event has fixed up the ID. This serialises the fixup against
+	 * all other wiphy-locked ml_peer_id accesses.
+	 *
+	 * The firmware sends the event only once, in response to the assoc-link
+	 * peer assoc, so block only for that link.
+	 */
+	if (!ah->host_alloc_ml_id &&
+	    peer_arg->is_assoc &&
+	    peer_arg->ml.enabled &&
+	    peer_arg->ml.assoc_link &&
+	    !wait_for_completion_timeout(&ah->peer_ml_id_done, 1 * HZ)) {
+		ath12k_warn(ar->ab, "failed to get MLO peer map event for %pM vdev %i\n",
+			    peer_arg->peer_mac, peer_arg->vdev_id);
+		return -ETIMEDOUT;
+	}
+
+	return 0;
+}
+
 static void ath12k_bss_assoc(struct ath12k *ar,
 			     struct ath12k_link_vif *arvif,
 			     struct ieee80211_bss_conf *bss_conf)
@@ -3912,18 +3978,10 @@ static void ath12k_bss_assoc(struct ath12k *ar,
 	}
 
 	peer_arg->is_assoc = true;
-	ret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);
-	if (ret) {
-		ath12k_warn(ar->ab, "failed to run peer assoc for %pM vdev %i: %d\n",
-			    bss_conf->bssid, arvif->vdev_id, ret);
-		return;
-	}
 
-	if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
-		ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
-			    bss_conf->bssid, arvif->vdev_id);
+	ret = ath12k_mac_peer_assoc(ar, peer_arg);
+	if (ret)
 		return;
-	}
 
 	ret = ath12k_setup_peer_smps(ar, arvif, bss_conf->bssid,
 				     &link_sta->ht_cap, &link_sta->he_6ghz_capa);
@@ -6477,18 +6535,10 @@ static int ath12k_mac_station_assoc(struct ath12k *ar,
 	}
 
 	peer_arg->is_assoc = true;
-	ret = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);
-	if (ret) {
-		ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
-			    arsta->addr, arvif->vdev_id, ret);
-		return ret;
-	}
 
-	if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ)) {
-		ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
-			    arsta->addr, arvif->vdev_id);
-		return -ETIMEDOUT;
-	}
+	ret = ath12k_mac_peer_assoc(ar, peer_arg);
+	if (ret)
+		return ret;
 
 	num_vht_rates = ath12k_mac_bitrate_mask_num_vht_rates(ar, band, mask);
 	num_he_rates = ath12k_mac_bitrate_mask_num_he_rates(ar, band, mask);
@@ -6837,14 +6887,8 @@ static void ath12k_sta_rc_update_wk(struct wiphy *wiphy, struct wiphy_work *wk)
 						  peer_arg, true);
 
 			peer_arg->is_assoc = false;
-			err = ath12k_wmi_send_peer_assoc_cmd(ar, peer_arg);
-			if (err)
-				ath12k_warn(ar->ab, "failed to run peer assoc for STA %pM vdev %i: %d\n",
-					    arsta->addr, arvif->vdev_id, err);
 
-			if (!wait_for_completion_timeout(&ar->peer_assoc_done, 1 * HZ))
-				ath12k_warn(ar->ab, "failed to get peer assoc conf event for %pM vdev %i\n",
-					    arsta->addr, arvif->vdev_id);
+			ath12k_mac_peer_assoc(ar, peer_arg);
 		}
 	}
 }
@@ -7262,10 +7306,8 @@ static void ath12k_mac_ml_station_remove(struct ath12k_vif *ahvif,
 		ath12k_mac_free_unassign_link_sta(ah, ahsta, link_id);
 	}
 
-	if (sta->mlo) {
-		clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map);
-		ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
-	}
+	if (sta->mlo)
+		ath12k_peer_ml_free(ah, ahsta);
 }
 
 static int ath12k_mac_handle_link_sta_state(struct ieee80211_hw *hw,
@@ -7729,15 +7771,23 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
 		/* ML sta */
 		if (sta->mlo && !ahsta->links_map &&
 		    (hweight16(sta->valid_links) == 1)) {
-			ahsta->ml_peer_id = ath12k_peer_ml_alloc(ah);
-			if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) {
-				ath12k_hw_warn(ah, "unable to allocate ML peer id for sta %pM",
-					       sta->addr);
-				goto exit;
+			if (ah->host_alloc_ml_id) {
+				ahsta->ml_peer_id = ath12k_peer_ml_alloc(ah);
+				if (ahsta->ml_peer_id == ATH12K_MLO_PEER_ID_INVALID) {
+					ath12k_hw_warn(ah, "unable to allocate ML peer id for sta %pM",
+						       sta->addr);
+					goto exit;
+				}
+			} else {
+				/*
+				 * firmware allocates the ML peer ID and notifies
+				 * the host via HTT_T2H_MSG_TYPE_MLO_RX_PEER_MAP
+				 */
+				ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_PENDING;
 			}
 
 			dp_params.is_mlo = true;
-			dp_params.peer_id = ahsta->ml_peer_id | ATH12K_PEER_ML_ID_VALID;
+			dp_params.peer_id = ahsta->ml_peer_id;
 		}
 
 		dp_params.sta = sta;
@@ -7874,10 +7924,8 @@ int ath12k_mac_op_sta_state(struct ieee80211_hw *hw,
 peer_delete:
 	ath12k_dp_peer_delete(&ah->dp_hw, sta->addr, sta);
 ml_peer_id_clear:
-	if (sta->mlo) {
-		clear_bit(ahsta->ml_peer_id, ah->free_ml_peer_id_map);
-		ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
-	}
+	if (sta->mlo)
+		ath12k_peer_ml_free(ah, ahsta);
 exit:
 	/* update the state if everything went well */
 	if (!ret)
@@ -15307,6 +15355,7 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_hw_group *ag,
 	ah->num_radio = num_pdev_map;
 
 	mutex_init(&ah->hw_mutex);
+	init_completion(&ah->peer_ml_id_done);
 
 	spin_lock_init(&ah->dp_hw.peer_lock);
 	INIT_LIST_HEAD(&ah->dp_hw.dp_peers_list);
@@ -15381,8 +15430,9 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag)
 	int mac_id, device_id, total_radio, num_hw;
 	struct ath12k_base *ab;
 	struct ath12k_hw *ah;
-	int ret, i, j;
+	bool conf = false;
 	u8 radio_per_hw;
+	int ret, i, j;
 
 	total_radio = 0;
 	for (i = 0; i < ag->num_devices; i++) {
@@ -15422,6 +15472,19 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag)
 			}
 
 			ab = ag->ab[device_id];
+
+			/*
+			 * the assumption is all devices within an ah
+			 * share the same host_alloc_ml_id configuration
+			 */
+			if (j == 0) {
+				conf = ab->hw_params->host_alloc_ml_id;
+			} else if (conf != ab->hw_params->host_alloc_ml_id) {
+				ath12k_warn(ab, "inconsistent ML ID config within ah, device 0 uses %s allocated ID, while device %u doesn't\n",
+					    conf ? "host" : "firmware", device_id);
+				goto err;
+			}
+
 			pdev_map[j].ab = ab;
 			pdev_map[j].pdev_idx = mac_id;
 			mac_id++;
@@ -15446,6 +15509,7 @@ int ath12k_mac_allocate(struct ath12k_hw_group *ag)
 		}
 
 		ah->dev = ab->dev;
+		ah->host_alloc_ml_id = conf;
 
 		ag->ah[i] = ah;
 		ag->num_hw++;
diff --git a/drivers/net/wireless/ath/ath12k/peer.c b/drivers/net/wireless/ath/ath12k/peer.c
index c222bdaa333c52..25e4b79f11d63b 100644
--- a/drivers/net/wireless/ath/ath12k/peer.c
+++ b/drivers/net/wireless/ath/ath12k/peer.c
@@ -230,7 +230,16 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_link_vif *arvif,
 		/* Fill ML info into created peer */
 		if (sta->mlo) {
 			ml_peer_id = ahsta->ml_peer_id;
-			peer->ml_id = ml_peer_id | ATH12K_PEER_ML_ID_VALID;
+			/*
+			 * For chips where firmware allocates the ML peer ID,
+			 * ml_peer_id is ATH12K_MLO_PEER_ID_PENDING here. The
+			 * MLO_RX_PEER_MAP HTT event handler fixes up
+			 * peer->ml_id once the ID is known.
+			 */
+			if (ml_peer_id == ATH12K_MLO_PEER_ID_PENDING)
+				peer->ml_id = ATH12K_MLO_PEER_ID_INVALID;
+			else
+				peer->ml_id = ml_peer_id;
 			ether_addr_copy(peer->ml_addr, sta->addr);
 
 			/* the assoc link is considered primary for now */
@@ -276,9 +285,25 @@ u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah)
 	}
 
 	if (ml_peer_id == ATH12K_MAX_MLO_PEERS)
-		ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
+		return ATH12K_MLO_PEER_ID_INVALID;
 
-	return ml_peer_id;
+	return ml_peer_id | ATH12K_PEER_ML_ID_VALID;
+}
+
+void ath12k_peer_ml_free(struct ath12k_hw *ah, struct ath12k_sta *ahsta)
+{
+	lockdep_assert_wiphy(ah->hw->wiphy);
+
+	/*
+	 * Only devices that allocate the ID on the host own a slot in
+	 * free_ml_peer_id_map.
+	 */
+	if (ah->host_alloc_ml_id &&
+	    (ahsta->ml_peer_id <
+	     (ATH12K_MAX_MLO_PEERS | ATH12K_PEER_ML_ID_VALID)))
+		clear_bit(ahsta->ml_peer_id & ~ATH12K_PEER_ML_ID_VALID,
+			  ah->free_ml_peer_id_map);
+	ahsta->ml_peer_id = ATH12K_MLO_PEER_ID_INVALID;
 }
 
 int ath12k_peer_mlo_link_peers_delete(struct ath12k_vif *ahvif, struct ath12k_sta *ahsta)
diff --git a/drivers/net/wireless/ath/ath12k/peer.h b/drivers/net/wireless/ath/ath12k/peer.h
index 49d89796bc46e2..0f7f25b8e89c03 100644
--- a/drivers/net/wireless/ath/ath12k/peer.h
+++ b/drivers/net/wireless/ath/ath12k/peer.h
@@ -26,4 +26,5 @@ int ath12k_link_sta_rhash_add(struct ath12k_base *ab, struct ath12k_link_sta *ar
 struct ath12k_link_sta *ath12k_link_sta_find_by_addr(struct ath12k_base *ab,
 						     const u8 *addr);
 u16 ath12k_peer_ml_alloc(struct ath12k_hw *ah);
+void ath12k_peer_ml_free(struct ath12k_hw *ah, struct ath12k_sta *ahsta);
 #endif /* _PEER_H_ */
diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
index e5bf9d2181040d..0c277f51d99c1a 100644
--- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c
+++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c
@@ -439,6 +439,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
 			.max_client_dbs = 128,
 			.max_client_dbs_sbs = 128,
 		},
+
+		.host_alloc_ml_id = true,
 	},
 	{
 		.name = "wcn7850 hw2.0",
@@ -530,6 +532,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
 			.max_client_dbs = 128,
 			.max_client_dbs_sbs = 128,
 		},
+
+		.host_alloc_ml_id = false,
 	},
 	{
 		.name = "qcn9274 hw2.0",
@@ -617,6 +621,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
 			.max_client_dbs = 128,
 			.max_client_dbs_sbs = 128,
 		},
+
+		.host_alloc_ml_id = true,
 	},
 	{
 		.name = "ipq5332 hw1.0",
@@ -697,6 +703,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
 			.max_client_dbs = 128,
 			.max_client_dbs_sbs = 128,
 		},
+
+		.host_alloc_ml_id = true,
 	},
 	{
 		.name = "qcc2072 hw1.0",
@@ -789,6 +797,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
 			.max_client_dbs = 128,
 			.max_client_dbs_sbs = 128,
 		},
+
+		.host_alloc_ml_id = false,
 	},
 	{
 		.name = "ipq5424 hw1.0",
@@ -873,6 +883,8 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = {
 			.max_client_dbs = 128,
 			.max_client_dbs_sbs = 128,
 		},
+
+		.host_alloc_ml_id = true,
 	},
 };
 

3/2 2026/07/13 08:03 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 12746
							output: 28
							thoughts: 651
						

Thoughts:
**Analyzing the Reachability of an ath12k Patch in Virtualized Environments**

Okay, so I'm looking at this patch for the `ath12k` wireless driver, which is a big deal because `ath12k` is Qualcomm Wi-Fi 7 hardware, specifically. The patch itself seems pretty straightforward – it's adding a flag, a new HTT event handler for Multi-Link Operation (MLO) peer mapping, and modifying a bunch of existing functions related to peer association and creation. Functionally, it's adding MLO support to the driver. This is interesting, but my immediate thought is about testability. Can I even *get* to this code path in a virtual environment?

My concern is that Wi-Fi drivers, *especially* at this level, usually depend on actual hardware. You need a PCIe device or something similar, and that makes fuzzing and testing in QEMU or GCE pretty tricky. I immediately think of `mac80211_hwsim`, the software simulator for mac80211, but that's mac80211. It wouldn't model the specific nuances of `ath12k` hardware.

The question then becomes: can `ath12k` be fuzzed without the actual hardware? I know syzkaller has some mac80211 support, but that’s broad and probably wouldn’t hit this particular driver unless there was a specific emulator. We have emulators for other hardware types, like `vhci` for Bluetooth or `dummy_hcd` for USB, but I’m not aware of anything like that for `ath12k`. No specific virtual device, no.

Then I recalled syzkaller has PCI fuzzing via `syz_pcidev` or simulated PCI (e.g. `vfio`). But wait, the original prompt *specifically* said it's code paths that are impossible to reach in virtualized environments like GCE or QEMU, even with hardware emulation. So, is this patch reachable at all?

This means I need to double-check if there's *any* way to get to this `ath12k` code with fuzzing. Is there anything in syzkaller's definitions for PCI devices, or anything explicitly targeting `ath12k`? I should check `sys/linux/dev_wifi.txt` and the kernel source, and maybe use `grepper` to search for any signs of fuzzing or virtual devices related to `ath12k`. I need to figure out if there's any test module or any way of virtualizing or emulating `ath12k`, because if there isn't, this patch is probably inaccessible without real hardware, which makes it much harder to test and fuzz.



4/2 2026/07/13 08:03 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "ath12k",
  "PathPrefix": "tools/testing/"
}

Results:
{
  "error": "no matches"
}

5/2 2026/07/13 08:03 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 14033
							output: 32
							thoughts: 20
						

Thoughts:
Okay, here's my thought process summarized, geared towards an expert:

**Investigating `ath12k` Emulator Presence**

Alright, let's get down to brass tacks. I'm taking a look at the kernel and the `ath12k` driver. Given what I know about wireless chipset development and the evolution of these drivers, my first thought is: Has anyone, somewhere, created an *emulator* for `ath12k` within the kernel itself? I'm not talking about full emulation like QEMU or something; I'm thinking more along the lines of a software-based representation for testing purposes, maybe simulating certain hardware behaviors or for driver development in the absence of the real hardware. So, my initial question is: Does a kernel-level `ath12k` emulator exist, and, if so, what are its implications for the overall system?



6/2 2026/07/13 08:03 tool grepper
0m Args:
{
  "Expression": "ath12k",
  "PathPrefix": "drivers/net/wireless/ath/"
}

Results:
{
  "Output": "\nFull output is too long, showing 500 out of 35012 lines.\nUse more precise expression if possible.\n\ndrivers/net/wireless/ath/Kconfig=65=source \"drivers/net/wireless/ath/ath11k/Kconfig\"\ndrivers/net/wireless/ath/Kconfig:66:source \"drivers/net/wireless/ath/ath12k/Kconfig\"\ndrivers/net/wireless/ath/Kconfig-67-\n--\ndrivers/net/wireless/ath/Makefile=10=obj-$(CONFIG_ATH11K)\t\t+= ath11k/\ndrivers/net/wireless/ath/Makefile:11:obj-$(CONFIG_ATH12K)\t\t+= ath12k/\ndrivers/net/wireless/ath/Makefile-12-\n--\ndrivers/net/wireless/ath/ath12k/Kconfig=2=config ATH12K\ndrivers/net/wireless/ath/ath12k/Kconfig:3:\ttristate \"Qualcomm Wi-Fi 7 support (ath12k)\"\ndrivers/net/wireless/ath/ath12k/Kconfig-4-\tdepends on MAC80211 \u0026\u0026 HAS_DMA \u0026\u0026 PCI\n--\ndrivers/net/wireless/ath/ath12k/Kconfig-14-\ndrivers/net/wireless/ath/ath12k/Kconfig:15:\t  If you choose to build a module, it'll be called ath12k.\ndrivers/net/wireless/ath/ath12k/Kconfig-16-\ndrivers/net/wireless/ath/ath12k/Kconfig=17=config ATH12K_AHB\ndrivers/net/wireless/ath/ath12k/Kconfig:18:\tbool \"Qualcomm ath12k AHB support\"\ndrivers/net/wireless/ath/ath12k/Kconfig-19-\tdepends on ATH12K \u0026\u0026 REMOTEPROC\n--\ndrivers/net/wireless/ath/ath12k/Kconfig=25=config ATH12K_DEBUG\ndrivers/net/wireless/ath/ath12k/Kconfig:26:\tbool \"ath12k debugging\"\ndrivers/net/wireless/ath/ath12k/Kconfig-27-\tdepends on ATH12K\n--\ndrivers/net/wireless/ath/ath12k/Kconfig=35=config ATH12K_DEBUGFS\ndrivers/net/wireless/ath/ath12k/Kconfig:36:\tbool \"Qualcomm ath12k debugfs support\"\ndrivers/net/wireless/ath/ath12k/Kconfig-37-\tdepends on ATH12K \u0026\u0026 MAC80211_DEBUGFS\ndrivers/net/wireless/ath/ath12k/Kconfig-38-\thelp\ndrivers/net/wireless/ath/ath12k/Kconfig:39:\t  Enable ath12k debugfs support\ndrivers/net/wireless/ath/ath12k/Kconfig-40-\n--\ndrivers/net/wireless/ath/ath12k/Kconfig=44=config ATH12K_TRACING\ndrivers/net/wireless/ath/ath12k/Kconfig:45:\tbool \"ath12k tracing support\"\ndrivers/net/wireless/ath/ath12k/Kconfig-46-\tdepends on ATH12K \u0026\u0026 EVENT_TRACING\ndrivers/net/wireless/ath/ath12k/Kconfig-47-\thelp\ndrivers/net/wireless/ath/ath12k/Kconfig:48:\t  Enable ath12k tracing infrastructure.\ndrivers/net/wireless/ath/ath12k/Kconfig-49-\n--\ndrivers/net/wireless/ath/ath12k/Kconfig=53=config ATH12K_COREDUMP\ndrivers/net/wireless/ath/ath12k/Kconfig:54:\tbool \"ath12k coredump\"\ndrivers/net/wireless/ath/ath12k/Kconfig-55-\tdepends on ATH12K\n--\ndrivers/net/wireless/ath/ath12k/Kconfig-57-\thelp\ndrivers/net/wireless/ath/ath12k/Kconfig:58:\t  Enable ath12k coredump collection\ndrivers/net/wireless/ath/ath12k/Kconfig-59-\n--\ndrivers/net/wireless/ath/ath12k/Makefile-1-# SPDX-License-Identifier: BSD-3-Clause-Clear\ndrivers/net/wireless/ath/ath12k/Makefile:2:obj-$(CONFIG_ATH12K) += ath12k.o\ndrivers/net/wireless/ath/ath12k/Makefile:3:ath12k-y += core.o \\\ndrivers/net/wireless/ath/ath12k/Makefile-4-\t    hal.o \\\n--\ndrivers/net/wireless/ath/ath12k/Makefile-24-\ndrivers/net/wireless/ath/ath12k/Makefile:25:ath12k-$(CONFIG_ATH12K_AHB) += ahb.o\ndrivers/net/wireless/ath/ath12k/Makefile-26-\ndrivers/net/wireless/ath/ath12k/Makefile=27=obj-$(CONFIG_ATH12K) += wifi7/\ndrivers/net/wireless/ath/ath12k/Makefile-28-\ndrivers/net/wireless/ath/ath12k/Makefile:29:ath12k-$(CONFIG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o\ndrivers/net/wireless/ath/ath12k/Makefile:30:ath12k-$(CONFIG_ACPI) += acpi.o\ndrivers/net/wireless/ath/ath12k/Makefile:31:ath12k-$(CONFIG_ATH12K_TRACING) += trace.o\ndrivers/net/wireless/ath/ath12k/Makefile:32:ath12k-$(CONFIG_PM) += wow.o\ndrivers/net/wireless/ath/ath12k/Makefile:33:ath12k-$(CONFIG_ATH12K_COREDUMP) += coredump.o\ndrivers/net/wireless/ath/ath12k/Makefile:34:ath12k-$(CONFIG_NL80211_TESTMODE) += testmode.o\ndrivers/net/wireless/ath/ath12k/Makefile:35:ath12k-$(CONFIG_THERMAL) += thermal.o\ndrivers/net/wireless/ath/ath12k/Makefile-36-\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-10-\ndrivers/net/wireless/ath/ath12k/acpi.c:11:static int ath12k_acpi_dsm_get_data(struct ath12k_base *ab, int func)\ndrivers/net/wireless/ath/ath12k/acpi.c-12-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-18-\tif (!root_handle) {\ndrivers/net/wireless/ath/ath12k/acpi.c:19:\t\tath12k_dbg(ab, ATH12K_DBG_BOOT, \"invalid acpi handler\\n\");\ndrivers/net/wireless/ath/ath12k/acpi.c-20-\t\treturn -EOPNOTSUPP;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-26-\tif (!obj) {\ndrivers/net/wireless/ath/ath12k/acpi.c:27:\t\tath12k_dbg(ab, ATH12K_DBG_BOOT, \"acpi_evaluate_dsm() failed\\n\");\ndrivers/net/wireless/ath/ath12k/acpi.c-28-\t\treturn -ENOENT;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-46-\t\t\t\t   ATH12K_ACPI_BDF_ANCHOR_STRING_LEN)) {\ndrivers/net/wireless/ath/ath12k/acpi.c:47:\t\t\t\tath12k_warn(ab, \"invalid ACPI DSM BDF size: %d\\n\",\ndrivers/net/wireless/ath/ath12k/acpi.c-48-\t\t\t\t\t    obj-\u003estring.length);\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-62-\t\t\t    obj-\u003ebuffer.length \u003e ATH12K_ACPI_DSM_FUNC_MAX_BITMAP_SIZE) {\ndrivers/net/wireless/ath/ath12k/acpi.c:63:\t\t\t\tath12k_warn(ab, \"invalid ACPI DSM func size: %d\\n\",\ndrivers/net/wireless/ath/ath12k/acpi.c-64-\t\t\t\t\t    obj-\u003ebuffer.length);\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-75-\t\t\tif (obj-\u003ebuffer.length != ATH12K_ACPI_DSM_TAS_CFG_SIZE) {\ndrivers/net/wireless/ath/ath12k/acpi.c:76:\t\t\t\tath12k_warn(ab, \"invalid ACPI DSM TAS config size: %d\\n\",\ndrivers/net/wireless/ath/ath12k/acpi.c-77-\t\t\t\t\t    obj-\u003ebuffer.length);\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-87-\t\t\tif (obj-\u003ebuffer.length != ATH12K_ACPI_DSM_TAS_DATA_SIZE) {\ndrivers/net/wireless/ath/ath12k/acpi.c:88:\t\t\t\tath12k_warn(ab, \"invalid ACPI DSM TAS data size: %d\\n\",\ndrivers/net/wireless/ath/ath12k/acpi.c-89-\t\t\t\t\t    obj-\u003ebuffer.length);\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-99-\t\t\tif (obj-\u003ebuffer.length != ATH12K_ACPI_DSM_BIOS_SAR_DATA_SIZE) {\ndrivers/net/wireless/ath/ath12k/acpi.c:100:\t\t\t\tath12k_warn(ab, \"invalid ACPI BIOS SAR data size: %d\\n\",\ndrivers/net/wireless/ath/ath12k/acpi.c-101-\t\t\t\t\t    obj-\u003ebuffer.length);\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-111-\t\t\tif (obj-\u003ebuffer.length != ATH12K_ACPI_DSM_GEO_OFFSET_DATA_SIZE) {\ndrivers/net/wireless/ath/ath12k/acpi.c:112:\t\t\t\tath12k_warn(ab, \"invalid ACPI GEO OFFSET data size: %d\\n\",\ndrivers/net/wireless/ath/ath12k/acpi.c-113-\t\t\t\t\t    obj-\u003ebuffer.length);\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-123-\t\t\tif (obj-\u003ebuffer.length != ATH12K_ACPI_DSM_CCA_DATA_SIZE) {\ndrivers/net/wireless/ath/ath12k/acpi.c:124:\t\t\t\tath12k_warn(ab, \"invalid ACPI DSM CCA data size: %d\\n\",\ndrivers/net/wireless/ath/ath12k/acpi.c-125-\t\t\t\t\t    obj-\u003ebuffer.length);\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-135-\t\t\tif (obj-\u003ebuffer.length != ATH12K_ACPI_DSM_BAND_EDGE_DATA_SIZE) {\ndrivers/net/wireless/ath/ath12k/acpi.c:136:\t\t\t\tath12k_warn(ab, \"invalid ACPI DSM band edge data size: %d\\n\",\ndrivers/net/wireless/ath/ath12k/acpi.c-137-\t\t\t\t\t    obj-\u003ebuffer.length);\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-147-\t} else {\ndrivers/net/wireless/ath/ath12k/acpi.c:148:\t\tath12k_warn(ab, \"ACPI DSM method returned an unsupported object type: %d\\n\",\ndrivers/net/wireless/ath/ath12k/acpi.c-149-\t\t\t    obj-\u003etype);\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-160-\ndrivers/net/wireless/ath/ath12k/acpi.c:161:static int ath12k_acpi_set_power_limit(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.c-162-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-167-\t    tas_sar_power_table[1] != ATH12K_ACPI_TAS_DATA_ENABLE) {\ndrivers/net/wireless/ath/ath12k/acpi.c:168:\t\tath12k_warn(ab, \"latest ACPI TAS data is invalid\\n\");\ndrivers/net/wireless/ath/ath12k/acpi.c-169-\t\treturn -EINVAL;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-171-\ndrivers/net/wireless/ath/ath12k/acpi.c:172:\tret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_DATA_TYPE,\ndrivers/net/wireless/ath/ath12k/acpi.c-173-\t\t\t\t      tas_sar_power_table,\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-175-\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:176:\t\tath12k_warn(ab, \"failed to send ACPI TAS data table: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-177-\t\treturn ret;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-182-\ndrivers/net/wireless/ath/ath12k/acpi.c:183:static int ath12k_acpi_set_bios_sar_power(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.c-184-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-188-\t    ab-\u003eacpi.bios_sar_data[1] != ATH12K_ACPI_POWER_LIMIT_ENABLE_FLAG) {\ndrivers/net/wireless/ath/ath12k/acpi.c:189:\t\tath12k_warn(ab, \"invalid latest ACPI BIOS SAR data\\n\");\ndrivers/net/wireless/ath/ath12k/acpi.c-190-\t\treturn -EINVAL;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-192-\ndrivers/net/wireless/ath/ath12k/acpi.c:193:\tret = ath12k_wmi_set_bios_sar_cmd(ab, ab-\u003eacpi.bios_sar_data);\ndrivers/net/wireless/ath/ath12k/acpi.c-194-\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:195:\t\tath12k_warn(ab, \"failed to set ACPI BIOS SAR table: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-196-\t\treturn ret;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-201-\ndrivers/net/wireless/ath/ath12k/acpi.c:202:static void ath12k_acpi_dsm_notify(acpi_handle handle, u32 event, void *data)\ndrivers/net/wireless/ath/ath12k/acpi.c-203-{\ndrivers/net/wireless/ath/ath12k/acpi.c-204-\tint ret;\ndrivers/net/wireless/ath/ath12k/acpi.c:205:\tstruct ath12k_base *ab = data;\ndrivers/net/wireless/ath/ath12k/acpi.c-206-\ndrivers/net/wireless/ath/ath12k/acpi.c-207-\tif (event == ATH12K_ACPI_NOTIFY_EVENT) {\ndrivers/net/wireless/ath/ath12k/acpi.c:208:\t\tath12k_warn(ab, \"unknown acpi notify %u\\n\", event);\ndrivers/net/wireless/ath/ath12k/acpi.c-209-\t\treturn;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-212-\tif (!ab-\u003eacpi.acpi_tas_enable) {\ndrivers/net/wireless/ath/ath12k/acpi.c:213:\t\tath12k_dbg(ab, ATH12K_DBG_BOOT, \"acpi_tas_enable is false\\n\");\ndrivers/net/wireless/ath/ath12k/acpi.c-214-\t\treturn;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-216-\ndrivers/net/wireless/ath/ath12k/acpi.c:217:\tret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_DATA);\ndrivers/net/wireless/ath/ath12k/acpi.c-218-\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:219:\t\tath12k_warn(ab, \"failed to update ACPI TAS data table: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-220-\t\treturn;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-222-\ndrivers/net/wireless/ath/ath12k/acpi.c:223:\tret = ath12k_acpi_set_power_limit(ab);\ndrivers/net/wireless/ath/ath12k/acpi.c-224-\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:225:\t\tath12k_warn(ab, \"failed to set ACPI TAS power limit data: %d\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-226-\t\treturn;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-231-\ndrivers/net/wireless/ath/ath12k/acpi.c:232:\tret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_BIOS_SAR);\ndrivers/net/wireless/ath/ath12k/acpi.c-233-\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:234:\t\tath12k_warn(ab, \"failed to update BIOS SAR: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-235-\t\treturn;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-237-\ndrivers/net/wireless/ath/ath12k/acpi.c:238:\tret = ath12k_acpi_set_bios_sar_power(ab);\ndrivers/net/wireless/ath/ath12k/acpi.c-239-\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:240:\t\tath12k_warn(ab, \"failed to set BIOS SAR power limit: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-241-\t\treturn;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-244-\ndrivers/net/wireless/ath/ath12k/acpi.c:245:static int ath12k_acpi_set_bios_sar_params(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.c-246-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-248-\ndrivers/net/wireless/ath/ath12k/acpi.c:249:\tret = ath12k_wmi_set_bios_sar_cmd(ab, ab-\u003eacpi.bios_sar_data);\ndrivers/net/wireless/ath/ath12k/acpi.c-250-\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:251:\t\tath12k_warn(ab, \"failed to set ACPI BIOS SAR table: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-252-\t\treturn ret;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-254-\ndrivers/net/wireless/ath/ath12k/acpi.c:255:\tret = ath12k_wmi_set_bios_geo_cmd(ab, ab-\u003eacpi.geo_offset_data);\ndrivers/net/wireless/ath/ath12k/acpi.c-256-\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:257:\t\tath12k_warn(ab, \"failed to set ACPI BIOS GEO table: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-258-\t\treturn ret;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-263-\ndrivers/net/wireless/ath/ath12k/acpi.c:264:static int ath12k_acpi_set_tas_params(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.c-265-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-267-\ndrivers/net/wireless/ath/ath12k/acpi.c:268:\tret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_CONFIG_TYPE,\ndrivers/net/wireless/ath/ath12k/acpi.c-269-\t\t\t\t      ab-\u003eacpi.tas_cfg,\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-271-\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:272:\t\tath12k_warn(ab, \"failed to send ACPI TAS config table parameter: %d\\n\",\ndrivers/net/wireless/ath/ath12k/acpi.c-273-\t\t\t    ret);\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-276-\ndrivers/net/wireless/ath/ath12k/acpi.c:277:\tret = ath12k_wmi_set_bios_cmd(ab, WMI_BIOS_PARAM_TAS_DATA_TYPE,\ndrivers/net/wireless/ath/ath12k/acpi.c-278-\t\t\t\t      ab-\u003eacpi.tas_sar_power_table,\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-280-\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:281:\t\tath12k_warn(ab, \"failed to send ACPI TAS data table parameter: %d\\n\",\ndrivers/net/wireless/ath/ath12k/acpi.c-282-\t\t\t    ret);\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-288-\ndrivers/net/wireless/ath/ath12k/acpi.c:289:bool ath12k_acpi_get_disable_rfkill(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.c-290-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-293-\ndrivers/net/wireless/ath/ath12k/acpi.c:294:bool ath12k_acpi_get_disable_11be(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.c-295-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-298-\ndrivers/net/wireless/ath/ath12k/acpi.c:299:void ath12k_acpi_set_dsm_func(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.c-300-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-308-\tif (ab-\u003eacpi.acpi_tas_enable) {\ndrivers/net/wireless/ath/ath12k/acpi.c:309:\t\tret = ath12k_acpi_set_tas_params(ab);\ndrivers/net/wireless/ath/ath12k/acpi.c-310-\t\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:311:\t\t\tath12k_warn(ab, \"failed to send ACPI TAS parameters: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-312-\t\t\treturn;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-316-\tif (ab-\u003eacpi.acpi_bios_sar_enable) {\ndrivers/net/wireless/ath/ath12k/acpi.c:317:\t\tret = ath12k_acpi_set_bios_sar_params(ab);\ndrivers/net/wireless/ath/ath12k/acpi.c-318-\t\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:319:\t\t\tath12k_warn(ab, \"failed to send ACPI BIOS SAR: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-320-\t\t\treturn;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-325-\t\tbuf = ab-\u003eacpi.cca_data + ATH12K_ACPI_CCA_THR_OFFSET_DATA_OFFSET;\ndrivers/net/wireless/ath/ath12k/acpi.c:326:\t\tret = ath12k_wmi_set_bios_cmd(ab,\ndrivers/net/wireless/ath/ath12k/acpi.c-327-\t\t\t\t\t      WMI_BIOS_PARAM_CCA_THRESHOLD_TYPE,\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-330-\t\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:331:\t\t\tath12k_warn(ab, \"failed to set ACPI DSM CCA threshold: %d\\n\",\ndrivers/net/wireless/ath/ath12k/acpi.c-332-\t\t\t\t    ret);\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-337-\tif (ab-\u003eacpi.acpi_band_edge_enable) {\ndrivers/net/wireless/ath/ath12k/acpi.c:338:\t\tret = ath12k_wmi_set_bios_cmd(ab,\ndrivers/net/wireless/ath/ath12k/acpi.c-339-\t\t\t\t\t      WMI_BIOS_PARAM_TYPE_BANDEDGE,\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-342-\t\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:343:\t\t\tath12k_warn(ab,\ndrivers/net/wireless/ath/ath12k/acpi.c-344-\t\t\t\t    \"failed to set ACPI DSM band edge channel power: %d\\n\",\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-350-\ndrivers/net/wireless/ath/ath12k/acpi.c:351:int ath12k_acpi_start(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.c-352-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-368-\ndrivers/net/wireless/ath/ath12k/acpi.c:369:\tret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_SUPPORT_FUNCS);\ndrivers/net/wireless/ath/ath12k/acpi.c-370-\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:371:\t\tath12k_dbg(ab, ATH12K_DBG_BOOT, \"failed to get ACPI DSM data: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-372-\t\treturn ret;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-375-\tif (ATH12K_ACPI_FUNC_BIT_VALID(ab-\u003eacpi, ATH12K_ACPI_FUNC_BIT_DISABLE_FLAG)) {\ndrivers/net/wireless/ath/ath12k/acpi.c:376:\t\tret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_DISABLE_FLAG);\ndrivers/net/wireless/ath/ath12k/acpi.c-377-\t\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:378:\t\t\tath12k_warn(ab, \"failed to get ACPI DISABLE FLAG: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-379-\t\t\treturn ret;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-391-\tif (ATH12K_ACPI_FUNC_BIT_VALID(ab-\u003eacpi, ATH12K_ACPI_FUNC_BIT_BDF_EXT)) {\ndrivers/net/wireless/ath/ath12k/acpi.c:392:\t\tret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_BDF_EXT);\ndrivers/net/wireless/ath/ath12k/acpi.c-393-\t\tif (ret || ab-\u003eacpi.bdf_string[0] == '\\0') {\ndrivers/net/wireless/ath/ath12k/acpi.c:394:\t\t\tath12k_warn(ab, \"failed to get ACPI BDF EXT: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-395-\t\t\treturn ret;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-401-\tif (ATH12K_ACPI_FUNC_BIT_VALID(ab-\u003eacpi, ATH12K_ACPI_FUNC_BIT_TAS_CFG)) {\ndrivers/net/wireless/ath/ath12k/acpi.c:402:\t\tret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_CFG);\ndrivers/net/wireless/ath/ath12k/acpi.c-403-\t\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:404:\t\t\tath12k_warn(ab, \"failed to get ACPI TAS config table: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-405-\t\t\treturn ret;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-409-\tif (ATH12K_ACPI_FUNC_BIT_VALID(ab-\u003eacpi, ATH12K_ACPI_FUNC_BIT_TAS_DATA)) {\ndrivers/net/wireless/ath/ath12k/acpi.c:410:\t\tret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_TAS_DATA);\ndrivers/net/wireless/ath/ath12k/acpi.c-411-\t\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:412:\t\t\tath12k_warn(ab, \"failed to get ACPI TAS data table: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-413-\t\t\treturn ret;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-422-\tif (ATH12K_ACPI_FUNC_BIT_VALID(ab-\u003eacpi, ATH12K_ACPI_FUNC_BIT_BIOS_SAR)) {\ndrivers/net/wireless/ath/ath12k/acpi.c:423:\t\tret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_BIOS_SAR);\ndrivers/net/wireless/ath/ath12k/acpi.c-424-\t\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:425:\t\t\tath12k_warn(ab, \"failed to get ACPI bios sar data: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-426-\t\t\treturn ret;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-430-\tif (ATH12K_ACPI_FUNC_BIT_VALID(ab-\u003eacpi, ATH12K_ACPI_FUNC_BIT_GEO_OFFSET)) {\ndrivers/net/wireless/ath/ath12k/acpi.c:431:\t\tret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_GEO_OFFSET);\ndrivers/net/wireless/ath/ath12k/acpi.c-432-\t\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:433:\t\t\tath12k_warn(ab, \"failed to get ACPI geo offset data: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/acpi.c-434-\t\t\treturn ret;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-444-\tif (ATH12K_ACPI_FUNC_BIT_VALID(ab-\u003eacpi, ATH12K_ACPI_FUNC_BIT_CCA)) {\ndrivers/net/wireless/ath/ath12k/acpi.c:445:\t\tret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_INDEX_CCA);\ndrivers/net/wireless/ath/ath12k/acpi.c-446-\t\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:447:\t\t\tath12k_warn(ab, \"failed to get ACPI DSM CCA threshold configuration: %d\\n\",\ndrivers/net/wireless/ath/ath12k/acpi.c-448-\t\t\t\t    ret);\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-459-\t\t\t\t       ATH12K_ACPI_FUNC_BIT_BAND_EDGE_CHAN_POWER)) {\ndrivers/net/wireless/ath/ath12k/acpi.c:460:\t\tret = ath12k_acpi_dsm_get_data(ab, ATH12K_ACPI_DSM_FUNC_INDEX_BAND_EDGE);\ndrivers/net/wireless/ath/ath12k/acpi.c-461-\t\tif (ret) {\ndrivers/net/wireless/ath/ath12k/acpi.c:462:\t\t\tath12k_warn(ab, \"failed to get ACPI DSM band edge channel power: %d\\n\",\ndrivers/net/wireless/ath/ath12k/acpi.c-463-\t\t\t\t    ret);\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-473-\t\t\t\t\t     ACPI_DEVICE_NOTIFY,\ndrivers/net/wireless/ath/ath12k/acpi.c:474:\t\t\t\t\t     ath12k_acpi_dsm_notify, ab);\ndrivers/net/wireless/ath/ath12k/acpi.c-475-\tif (ACPI_FAILURE(status)) {\ndrivers/net/wireless/ath/ath12k/acpi.c:476:\t\tath12k_warn(ab, \"failed to install DSM notify callback: %d\\n\", status);\ndrivers/net/wireless/ath/ath12k/acpi.c-477-\t\treturn -EIO;\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-484-\ndrivers/net/wireless/ath/ath12k/acpi.c:485:int ath12k_acpi_check_bdf_variant_name(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.c-486-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-492-\tif (strscpy(ab-\u003eqmi.target.bdf_ext, ab-\u003eacpi.bdf_string + 4, max_len) \u003c 0)\ndrivers/net/wireless/ath/ath12k/acpi.c:493:\t\tath12k_dbg(ab, ATH12K_DBG_BOOT,\ndrivers/net/wireless/ath/ath12k/acpi.c-494-\t\t\t   \"acpi bdf variant longer than the buffer (variant: %s)\\n\",\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-499-\ndrivers/net/wireless/ath/ath12k/acpi.c:500:void ath12k_acpi_stop(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.c-501-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.c-506-\t\t\t\t   ACPI_DEVICE_NOTIFY,\ndrivers/net/wireless/ath/ath12k/acpi.c:507:\t\t\t\t   ath12k_acpi_dsm_notify);\ndrivers/net/wireless/ath/ath12k/acpi.c-508-\n--\ndrivers/net/wireless/ath/ath12k/acpi.h-74-\ndrivers/net/wireless/ath/ath12k/acpi.h:75:int ath12k_acpi_start(struct ath12k_base *ab);\ndrivers/net/wireless/ath/ath12k/acpi.h:76:void ath12k_acpi_stop(struct ath12k_base *ab);\ndrivers/net/wireless/ath/ath12k/acpi.h:77:bool ath12k_acpi_get_disable_rfkill(struct ath12k_base *ab);\ndrivers/net/wireless/ath/ath12k/acpi.h:78:bool ath12k_acpi_get_disable_11be(struct ath12k_base *ab);\ndrivers/net/wireless/ath/ath12k/acpi.h:79:void ath12k_acpi_set_dsm_func(struct ath12k_base *ab);\ndrivers/net/wireless/ath/ath12k/acpi.h:80:int ath12k_acpi_check_bdf_variant_name(struct ath12k_base *ab);\ndrivers/net/wireless/ath/ath12k/acpi.h-81-\n--\ndrivers/net/wireless/ath/ath12k/acpi.h-83-\ndrivers/net/wireless/ath/ath12k/acpi.h:84:static inline int ath12k_acpi_start(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.h-85-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.h-88-\ndrivers/net/wireless/ath/ath12k/acpi.h:89:static inline void ath12k_acpi_stop(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.h-90-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.h-92-\ndrivers/net/wireless/ath/ath12k/acpi.h:93:static inline bool ath12k_acpi_get_disable_rfkill(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.h-94-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.h-97-\ndrivers/net/wireless/ath/ath12k/acpi.h:98:static inline bool ath12k_acpi_get_disable_11be(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.h-99-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.h-102-\ndrivers/net/wireless/ath/ath12k/acpi.h:103:static inline void ath12k_acpi_set_dsm_func(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.h-104-{\n--\ndrivers/net/wireless/ath/ath12k/acpi.h-106-\ndrivers/net/wireless/ath/ath12k/acpi.h:107:static inline int ath12k_acpi_check_bdf_variant_name(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/acpi.h-108-{\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-21-\ndrivers/net/wireless/ath/ath12k/ahb.c:22:static struct ath12k_ahb_driver *ath12k_ahb_family_drivers[ATH12K_DEVICE_FAMILY_MAX];\ndrivers/net/wireless/ath/ath12k/ahb.c:23:static const char ath12k_userpd_irq[][9] = {\"spawn\",\ndrivers/net/wireless/ath/ath12k/ahb.c-24-\t\t\t\t     \"ready\",\n--\ndrivers/net/wireless/ath/ath12k/ahb.c=83=enum ext_irq_num {\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-122-\ndrivers/net/wireless/ath/ath12k/ahb.c:123:static u32 ath12k_ahb_read32(struct ath12k_base *ab, u32 offset)\ndrivers/net/wireless/ath/ath12k/ahb.c-124-{\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-129-\ndrivers/net/wireless/ath/ath12k/ahb.c:130:static void ath12k_ahb_write32(struct ath12k_base *ab, u32 offset,\ndrivers/net/wireless/ath/ath12k/ahb.c-131-\t\t\t       u32 value)\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-138-\ndrivers/net/wireless/ath/ath12k/ahb.c:139:static void ath12k_ahb_cancel_workqueue(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/ahb.c-140-{\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-143-\tfor (i = 0; i \u003c ab-\u003ehw_params-\u003ece_count; i++) {\ndrivers/net/wireless/ath/ath12k/ahb.c:144:\t\tstruct ath12k_ce_pipe *ce_pipe = \u0026ab-\u003ece.ce_pipe[i];\ndrivers/net/wireless/ath/ath12k/ahb.c-145-\ndrivers/net/wireless/ath/ath12k/ahb.c:146:\t\tif (ath12k_ce_get_attr_flags(ab, i) \u0026 CE_ATTR_DIS_INTR)\ndrivers/net/wireless/ath/ath12k/ahb.c-147-\t\t\tcontinue;\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-152-\ndrivers/net/wireless/ath/ath12k/ahb.c:153:static void ath12k_ahb_ext_grp_disable(struct ath12k_ext_irq_grp *irq_grp)\ndrivers/net/wireless/ath/ath12k/ahb.c-154-{\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-160-\ndrivers/net/wireless/ath/ath12k/ahb.c:161:static void __ath12k_ahb_ext_irq_disable(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/ahb.c-162-{\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-165-\tfor (i = 0; i \u003c ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) {\ndrivers/net/wireless/ath/ath12k/ahb.c:166:\t\tstruct ath12k_ext_irq_grp *irq_grp = \u0026ab-\u003eext_irq_grp[i];\ndrivers/net/wireless/ath/ath12k/ahb.c-167-\ndrivers/net/wireless/ath/ath12k/ahb.c:168:\t\tath12k_ahb_ext_grp_disable(irq_grp);\ndrivers/net/wireless/ath/ath12k/ahb.c-169-\t\tif (irq_grp-\u003enapi_enabled) {\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-176-\ndrivers/net/wireless/ath/ath12k/ahb.c:177:static void ath12k_ahb_ext_grp_enable(struct ath12k_ext_irq_grp *irq_grp)\ndrivers/net/wireless/ath/ath12k/ahb.c-178-{\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-184-\ndrivers/net/wireless/ath/ath12k/ahb.c:185:static void ath12k_ahb_setbit32(struct ath12k_base *ab, u8 bit, u32 offset)\ndrivers/net/wireless/ath/ath12k/ahb.c-186-{\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-188-\ndrivers/net/wireless/ath/ath12k/ahb.c:189:\tval = ath12k_ahb_read32(ab, offset);\ndrivers/net/wireless/ath/ath12k/ahb.c:190:\tath12k_ahb_write32(ab, offset, val | BIT(bit));\ndrivers/net/wireless/ath/ath12k/ahb.c-191-}\ndrivers/net/wireless/ath/ath12k/ahb.c-192-\ndrivers/net/wireless/ath/ath12k/ahb.c:193:static void ath12k_ahb_clearbit32(struct ath12k_base *ab, u8 bit, u32 offset)\ndrivers/net/wireless/ath/ath12k/ahb.c-194-{\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-196-\ndrivers/net/wireless/ath/ath12k/ahb.c:197:\tval = ath12k_ahb_read32(ab, offset);\ndrivers/net/wireless/ath/ath12k/ahb.c:198:\tath12k_ahb_write32(ab, offset, val \u0026 ~BIT(bit));\ndrivers/net/wireless/ath/ath12k/ahb.c-199-}\ndrivers/net/wireless/ath/ath12k/ahb.c-200-\ndrivers/net/wireless/ath/ath12k/ahb.c:201:static void ath12k_ahb_ce_irq_enable(struct ath12k_base *ab, u16 ce_id)\ndrivers/net/wireless/ath/ath12k/ahb.c-202-{\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-212-\tif (ce_attr-\u003esrc_nentries)\ndrivers/net/wireless/ath/ath12k/ahb.c:213:\t\tath12k_ahb_setbit32(ab, ce_id, ie1_reg_addr);\ndrivers/net/wireless/ath/ath12k/ahb.c-214-\ndrivers/net/wireless/ath/ath12k/ahb.c-215-\tif (ce_attr-\u003edest_nentries) {\ndrivers/net/wireless/ath/ath12k/ahb.c:216:\t\tath12k_ahb_setbit32(ab, ce_id, ie2_reg_addr);\ndrivers/net/wireless/ath/ath12k/ahb.c:217:\t\tath12k_ahb_setbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,\ndrivers/net/wireless/ath/ath12k/ahb.c-218-\t\t\t\t    ie3_reg_addr);\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-221-\ndrivers/net/wireless/ath/ath12k/ahb.c:222:static void ath12k_ahb_ce_irq_disable(struct ath12k_base *ab, u16 ce_id)\ndrivers/net/wireless/ath/ath12k/ahb.c-223-{\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-233-\tif (ce_attr-\u003esrc_nentries)\ndrivers/net/wireless/ath/ath12k/ahb.c:234:\t\tath12k_ahb_clearbit32(ab, ce_id, ie1_reg_addr);\ndrivers/net/wireless/ath/ath12k/ahb.c-235-\ndrivers/net/wireless/ath/ath12k/ahb.c-236-\tif (ce_attr-\u003edest_nentries) {\ndrivers/net/wireless/ath/ath12k/ahb.c:237:\t\tath12k_ahb_clearbit32(ab, ce_id, ie2_reg_addr);\ndrivers/net/wireless/ath/ath12k/ahb.c:238:\t\tath12k_ahb_clearbit32(ab, ce_id + CE_HOST_IE_3_SHIFT,\ndrivers/net/wireless/ath/ath12k/ahb.c-239-\t\t\t\t      ie3_reg_addr);\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-242-\ndrivers/net/wireless/ath/ath12k/ahb.c:243:static void ath12k_ahb_sync_ce_irqs(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/ahb.c-244-{\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-248-\tfor (i = 0; i \u003c ab-\u003ehw_params-\u003ece_count; i++) {\ndrivers/net/wireless/ath/ath12k/ahb.c:249:\t\tif (ath12k_ce_get_attr_flags(ab, i) \u0026 CE_ATTR_DIS_INTR)\ndrivers/net/wireless/ath/ath12k/ahb.c-250-\t\t\tcontinue;\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-256-\ndrivers/net/wireless/ath/ath12k/ahb.c:257:static void ath12k_ahb_sync_ext_irqs(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/ahb.c-258-{\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-262-\tfor (i = 0; i \u003c ATH12K_EXT_IRQ_GRP_NUM_MAX; i++) {\ndrivers/net/wireless/ath/ath12k/ahb.c:263:\t\tstruct ath12k_ext_irq_grp *irq_grp = \u0026ab-\u003eext_irq_grp[i];\ndrivers/net/wireless/ath/ath12k/ahb.c-264-\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-271-\ndrivers/net/wireless/ath/ath12k/ahb.c:272:static void ath12k_ahb_ce_irqs_enable(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/ahb.c-273-{\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-276-\tfor (i = 0; i \u003c ab-\u003ehw_params-\u003ece_count; i++) {\ndrivers/net/wireless/ath/ath12k/ahb.c:277:\t\tif (ath12k_ce_get_attr_flags(ab, i) \u0026 CE_ATTR_DIS_INTR)\ndrivers/net/wireless/ath/ath12k/ahb.c-278-\t\t\tcontinue;\ndrivers/net/wireless/ath/ath12k/ahb.c:279:\t\tath12k_ahb_ce_irq_enable(ab, i);\ndrivers/net/wireless/ath/ath12k/ahb.c-280-\t}\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-282-\ndrivers/net/wireless/ath/ath12k/ahb.c:283:static void ath12k_ahb_ce_irqs_disable(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/ahb.c-284-{\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-287-\tfor (i = 0; i \u003c ab-\u003ehw_params-\u003ece_count; i++) {\ndrivers/net/wireless/ath/ath12k/ahb.c:288:\t\tif (ath12k_ce_get_attr_flags(ab, i) \u0026 CE_ATTR_DIS_INTR)\ndrivers/net/wireless/ath/ath12k/ahb.c-289-\t\t\tcontinue;\ndrivers/net/wireless/ath/ath12k/ahb.c:290:\t\tath12k_ahb_ce_irq_disable(ab, i);\ndrivers/net/wireless/ath/ath12k/ahb.c-291-\t}\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-293-\ndrivers/net/wireless/ath/ath12k/ahb.c:294:static int ath12k_ahb_start(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/ahb.c-295-{\ndrivers/net/wireless/ath/ath12k/ahb.c:296:\tath12k_ahb_ce_irqs_enable(ab);\ndrivers/net/wireless/ath/ath12k/ahb.c:297:\tath12k_ce_rx_post_buf(ab);\ndrivers/net/wireless/ath/ath12k/ahb.c-298-\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-301-\ndrivers/net/wireless/ath/ath12k/ahb.c:302:static void ath12k_ahb_ext_irq_enable(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/ahb.c-303-{\ndrivers/net/wireless/ath/ath12k/ahb.c:304:\tstruct ath12k_ext_irq_grp *irq_grp;\ndrivers/net/wireless/ath/ath12k/ahb.c-305-\tint i;\n\n"
}

7/2 2026/07/13 08:03 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 28988
							output: 42
							thoughts: 739
						

Thoughts:
**Reviewing the `ath12k` Driver for Fuzzing Suitability**

Okay, so I'm looking at `ath12k`, and it's got both `ath12k_ahb` and `ath12k_pci` variants.  Then there's `mac80211_hwsim`, which simulates mac80211, but that's distinct from the `ath12k` hardware driver itself. The key question is whether we can effectively fuzz `ath12k` with syzkaller. Syzkaller's got PCI fuzzing, which sounds promising since `ath12k` has a PCI interface.

The task is to determine if a patch introduces functional changes that warrant fuzzing.  The prompt's warning is relevant: "Code paths that are impossible to reach in virtualized environments... are not worth fuzzing". I need to figure out if `ath12k` *is* reachable.  My initial thought is that if it's a PCI driver, syzkaller should be able to reach it via `syz_pcidev` or similar mechanisms. But, hold on.  `syz_pcidev` isn't generally used to fuzz complex Wi-Fi drivers like `ath12k` because they typically involve firmware loading and DMA, which the PCI fuzzer struggles with.

However, the presence of "syz-cluster" in the commit message is interesting. Does this mean syzkaller found a bug or is actively fuzzing this driver? No, I am reviewing a patch. I am looking at it to determine if it is worth fuzzing.

My primary concern is that `ath12k` requires hardware or an emulator. Does it have testmode or a software simulator? Can it be reached in QEMU? There doesn't appear to be a dedicated `ath12k` emulator in QEMU, and PCI fuzzing often fails due to the driver's firmware loading requirements and device boot sequence (`ath12k_core_fetch_bdf`, etc.). Without a real device or a good emulator, the probe will fail and most of the code in `mac.c`, `dp_htt.c`, etc. will be unreachable.

I'll check for a test mode or software simulator. Looking at `drivers/net/wireless/ath/ath12k/Makefile`, I see `ath12k-$(CONFIG_NL80211_TESTMODE) += testmode.o`. This test mode is for nl80211 test commands, but it still seems to require hardware presence. There is also `mac80211_hwsim`, but it's a separate driver, not specific to `ath12k`. Finally, I should look at `ath12k_pci_probe`. It seems doubtful the `ath12k` driver can be probed without hardware.



8/2 2026/07/13 08:03 tool grepper
0m Args:
{
  "Expression": "ath12k_pci_probe",
  "PathPrefix": "drivers/net/wireless/ath/ath12k/"
}

Results:
{
  "Output": "drivers/net/wireless/ath/ath12k/pci.c=1517=ath12k_get_device_family(const struct pci_device_id *pci_dev)\n--\ndrivers/net/wireless/ath/ath12k/pci.c-1537-\ndrivers/net/wireless/ath/ath12k/pci.c:1538:static int ath12k_pci_probe(struct pci_dev *pdev,\ndrivers/net/wireless/ath/ath12k/pci.c-1539-\t\t\t    const struct pci_device_id *pci_dev)\n--\ndrivers/net/wireless/ath/ath12k/pci.c=1818=int ath12k_pci_register_driver(const enum ath12k_device_family device_id,\n--\ndrivers/net/wireless/ath/ath12k/pci.c-1839-\tpci_driver-\u003eid_table = driver-\u003eid_table;\ndrivers/net/wireless/ath/ath12k/pci.c:1840:\tpci_driver-\u003eprobe = ath12k_pci_probe;\ndrivers/net/wireless/ath/ath12k/pci.c-1841-\tpci_driver-\u003eremove = ath12k_pci_remove;\n"
}

9/2 2026/07/13 08:03 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 30748
							output: 47
							thoughts: 24
						

Thoughts:
Here's my analysis of the situation, tailored for an expert like yourself:

**Diving into the `ath12k_pci_probe` Function**

Okay, so we're talking about `ath12k_pci_probe`. My primary concern right now is whether this function is fundamentally tied to actual hardware presence. Is it *required* to have the physical PCI device connected to even function in some capacity? Does it need to do some device initialization that necessitates the hardware? Understanding this is critical for whatever testing or analysis we're planning. My immediate focus is to get a handle on the function's dependencies in that respect. I need to know if I can reliably emulate this without the actual hardware in place. If it *does* rely on specific hardware interactions, I need to know precisely which ones, so I can try to simulate them in a test environment.



10/2 2026/07/13 08:03 tool read-file
0m Args:
{
  "File": "drivers/net/wireless/ath/ath12k/pci.c",
  "FirstLine": 1538,
  "LineCount": 100
}

Results:
{
  "Contents": "1538:\tstatic int ath12k_pci_probe(struct pci_dev *pdev,\n1539:\t\t\t\t    const struct pci_device_id *pci_dev)\n1540:\t{\n1541:\t\tenum ath12k_device_family device_id;\n1542:\t\tstruct ath12k_pci *ab_pci;\n1543:\t\tstruct ath12k_base *ab;\n1544:\t\tint ret;\n1545:\t\n1546:\t\tab = ath12k_core_alloc(\u0026pdev-\u003edev, sizeof(*ab_pci), ATH12K_BUS_PCI);\n1547:\t\tif (!ab) {\n1548:\t\t\tdev_err(\u0026pdev-\u003edev, \"failed to allocate ath12k base\\n\");\n1549:\t\t\treturn -ENOMEM;\n1550:\t\t}\n1551:\t\n1552:\t\tab-\u003edev = \u0026pdev-\u003edev;\n1553:\t\tab_pci = ath12k_pci_priv(ab);\n1554:\t\tab_pci-\u003edev_id = pci_dev-\u003edevice;\n1555:\t\tab_pci-\u003eab = ab;\n1556:\t\tab_pci-\u003epdev = pdev;\n1557:\t\tab-\u003ehif.ops = \u0026ath12k_pci_hif_ops;\n1558:\t\tab-\u003efw_mode = ATH12K_FIRMWARE_MODE_NORMAL;\n1559:\t\tpci_set_drvdata(pdev, ab);\n1560:\t\tspin_lock_init(\u0026ab_pci-\u003ewindow_lock);\n1561:\t\n1562:\t\tret = ath12k_pci_claim(ab_pci, pdev);\n1563:\t\tif (ret) {\n1564:\t\t\tath12k_err(ab, \"failed to claim device: %d\\n\", ret);\n1565:\t\t\tgoto err_free_core;\n1566:\t\t}\n1567:\t\n1568:\t\tath12k_dbg(ab, ATH12K_DBG_BOOT, \"pci probe %04x:%04x %04x:%04x\\n\",\n1569:\t\t\t   pdev-\u003evendor, pdev-\u003edevice,\n1570:\t\t\t   pdev-\u003esubsystem_vendor, pdev-\u003esubsystem_device);\n1571:\t\n1572:\t\tab-\u003eid.vendor = pdev-\u003evendor;\n1573:\t\tab-\u003eid.device = pdev-\u003edevice;\n1574:\t\tab-\u003eid.subsystem_vendor = pdev-\u003esubsystem_vendor;\n1575:\t\tab-\u003eid.subsystem_device = pdev-\u003esubsystem_device;\n1576:\t\n1577:\t\tdevice_id = ath12k_get_device_family(pci_dev);\n1578:\t\tif (device_id \u003e= ATH12K_DEVICE_FAMILY_MAX) {\n1579:\t\t\tath12k_err(ab, \"failed to get device family id\\n\");\n1580:\t\t\tret = -EINVAL;\n1581:\t\t\tgoto err_pci_free_region;\n1582:\t\t}\n1583:\t\n1584:\t\tath12k_dbg(ab, ATH12K_DBG_PCI, \"PCI device family id: %d\\n\", device_id);\n1585:\t\n1586:\t\tab_pci-\u003edevice_family_ops = \u0026ath12k_pci_family_drivers[device_id]-\u003eops;\n1587:\t\tab_pci-\u003ereg_base = ath12k_pci_family_drivers[device_id]-\u003ereg_base;\n1588:\t\n1589:\t\t/* Call device specific probe. This is the callback that can\n1590:\t\t * be used to override any ops in future\n1591:\t\t * probe is validated for NULL during registration.\n1592:\t\t */\n1593:\t\tret = ab_pci-\u003edevice_family_ops-\u003eprobe(pdev, pci_dev);\n1594:\t\tif (ret) {\n1595:\t\t\tath12k_err(ab, \"failed to probe device: %d\\n\", ret);\n1596:\t\t\tgoto err_pci_free_region;\n1597:\t\t}\n1598:\t\n1599:\t\tret = ath12k_pci_msi_alloc(ab_pci);\n1600:\t\tif (ret) {\n1601:\t\t\tath12k_err(ab, \"failed to alloc msi: %d\\n\", ret);\n1602:\t\t\tgoto err_pci_free_region;\n1603:\t\t}\n1604:\t\n1605:\t\tret = ath12k_core_pre_init(ab);\n1606:\t\tif (ret)\n1607:\t\t\tgoto err_pci_msi_free;\n1608:\t\n1609:\t\tret = ath12k_pci_set_irq_affinity_hint(ab_pci, cpumask_of(0));\n1610:\t\tif (ret) {\n1611:\t\t\tath12k_err(ab, \"failed to set irq affinity %d\\n\", ret);\n1612:\t\t\tgoto err_pci_msi_free;\n1613:\t\t}\n1614:\t\n1615:\t\tret = ath12k_mhi_register(ab_pci);\n1616:\t\tif (ret) {\n1617:\t\t\tath12k_err(ab, \"failed to register mhi: %d\\n\", ret);\n1618:\t\t\tgoto err_irq_affinity_cleanup;\n1619:\t\t}\n1620:\t\n1621:\t\tret = ath12k_hal_srng_init(ab);\n1622:\t\tif (ret)\n1623:\t\t\tgoto err_mhi_unregister;\n1624:\t\n1625:\t\tret = ath12k_ce_alloc_pipes(ab);\n1626:\t\tif (ret) {\n1627:\t\t\tath12k_err(ab, \"failed to allocate ce pipes: %d\\n\", ret);\n1628:\t\t\tgoto err_hal_srng_deinit;\n1629:\t\t}\n1630:\t\n1631:\t\tath12k_pci_init_qmi_ce_config(ab);\n1632:\t\n1633:\t\tret = ath12k_pci_config_irq(ab);\n1634:\t\tif (ret) {\n1635:\t\t\tath12k_err(ab, \"failed to config irq: %d\\n\", ret);\n1636:\t\t\tgoto err_ce_free;\n1637:\t\t}\n"
}

11/2 2026/07/13 08:03 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 32800
							output: 39
							thoughts: 611
						

Thoughts:
**WorthFuzzing Assessment: Ath12k Driver**

Okay, let's break this down. The core issue here is whether this patch, touching `ath12k` code, is worth fuzzing, given the constraints of our virtualized environments. The initial thought is that the `ath12k` driver utilizes the Modem Host Interface (MHI) to communicate with its firmware, and if we're dealing with syzkaller's PCI fuzzer, which *could* theoretically simulate the MHI state machine, it is really difficult for the fuzzer to accurately represent the MHI state machine.

However, the key is the prompt's explicit exclusion of code paths unreachable in virtual environments. Can `ath12k` be reached through something like `mac80211_hwsim`? No, that's a completely different driver. Is there *any* software emulation available for `ath12k`? Nope.

The patch modifies functions like `ath12k_dp_htt_mlo_peer_map_handler`, `ath12k_mac_peer_assoc`, and `ath12k_mac_op_sta_state`. Now, I recognize these as mac80211 callbacks and HTT event handlers. But if the device itself isn't successfully probed and instantiated, these callbacks *won't* even be registered because `ath12k_mac_register` happens *after* firmware loading and WMI initialization. It's a fundamental dependency.

So, the next question becomes: can `ath12k` *be* fuzzed? Well, syzkaller has a `syz_80211_inject_frame` and `mac80211_hwsim` which is fine for the mac80211 stack. But it doesn't *target* specific hardware drivers like `ath12k` unless it can be instantiated. Since `ath12k` fundamentally requires either a real PCI device or AHB device, and there's no suitable software emulator for it, it's virtually impossible to reach in environments like GCE or QEMU. It's simply unreachable.

To be thorough, let's quickly check to see if there's *any* testing mode or simulation flags built into the code. Let's look for anything with "testmode" or "sim" in it. If there is not, my final conclusion will be to set `WorthFuzzing=false`.



12/2 2026/07/13 08:03 tool grepper
0m Args:
{
  "Expression": "hwsim|sim|dummy",
  "PathPrefix": "drivers/net/wireless/ath/ath12k/"
}

Results:
{
  "Output": "drivers/net/wireless/ath/ath12k/ahb.c=563=static int ath12k_ahb_config_ext_irq(struct ath12k_base *ab)\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-577-\ndrivers/net/wireless/ath/ath12k/ahb.c:578:\t\tirq_grp-\u003enapi_ndev = alloc_netdev_dummy(0);\ndrivers/net/wireless/ath/ath12k/ahb.c-579-\t\tif (!irq_grp-\u003enapi_ndev)\n--\ndrivers/net/wireless/ath/ath12k/core.c=102=static int ath12k_core_continue_suspend_resume(struct ath12k_base *ab)\n--\ndrivers/net/wireless/ath/ath12k/core.c-109-\t/* so far single_pdev_only chips have supports_suspend as true\ndrivers/net/wireless/ath/ath12k/core.c:110:\t * so pass 0 as a dummy pdev_id here.\ndrivers/net/wireless/ath/ath12k/core.c-111-\t */\n--\ndrivers/net/wireless/ath/ath12k/core.h=492=struct ath12k_link_sta {\n--\ndrivers/net/wireless/ath/ath12k/core.h-495-\ndrivers/net/wireless/ath/ath12k/core.h:496:\t/* link address similar to ieee80211_link_sta */\ndrivers/net/wireless/ath/ath12k/core.h-497-\tu8 addr[ETH_ALEN];\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-12-\ndrivers/net/wireless/ath/ath12k/debugfs.c:13:static ssize_t ath12k_write_simulate_radar(struct file *file,\ndrivers/net/wireless/ath/ath12k/debugfs.c-14-\t\t\t\t\t   const char __user *user_buf,\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-20-\twiphy_lock(ath12k_ar_to_hw(ar)-\u003ewiphy);\ndrivers/net/wireless/ath/ath12k/debugfs.c:21:\tret = ath12k_wmi_simulate_radar(ar);\ndrivers/net/wireless/ath/ath12k/debugfs.c-22-\tif (ret)\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-30-\ndrivers/net/wireless/ath/ath12k/debugfs.c:31:static const struct file_operations fops_simulate_radar = {\ndrivers/net/wireless/ath/ath12k/debugfs.c:32:\t.write = ath12k_write_simulate_radar,\ndrivers/net/wireless/ath/ath12k/debugfs.c:33:\t.open = simple_open\ndrivers/net/wireless/ath/ath12k/debugfs.c-34-};\ndrivers/net/wireless/ath/ath12k/debugfs.c-35-\ndrivers/net/wireless/ath/ath12k/debugfs.c:36:static ssize_t ath12k_read_simulate_fw_crash(struct file *file,\ndrivers/net/wireless/ath/ath12k/debugfs.c-37-\t\t\t\t\t     char __user *user_buf,\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-40-\tconst char buf[] =\ndrivers/net/wireless/ath/ath12k/debugfs.c:41:\t\t\"To simulate firmware crash write one of the keywords to this file:\\n\"\ndrivers/net/wireless/ath/ath12k/debugfs.c-42-\t\t\"`assert` - send WMI_FORCE_FW_HANG_CMDID to firmware to cause assert.\\n\";\ndrivers/net/wireless/ath/ath12k/debugfs.c-43-\ndrivers/net/wireless/ath/ath12k/debugfs.c:44:\treturn simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));\ndrivers/net/wireless/ath/ath12k/debugfs.c-45-}\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c=47=static ssize_t\ndrivers/net/wireless/ath/ath12k/debugfs.c:48:ath12k_write_simulate_fw_crash(struct file *file,\ndrivers/net/wireless/ath/ath12k/debugfs.c-49-\t\t\t       const char __user *user_buf,\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-62-\ndrivers/net/wireless/ath/ath12k/debugfs.c:63:\trc = simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, user_buf, count);\ndrivers/net/wireless/ath/ath12k/debugfs.c-64-\tif (rc \u003c 0)\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-81-\tif (!strcmp(buf, \"assert\")) {\ndrivers/net/wireless/ath/ath12k/debugfs.c:82:\t\tath12k_info(ab, \"simulating firmware assert crash\\n\");\ndrivers/net/wireless/ath/ath12k/debugfs.c-83-\t\tret = ath12k_wmi_force_fw_hang_cmd(ar,\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-90-\tif (ret) {\ndrivers/net/wireless/ath/ath12k/debugfs.c:91:\t\tath12k_warn(ab, \"failed to simulate firmware crash: %d\\n\", ret);\ndrivers/net/wireless/ath/ath12k/debugfs.c-92-\t\treturn ret;\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-97-\ndrivers/net/wireless/ath/ath12k/debugfs.c:98:static const struct file_operations fops_simulate_fw_crash = {\ndrivers/net/wireless/ath/ath12k/debugfs.c:99:\t.read = ath12k_read_simulate_fw_crash,\ndrivers/net/wireless/ath/ath12k/debugfs.c:100:\t.write = ath12k_write_simulate_fw_crash,\ndrivers/net/wireless/ath/ath12k/debugfs.c:101:\t.open = simple_open,\ndrivers/net/wireless/ath/ath12k/debugfs.c-102-\t.owner = THIS_MODULE,\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c=783=static ssize_t ath12k_read_tpc_stats(struct file *file,\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-789-\ndrivers/net/wireless/ath/ath12k/debugfs.c:790:\treturn simple_read_from_buffer(user_buf, count, ppos, buf, len);\ndrivers/net/wireless/ath/ath12k/debugfs.c-791-}\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c=808=static const struct file_operations fops_tpc_stats_type = {\ndrivers/net/wireless/ath/ath12k/debugfs.c-809-\t.write = ath12k_write_tpc_stats_type,\ndrivers/net/wireless/ath/ath12k/debugfs.c:810:\t.open = simple_open,\ndrivers/net/wireless/ath/ath12k/debugfs.c-811-\t.llseek = default_llseek,\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c=884=static ssize_t ath12k_read_extd_rx_stats(struct file *file,\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-896-\ndrivers/net/wireless/ath/ath12k/debugfs.c:897:\treturn simple_read_from_buffer(ubuf, count, ppos, buf, len);\ndrivers/net/wireless/ath/ath12k/debugfs.c-898-}\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c=900=static const struct file_operations fops_extd_rx_stats = {\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-902-\t.write = ath12k_write_extd_rx_stats,\ndrivers/net/wireless/ath/ath12k/debugfs.c:903:\t.open = simple_open,\ndrivers/net/wireless/ath/ath12k/debugfs.c-904-};\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c=997=static ssize_t ath12k_read_link_stats(struct file *file,\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-1003-\ndrivers/net/wireless/ath/ath12k/debugfs.c:1004:\treturn simple_read_from_buffer(user_buf, count, ppos, buf, len);\ndrivers/net/wireless/ath/ath12k/debugfs.c-1005-}\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c=1025=static ssize_t ath12k_debugfs_dump_device_dp_stats(struct file *file,\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-1212-\ndrivers/net/wireless/ath/ath12k/debugfs.c:1213:\tret = simple_read_from_buffer(user_buf, count, ppos, buf, len);\ndrivers/net/wireless/ath/ath12k/debugfs.c-1214-\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c=1218=static const struct file_operations fops_device_dp_stats = {\ndrivers/net/wireless/ath/ath12k/debugfs.c-1219-\t.read = ath12k_debugfs_dump_device_dp_stats,\ndrivers/net/wireless/ath/ath12k/debugfs.c:1220:\t.open = simple_open,\ndrivers/net/wireless/ath/ath12k/debugfs.c-1221-\t.owner = THIS_MODULE,\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c=1225=void ath12k_debugfs_pdev_create(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/debugfs.c-1226-{\ndrivers/net/wireless/ath/ath12k/debugfs.c:1227:\tdebugfs_create_file(\"simulate_fw_crash\", 0600, ab-\u003edebugfs_soc, ab,\ndrivers/net/wireless/ath/ath12k/debugfs.c:1228:\t\t\t    \u0026fops_simulate_fw_crash);\ndrivers/net/wireless/ath/ath12k/debugfs.c-1229-\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c=1260=void ath12k_debugfs_soc_destroy(struct ath12k_base *ab)\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-1264-\t/* We are not removing ath12k directory on purpose, even if it\ndrivers/net/wireless/ath/ath12k/debugfs.c:1265:\t * would be empty. This simplifies the directory handling and it's\ndrivers/net/wireless/ath/ath12k/debugfs.c-1266-\t * a minor cosmetic issue to leave an empty ath12k directory to\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c=1317=static ssize_t ath12k_read_vdev_stats(struct file *file,\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-1323-\ndrivers/net/wireless/ath/ath12k/debugfs.c:1324:\treturn simple_read_from_buffer(user_buf, count, ppos, buf, len);\ndrivers/net/wireless/ath/ath12k/debugfs.c-1325-}\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c=1384=static ssize_t ath12k_read_bcn_stats(struct file *file,\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-1390-\ndrivers/net/wireless/ath/ath12k/debugfs.c:1391:\treturn simple_read_from_buffer(user_buf, count, ppos, buf, len);\ndrivers/net/wireless/ath/ath12k/debugfs.c-1392-}\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c=1445=static ssize_t ath12k_read_pdev_stats(struct file *file,\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-1451-\ndrivers/net/wireless/ath/ath12k/debugfs.c:1452:\treturn simple_read_from_buffer(user_buf, count, ppos, buf, len);\ndrivers/net/wireless/ath/ath12k/debugfs.c-1453-}\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c=1463=static ssize_t\ndrivers/net/wireless/ath/ath12k/debugfs.c:1464:ath12k_write_simulate_incumbent_signal_interference(struct file *file,\ndrivers/net/wireless/ath/ath12k/debugfs.c-1465-\t\t\t\t\t\t    const char __user *user_buf,\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-1484-\twiphy_lock(wiphy);\ndrivers/net/wireless/ath/ath12k/debugfs.c:1485:\tret = ath12k_wmi_simulate_incumbent_signal_interference(ar, chan_bw_interference_bitmap);\ndrivers/net/wireless/ath/ath12k/debugfs.c-1486-\tif (ret)\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-1495-\ndrivers/net/wireless/ath/ath12k/debugfs.c:1496:static const struct file_operations fops_simulate_incumbent_signal_interference = {\ndrivers/net/wireless/ath/ath12k/debugfs.c:1497:\t.write = ath12k_write_simulate_incumbent_signal_interference,\ndrivers/net/wireless/ath/ath12k/debugfs.c:1498:\t.open = simple_open,\ndrivers/net/wireless/ath/ath12k/debugfs.c-1499-};\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c=1520=void ath12k_debugfs_register(struct ath12k *ar)\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-1554-\tif (ar-\u003emac.sbands[NL80211_BAND_5GHZ].channels) {\ndrivers/net/wireless/ath/ath12k/debugfs.c:1555:\t\tdebugfs_create_file(\"dfs_simulate_radar\", 0200,\ndrivers/net/wireless/ath/ath12k/debugfs.c-1556-\t\t\t\t    ar-\u003edebug.debugfs_pdev, ar,\ndrivers/net/wireless/ath/ath12k/debugfs.c:1557:\t\t\t\t    \u0026fops_simulate_radar);\ndrivers/net/wireless/ath/ath12k/debugfs.c-1558-\t}\n--\ndrivers/net/wireless/ath/ath12k/debugfs.c-1568-\t\t     ar-\u003eab-\u003ewmi_ab.svc_map)) {\ndrivers/net/wireless/ath/ath12k/debugfs.c:1569:\t\tdebugfs_create_file(\"simulate_incumbent_signal_interference\", 0200,\ndrivers/net/wireless/ath/ath12k/debugfs.c-1570-\t\t\t\t    ar-\u003edebug.debugfs_pdev, ar,\ndrivers/net/wireless/ath/ath12k/debugfs.c:1571:\t\t\t\t    \u0026fops_simulate_incumbent_signal_interference);\ndrivers/net/wireless/ath/ath12k/debugfs.c-1572-\t}\n--\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c=884=ath12k_htt_print_hw_stats_whal_tx_tlv(const void *tag_buf, u16 tag_len,\n--\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c-904-\t\t\t le32_to_cpu(htt_stats_buf-\u003ehwsch_unpause_wait_tqm_write));\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c:905:\tlen += scnprintf(buf + len, buf_len - len, \"hwsch_dummy_tlv_skipped = %u\\n\",\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c:906:\t\t\t le32_to_cpu(htt_stats_buf-\u003ehwsch_dummy_tlv_skipped));\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c-907-\tlen += scnprintf(buf + len, buf_len - len,\n--\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c=1535=ath12k_htt_print_tx_de_compl_stats_tlv(const void *tag_buf, u16 tag_len,\n--\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c-1546-\tlen += scnprintf(buf + len, buf_len - len, \"HTT_TX_DE_COMPL_STATS_TLV:\\n\");\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c:1547:\tlen += scnprintf(buf + len, buf_len - len, \"tcl_dummy_frame = %u\\n\",\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c:1548:\t\t\t le32_to_cpu(htt_stats_buf-\u003etcl_dummy_frame));\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c:1549:\tlen += scnprintf(buf + len, buf_len - len, \"tqm_dummy_frame = %u\\n\",\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c:1550:\t\t\t le32_to_cpu(htt_stats_buf-\u003etqm_dummy_frame));\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c-1551-\tlen += scnprintf(buf + len, buf_len - len, \"tqm_notify_frame = %u\\n\",\n--\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c=6165=static ssize_t ath12k_read_htt_stats_type(struct file *file,\n--\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c-6179-\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c:6180:\treturn simple_read_from_buffer(user_buf, count, ppos, buf, len);\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c-6181-}\n--\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c=6225=static const struct file_operations fops_htt_stats_type = {\n--\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c-6227-\t.write = ath12k_write_htt_stats_type,\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c:6228:\t.open = simple_open,\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c-6229-\t.owner = THIS_MODULE,\n--\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c=6351=static ssize_t ath12k_read_htt_stats(struct file *file,\n--\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c-6360-\tlength = min_t(u32, stats_req-\u003ebuf_len, ATH12K_HTT_STATS_BUF_SIZE);\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c:6361:\treturn simple_read_from_buffer(user_buf, count, ppos, buf, length);\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c-6362-}\n--\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c=6426=static const struct file_operations fops_htt_stats_reset = {\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c-6427-\t.write = ath12k_write_htt_stats_reset,\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c:6428:\t.open = simple_open,\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.c-6429-\t.owner = THIS_MODULE,\n--\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.h=754=struct ath12k_htt_hw_stats_whal_tx_tlv {\n--\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.h-757-\t__le32 hwsch_unpause_wait_tqm_write;\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.h:758:\t__le32 hwsch_dummy_tlv_skipped;\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.h-759-\t__le32 hwsch_misaligned_offset_received;\n--\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.h=978=struct ath12k_htt_tx_de_compl_stats_tlv {\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.h:979:\t__le32 tcl_dummy_frame;\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.h:980:\t__le32 tqm_dummy_frame;\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.h-981-\t__le32 tqm_notify_frame;\n--\ndrivers/net/wireless/ath/ath12k/debugfs_sta.c=139=static ssize_t ath12k_dbg_sta_dump_rx_stats(struct file *file,\n--\ndrivers/net/wireless/ath/ath12k/debugfs_sta.c-241-\tif (len)\ndrivers/net/wireless/ath/ath12k/debugfs_sta.c:242:\t\tret = simple_read_from_buffer(user_buf, count, ppos, buf, len);\ndrivers/net/wireless/ath/ath12k/debugfs_sta.c-243-\treturn ret;\n--\ndrivers/net/wireless/ath/ath12k/debugfs_sta.c=246=static const struct file_operations fops_rx_stats = {\ndrivers/net/wireless/ath/ath12k/debugfs_sta.c-247-\t.read = ath12k_dbg_sta_dump_rx_stats,\ndrivers/net/wireless/ath/ath12k/debugfs_sta.c:248:\t.open = simple_open,\ndrivers/net/wireless/ath/ath12k/debugfs_sta.c-249-\t.owner = THIS_MODULE,\n--\ndrivers/net/wireless/ath/ath12k/debugfs_sta.c=296=static const struct file_operations fops_reset_rx_stats = {\ndrivers/net/wireless/ath/ath12k/debugfs_sta.c-297-\t.write = ath12k_dbg_sta_reset_rx_stats,\ndrivers/net/wireless/ath/ath12k/debugfs_sta.c:298:\t.open = simple_open,\ndrivers/net/wireless/ath/ath12k/debugfs_sta.c-299-\t.owner = THIS_MODULE,\n--\ndrivers/net/wireless/ath/ath12k/dp_peer.c=536=int ath12k_dp_link_peer_assign(struct ath12k_dp *dp, struct ath12k_dp_hw *dp_hw,\n--\ndrivers/net/wireless/ath/ath12k/dp_peer.c-599-\t\t * If old entry addition also fails, then nothing\ndrivers/net/wireless/ath/ath12k/dp_peer.c:600:\t\t * can be done, simply proceed\ndrivers/net/wireless/ath/ath12k/dp_peer.c-601-\t\t */\n--\ndrivers/net/wireless/ath/ath12k/htc.c=558=int ath12k_htc_connect_service(struct ath12k_htc *htc,\n--\ndrivers/net/wireless/ath/ath12k/htc.c-563-\tstruct ath12k_htc_conn_svc *req_msg;\ndrivers/net/wireless/ath/ath12k/htc.c:564:\tstruct ath12k_htc_conn_svc_resp resp_msg_dummy;\ndrivers/net/wireless/ath/ath12k/htc.c:565:\tstruct ath12k_htc_conn_svc_resp *resp_msg = \u0026resp_msg_dummy;\ndrivers/net/wireless/ath/ath12k/htc.c-566-\tenum ath12k_htc_ep_id assigned_eid = ATH12K_HTC_EP_COUNT;\n--\ndrivers/net/wireless/ath/ath12k/htc.c-580-\t\tmax_msg_size = ATH12K_HTC_MAX_CTRL_MSG_LEN;\ndrivers/net/wireless/ath/ath12k/htc.c:581:\t\tmemset(\u0026resp_msg_dummy, 0, sizeof(resp_msg_dummy));\ndrivers/net/wireless/ath/ath12k/htc.c-582-\t\tgoto setup;\n--\ndrivers/net/wireless/ath/ath12k/mac.c=2380=static void ath12k_peer_assoc_h_vht(struct ath12k *ar,\n--\ndrivers/net/wireless/ath/ath12k/mac.c-2421-\ndrivers/net/wireless/ath/ath12k/mac.c:2422:\t/* TODO: similar flags required? */\ndrivers/net/wireless/ath/ath12k/mac.c-2423-\targ-\u003evht_capable = true;\n--\ndrivers/net/wireless/ath/ath12k/mac.c=12625=int ath12k_mac_op_set_frag_threshold(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/ath/ath12k/mac.c-12633-\t *\ndrivers/net/wireless/ath/ath12k/mac.c:12634:\t * Hence implement a dummy callback just to say fragmentation isn't\ndrivers/net/wireless/ath/ath12k/mac.c-12635-\t * supported. This effectively prevents mac80211 from doing frame\n--\ndrivers/net/wireless/ath/ath12k/pci.c=539=static int ath12k_pci_ext_irq_config(struct ath12k_base *ab)\n--\ndrivers/net/wireless/ath/ath12k/pci.c-565-\t\tirq_grp-\u003egrp_id = i;\ndrivers/net/wireless/ath/ath12k/pci.c:566:\t\tirq_grp-\u003enapi_ndev = alloc_netdev_dummy(0);\ndrivers/net/wireless/ath/ath12k/pci.c-567-\t\tif (!irq_grp-\u003enapi_ndev) {\n--\ndrivers/net/wireless/ath/ath12k/pci.c=1538=static int ath12k_pci_probe(struct pci_dev *pdev,\n--\ndrivers/net/wireless/ath/ath12k/pci.c-1638-\ndrivers/net/wireless/ath/ath12k/pci.c:1639:\t/* kernel may allocate a dummy vector before request_irq and\ndrivers/net/wireless/ath/ath12k/pci.c-1640-\t * then allocate a real vector when request_irq is called.\n--\ndrivers/net/wireless/ath/ath12k/reg.c=269=int ath12k_regd_update(struct ath12k *ar, bool init)\n--\ndrivers/net/wireless/ath/ath12k/reg.c-337-\ndrivers/net/wireless/ath/ath12k/reg.c:338:\t/* firmware provides reg rules which are similar for 2 GHz and 5 GHz\ndrivers/net/wireless/ath/ath12k/reg.c-339-\t * pdev but 6 GHz pdev has superset of all rules including rules for\n--\ndrivers/net/wireless/ath/ath12k/wmi.c=10483=ath12k_wmi_send_unit_test_cmd(struct ath12k *ar,\n--\ndrivers/net/wireless/ath/ath12k/wmi.c-10535-\ndrivers/net/wireless/ath/ath12k/wmi.c:10536:int ath12k_wmi_simulate_radar(struct ath12k *ar)\ndrivers/net/wireless/ath/ath12k/wmi.c-10537-{\n--\ndrivers/net/wireless/ath/ath12k/wmi.c-10555-\t * Currently we could pass segment_id(b0 - b1), chirp(b2)\ndrivers/net/wireless/ath/ath12k/wmi.c:10556:\t * freq offset (b3 - b10) to unit test. For simulation\ndrivers/net/wireless/ath/ath12k/wmi.c-10557-\t * purpose this can be set to 0 which is valid.\n--\ndrivers/net/wireless/ath/ath12k/wmi.c=10571=int ath12k_wmi_send_tpc_stats_request(struct ath12k *ar,\n--\ndrivers/net/wireless/ath/ath12k/wmi.c-10638-\ndrivers/net/wireless/ath/ath12k/wmi.c:10639:int ath12k_wmi_simulate_incumbent_signal_interference(struct ath12k *ar,\ndrivers/net/wireless/ath/ath12k/wmi.c-10640-\t\t\t\t\t\t      u32 chan_bw_interference_bitmap)\n--\ndrivers/net/wireless/ath/ath12k/wmi.c-10668-\tath12k_dbg(ar-\u003eab, ATH12K_DBG_WMI,\ndrivers/net/wireless/ath/ath12k/wmi.c:10669:\t\t   \"Triggering incumbent signal interference simulation, interference bitmap: 0x%x\\n\",\ndrivers/net/wireless/ath/ath12k/wmi.c-10670-\t\t   chan_bw_interference_bitmap);\n--\ndrivers/net/wireless/ath/ath12k/wmi.h=3697=enum wmi_sta_ps_mode {\n--\ndrivers/net/wireless/ath/ath12k/wmi.h-3709-/* type, 0:unused 1: ASSERT 2: not respond detect command\ndrivers/net/wireless/ath/ath12k/wmi.h:3710: * delay_time_ms, the simulate will delay time\ndrivers/net/wireless/ath/ath12k/wmi.h-3711- */\n--\ndrivers/net/wireless/ath/ath12k/wmi.h=6607=int ath12k_wmi_send_pdev_set_regdomain(struct ath12k *ar,\ndrivers/net/wireless/ath/ath12k/wmi.h-6608-\t\t\t\t       struct ath12k_wmi_pdev_set_regdomain_arg *arg);\ndrivers/net/wireless/ath/ath12k/wmi.h:6609:int ath12k_wmi_simulate_radar(struct ath12k *ar);\ndrivers/net/wireless/ath/ath12k/wmi.h-6610-int ath12k_wmi_send_twt_enable_cmd(struct ath12k *ar, u32 pdev_id);\n--\ndrivers/net/wireless/ath/ath12k/wmi.h=6720=int ath12k_wmi_send_mlo_link_set_active_cmd(struct ath12k_base *ab,\ndrivers/net/wireless/ath/ath12k/wmi.h-6721-\t\t\t\t\t    struct wmi_mlo_link_set_active_arg *param);\ndrivers/net/wireless/ath/ath12k/wmi.h:6722:int ath12k_wmi_simulate_incumbent_signal_interference(struct ath12k *ar,\ndrivers/net/wireless/ath/ath12k/wmi.h-6723-\t\t\t\t\t\t      u32 chan_bw_interference_bitmap);\n"
}

13/2 2026/07/13 08:03 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 42920
							output: 42
							thoughts: 533
						

Thoughts:
**WorthFuzzing=false: ath12k Patch Review**

Okay, so there's no software emulator for `ath12k`. Wait a minute, this patch came from `syz-cluster`, which means syzkaller found *something*! Either a bug or a test.  I know syzkaller *can* fuzz `ath12k` if the kernel is configured with `CONFIG_PCI` and `CONFIG_ATH12K`, using `syz_pcidev` or `syz_usbdev`. But hold on, `ath12k` uses MHI...does syzkaller have an MHI emulator? No, it doesn't. However, it *could* inject mac80211 frames or interact with mac80211 via `mac80211_hwsim`. 

But if `ath12k` is unreachable, why did syzkaller even apply this patch? Ah, right. My job is to determine if the patch introduces changes that need fuzzing, specifically if it can be reached in virtualized environments.  The instructions are clear: if it's impossible to reach, return `WorthFuzzing=false`.

Let's double-check reachability. Is there any virtual `ath12k` hardware in QEMU? Nope. Can I get to it through `mac80211_hwsim`? No, that's a separate driver.  Okay, what about `syz_pcidev`?

Syzkaller's `syz_pcidev` *could* trigger `ath12k_pci_probe`.  But, `ath12k_pci_probe` calls `ath12k_mhi_register`, which waits for the MHI device to boot. Without a real MHI device or an emulator... it'll fail, and the driver won't register with mac80211.  So even with the PCI probe, it's not going to get past that MHI registration step. I should check `ath12k_mhi_register` to confirm this behavior. Therefore, given the virtualization limitations, and the fact that the MHI device is the critical blocker to the code path, I'll return `WorthFuzzing=false` for this patch series.



14/2 2026/07/13 08:04 tool grepper
0m Args:
{
  "Expression": "ath12k_mhi_register",
  "PathPrefix": "drivers/net/wireless/ath/ath12k/"
}

Results:
{
  "Output": "drivers/net/wireless/ath/ath12k/mhi.c=180=static void ath12k_mhi_op_write_reg(struct mhi_controller *mhi_cntrl,\n--\ndrivers/net/wireless/ath/ath12k/mhi.c-186-\ndrivers/net/wireless/ath/ath12k/mhi.c:187:int ath12k_mhi_register(struct ath12k_pci *ab_pci)\ndrivers/net/wireless/ath/ath12k/mhi.c-188-{\n--\ndrivers/net/wireless/ath/ath12k/mhi.h=35=void ath12k_mhi_stop(struct ath12k_pci *ar_pci, bool is_suspend);\ndrivers/net/wireless/ath/ath12k/mhi.h:36:int ath12k_mhi_register(struct ath12k_pci *ar_pci);\ndrivers/net/wireless/ath/ath12k/mhi.h-37-void ath12k_mhi_unregister(struct ath12k_pci *ar_pci);\n--\ndrivers/net/wireless/ath/ath12k/pci.c=1538=static int ath12k_pci_probe(struct pci_dev *pdev,\n--\ndrivers/net/wireless/ath/ath12k/pci.c-1614-\ndrivers/net/wireless/ath/ath12k/pci.c:1615:\tret = ath12k_mhi_register(ab_pci);\ndrivers/net/wireless/ath/ath12k/pci.c-1616-\tif (ret) {\n"
}

15/2 2026/07/13 08:04 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 44450
							output: 46
							thoughts: 18
						

Thoughts:
Here's my attempt at summarizing the thought process, tailored for an expert audience:

**Diving into `ath12k_mhi_register`**

Okay, time to dig into the `ath12k_mhi_register` function. I need to understand what this does, specifically in the context of the ath12k driver and the MHI interface. Is it registering something, likely a device or resource, with the MHI subsystem? Perhaps it's initializing MHI-specific configuration or setting up communication channels. I'll need to look at the function's arguments, return values, and what resources are being used and how. I'm assuming it's related to the interface between the host driver (ath12k) and the MHI firmware on the Qualcomm chip. Knowing the flow from register to the rest of the code will be important. I need to know how this impacts the overall flow.



16/2 2026/07/13 08:04 tool read-file
0m Args:
{
  "File": "drivers/net/wireless/ath/ath12k/mhi.c",
  "FirstLine": 187,
  "LineCount": 100
}

Results:
{
  "Contents": " 187:\tint ath12k_mhi_register(struct ath12k_pci *ab_pci)\n 188:\t{\n 189:\t\tstruct ath12k_base *ab = ab_pci-\u003eab;\n 190:\t\tstruct mhi_controller *mhi_ctrl;\n 191:\t\tunsigned int board_id;\n 192:\t\tint ret;\n 193:\t\tbool dualmac = false;\n 194:\t\n 195:\t\tmhi_ctrl = mhi_alloc_controller();\n 196:\t\tif (!mhi_ctrl)\n 197:\t\t\treturn -ENOMEM;\n 198:\t\n 199:\t\tab_pci-\u003emhi_pre_cb = MHI_CB_INVALID;\n 200:\t\tab_pci-\u003emhi_ctrl = mhi_ctrl;\n 201:\t\tmhi_ctrl-\u003ecntrl_dev = ab-\u003edev;\n 202:\t\tmhi_ctrl-\u003eregs = ab-\u003emem;\n 203:\t\tmhi_ctrl-\u003ereg_len = ab-\u003emem_len;\n 204:\t\tmhi_ctrl-\u003erddm_size = ab-\u003ehw_params-\u003erddm_size;\n 205:\t\n 206:\t\tif (ab-\u003ehw_params-\u003eotp_board_id_register) {\n 207:\t\t\tboard_id =\n 208:\t\t\t\tath12k_pci_read32(ab, ab-\u003ehw_params-\u003eotp_board_id_register);\n 209:\t\t\tboard_id = u32_get_bits(board_id, OTP_BOARD_ID_MASK);\n 210:\t\n 211:\t\t\tif (!board_id || (board_id == OTP_INVALID_BOARD_ID)) {\n 212:\t\t\t\tath12k_dbg(ab, ATH12K_DBG_BOOT,\n 213:\t\t\t\t\t   \"failed to read board id\\n\");\n 214:\t\t\t} else if (board_id \u0026 OTP_VALID_DUALMAC_BOARD_ID_MASK) {\n 215:\t\t\t\tdualmac = true;\n 216:\t\t\t\tath12k_dbg(ab, ATH12K_DBG_BOOT,\n 217:\t\t\t\t\t   \"dualmac fw selected for board id: %x\\n\", board_id);\n 218:\t\t\t}\n 219:\t\t}\n 220:\t\n 221:\t\tif (dualmac) {\n 222:\t\t\tif (ab-\u003efw.amss_dualmac_data \u0026\u0026 ab-\u003efw.amss_dualmac_len \u003e 0) {\n 223:\t\t\t\t/* use MHI firmware file from firmware-N.bin */\n 224:\t\t\t\tmhi_ctrl-\u003efw_data = ab-\u003efw.amss_dualmac_data;\n 225:\t\t\t\tmhi_ctrl-\u003efw_sz = ab-\u003efw.amss_dualmac_len;\n 226:\t\t\t} else {\n 227:\t\t\t\tath12k_warn(ab, \"dualmac firmware IE not present in firmware-N.bin\\n\");\n 228:\t\t\t\tret = -ENOENT;\n 229:\t\t\t\tgoto free_controller;\n 230:\t\t\t}\n 231:\t\t} else {\n 232:\t\t\tif (ab-\u003efw.amss_data \u0026\u0026 ab-\u003efw.amss_len \u003e 0) {\n 233:\t\t\t\t/* use MHI firmware file from firmware-N.bin */\n 234:\t\t\t\tmhi_ctrl-\u003efw_data = ab-\u003efw.amss_data;\n 235:\t\t\t\tmhi_ctrl-\u003efw_sz = ab-\u003efw.amss_len;\n 236:\t\t\t} else {\n 237:\t\t\t\t/* use the old separate mhi.bin MHI firmware file */\n 238:\t\t\t\tath12k_core_create_firmware_path(ab, ATH12K_AMSS_FILE,\n 239:\t\t\t\t\t\t\t\t ab_pci-\u003eamss_path,\n 240:\t\t\t\t\t\t\t\t sizeof(ab_pci-\u003eamss_path));\n 241:\t\t\t\tmhi_ctrl-\u003efw_image = ab_pci-\u003eamss_path;\n 242:\t\t\t}\n 243:\t\t}\n 244:\t\n 245:\t\tret = ath12k_mhi_get_msi(ab_pci);\n 246:\t\tif (ret) {\n 247:\t\t\tath12k_err(ab, \"failed to get msi for mhi\\n\");\n 248:\t\t\tgoto free_controller;\n 249:\t\t}\n 250:\t\n 251:\t\tif (!test_bit(ATH12K_PCI_FLAG_MULTI_MSI_VECTORS, \u0026ab_pci-\u003eflags))\n 252:\t\t\tmhi_ctrl-\u003eirq_flags = IRQF_SHARED | IRQF_NOBALANCING;\n 253:\t\n 254:\t\tmhi_ctrl-\u003eiova_start = 0;\n 255:\t\tmhi_ctrl-\u003eiova_stop = ab_pci-\u003edma_mask;\n 256:\t\tmhi_ctrl-\u003esbl_size = SZ_512K;\n 257:\t\tmhi_ctrl-\u003eseg_len = SZ_512K;\n 258:\t\tmhi_ctrl-\u003efbc_download = true;\n 259:\t\tmhi_ctrl-\u003eruntime_get = ath12k_mhi_op_runtime_get;\n 260:\t\tmhi_ctrl-\u003eruntime_put = ath12k_mhi_op_runtime_put;\n 261:\t\tmhi_ctrl-\u003estatus_cb = ath12k_mhi_op_status_cb;\n 262:\t\tmhi_ctrl-\u003eread_reg = ath12k_mhi_op_read_reg;\n 263:\t\tmhi_ctrl-\u003ewrite_reg = ath12k_mhi_op_write_reg;\n 264:\t\n 265:\t\tret = mhi_register_controller(mhi_ctrl, ab-\u003ehw_params-\u003emhi_config);\n 266:\t\tif (ret) {\n 267:\t\t\tath12k_err(ab, \"failed to register to mhi bus, err = %d\\n\", ret);\n 268:\t\t\tgoto free_controller;\n 269:\t\t}\n 270:\t\n 271:\t\treturn 0;\n 272:\t\n 273:\tfree_controller:\n 274:\t\tmhi_free_controller(mhi_ctrl);\n 275:\t\tab_pci-\u003emhi_ctrl = NULL;\n 276:\t\treturn ret;\n 277:\t}\n 278:\t\n 279:\tvoid ath12k_mhi_unregister(struct ath12k_pci *ab_pci)\n 280:\t{\n 281:\t\tstruct mhi_controller *mhi_ctrl = ab_pci-\u003emhi_ctrl;\n 282:\t\n 283:\t\tmhi_unregister_controller(mhi_ctrl);\n 284:\t\tkfree(mhi_ctrl-\u003eirq);\n 285:\t\tmhi_free_controller(mhi_ctrl);\n 286:\t\tab_pci-\u003emhi_ctrl = NULL;\n"
}

17/2 2026/07/13 08:04 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 46587
							output: 50
							thoughts: 74
						

Thoughts:
Okay, here's my take on those thoughts, framed as my own mental processing:

**Controller Initialization Conundrum**

Right, so `mhi_register_controller` registers the controller. Seems straightforward enough on the surface. But hold on, the registration is just the first step. Does this registration actually *kick off* the firmware download? That's the critical question here, isn't it?

Generally, I'd expect that the device initialization sequence is triggered by either `mhi_prepare_for_power_up` or `mhi_sync_power_up`, or something similar. These are the usual suspects in managing the power-up and download process. To get to the bottom of this, I need to see exactly where `mhi_sync_power_up` is actually *called* in the code. Tracing that call will tell me how the power-up and device initialization sequence is handled in this particular implementation, and confirm whether the download is kicked off explicitly, or implicitly. This is the next logical step in understanding the overall initialization flow.



18/2 2026/07/13 08:04 tool grepper
0m Args:
{
  "Expression": "mhi_sync_power_up|mhi_async_power_up",
  "PathPrefix": "drivers/net/wireless/ath/ath12k/"
}

Results:
{
  "Output": "drivers/net/wireless/ath/ath12k/mhi.c=406=static int ath12k_mhi_set_state(struct ath12k_pci *ab_pci,\n--\ndrivers/net/wireless/ath/ath12k/mhi.c-438-\t\t */\ndrivers/net/wireless/ath/ath12k/mhi.c:439:\t\tret = mhi_sync_power_up(ab_pci-\u003emhi_ctrl);\ndrivers/net/wireless/ath/ath12k/mhi.c-440-\t\tbreak;\n"
}

19/2 2026/07/13 08:04 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 47099
							output: 44
							thoughts: 21
						

Thoughts:
Here's my thought process, as requested:

**Tracing the Callers of `ath12k_mhi_set_state`**

Alright, time to get my hands dirty. I need to understand the control flow around `ath12k_mhi_set_state`. My initial move is to track down all the functions that directly call this one. This is crucial for grasping how it’s used within the `ath12k` MHI (Multi-Host Interface) driver context. I suspect this function likely manages the state transitions of some part of the MHI subsystem – perhaps power management, initialization, or error recovery. Uncovering the call graph is the first step towards confirming that and understanding the triggers. Let's see what the code reveals.



20/2 2026/07/13 08:04 tool grepper
0m Args:
{
  "Expression": "ath12k_mhi_set_state",
  "PathPrefix": "drivers/net/wireless/ath/ath12k/"
}

Results:
{
  "Output": "drivers/net/wireless/ath/ath12k/mhi.c=289=static char *ath12k_mhi_state_to_str(enum ath12k_mhi_state mhi_state)\n--\ndrivers/net/wireless/ath/ath12k/mhi.c-316-\ndrivers/net/wireless/ath/ath12k/mhi.c:317:static void ath12k_mhi_set_state_bit(struct ath12k_pci *ab_pci,\ndrivers/net/wireless/ath/ath12k/mhi.c-318-\t\t\t\t     enum ath12k_mhi_state mhi_state)\n--\ndrivers/net/wireless/ath/ath12k/mhi.c=356=static int ath12k_mhi_check_state_bit(struct ath12k_pci *ab_pci,\n--\ndrivers/net/wireless/ath/ath12k/mhi.c-405-\ndrivers/net/wireless/ath/ath12k/mhi.c:406:static int ath12k_mhi_set_state(struct ath12k_pci *ab_pci,\ndrivers/net/wireless/ath/ath12k/mhi.c-407-\t\t\t\tenum ath12k_mhi_state mhi_state)\n--\ndrivers/net/wireless/ath/ath12k/mhi.c-471-\ndrivers/net/wireless/ath/ath12k/mhi.c:472:\tath12k_mhi_set_state_bit(ab_pci, mhi_state);\ndrivers/net/wireless/ath/ath12k/mhi.c-473-\n--\ndrivers/net/wireless/ath/ath12k/mhi.c=482=int ath12k_mhi_start(struct ath12k_pci *ab_pci)\n--\ndrivers/net/wireless/ath/ath12k/mhi.c-487-\ndrivers/net/wireless/ath/ath12k/mhi.c:488:\tret = ath12k_mhi_set_state(ab_pci, ATH12K_MHI_INIT);\ndrivers/net/wireless/ath/ath12k/mhi.c-489-\tif (ret)\n--\ndrivers/net/wireless/ath/ath12k/mhi.c-491-\ndrivers/net/wireless/ath/ath12k/mhi.c:492:\tret = ath12k_mhi_set_state(ab_pci, ATH12K_MHI_POWER_ON);\ndrivers/net/wireless/ath/ath12k/mhi.c-493-\tif (ret)\n--\ndrivers/net/wireless/ath/ath12k/mhi.c=502=void ath12k_mhi_stop(struct ath12k_pci *ab_pci, bool is_suspend)\n--\ndrivers/net/wireless/ath/ath12k/mhi.c-508-\tif (is_suspend)\ndrivers/net/wireless/ath/ath12k/mhi.c:509:\t\tath12k_mhi_set_state(ab_pci, ATH12K_MHI_POWER_OFF_KEEP_DEV);\ndrivers/net/wireless/ath/ath12k/mhi.c-510-\telse\ndrivers/net/wireless/ath/ath12k/mhi.c:511:\t\tath12k_mhi_set_state(ab_pci, ATH12K_MHI_POWER_OFF);\ndrivers/net/wireless/ath/ath12k/mhi.c-512-\ndrivers/net/wireless/ath/ath12k/mhi.c:513:\tath12k_mhi_set_state(ab_pci, ATH12K_MHI_DEINIT);\ndrivers/net/wireless/ath/ath12k/mhi.c-514-}\n--\ndrivers/net/wireless/ath/ath12k/mhi.c=516=void ath12k_mhi_suspend(struct ath12k_pci *ab_pci)\ndrivers/net/wireless/ath/ath12k/mhi.c-517-{\ndrivers/net/wireless/ath/ath12k/mhi.c:518:\tath12k_mhi_set_state(ab_pci, ATH12K_MHI_SUSPEND);\ndrivers/net/wireless/ath/ath12k/mhi.c-519-}\n--\ndrivers/net/wireless/ath/ath12k/mhi.c=521=void ath12k_mhi_resume(struct ath12k_pci *ab_pci)\ndrivers/net/wireless/ath/ath12k/mhi.c-522-{\ndrivers/net/wireless/ath/ath12k/mhi.c:523:\tath12k_mhi_set_state(ab_pci, ATH12K_MHI_RESUME);\ndrivers/net/wireless/ath/ath12k/mhi.c-524-}\n"
}

21/2 2026/07/13 08:04 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 48660
							output: 44
							thoughts: 27
						

Thoughts:
Okay, here's my interpretation of that thought process, tailored for an expert audience, and written in the first person:

**My Perspective on the ath12k Driver Power-Up Sequence**

Alright, so I'm focusing on the `ath12k` driver here, specifically its power management aspects.  My understanding is that the `ath12k_mhi_start` function is *crucial* in the driver's initialization sequence, and I'm noting its call stack. It's invoked directly from `ath12k_pci_power_up`. Now, `ath12k_pci_power_up`, as the name suggests, is intimately linked to the PCI bus and the device's power state. This makes perfect sense; `ath12k_mhi_start` must be establishing the fundamental MHI (Multi-Function Hardware Interface) communication channel with the Qualcomm device.

Therefore, this confirms that the PCI power-up flow is directly responsible for setting up the initial link to the Qualcomm chipset, and `ath12k_mhi_start` is likely responsible for the low-level communication and initialization of this interface. I'd suspect that this function handles things like the MHI endpoint discovery, clock configuration, and possibly even the initial firmware download if it's not handled elsewhere. It's the lynchpin, the place where the driver's control is established with the hardware after a power cycle or reset. I'll need to dig deeper into the code of `ath12k_mhi_start` to understand the specifics of how it establishes this connection and ensure that it's handling potential error scenarios gracefully.



22/2 2026/07/13 08:04 tool grepper
0m Args:
{
  "Expression": "ath12k_pci_power_up",
  "PathPrefix": "drivers/net/wireless/ath/ath12k/"
}

Results:
{
  "Output": "drivers/net/wireless/ath/ath12k/pci.c=1326=static void ath12k_pci_coredump_download(struct ath12k_base *ab)\n--\ndrivers/net/wireless/ath/ath12k/pci.c-1437-\ndrivers/net/wireless/ath/ath12k/pci.c:1438:int ath12k_pci_power_up(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/pci.c-1439-{\n--\ndrivers/net/wireless/ath/ath12k/pci.c=1493=static const struct ath12k_hif_ops ath12k_pci_hif_ops = {\n--\ndrivers/net/wireless/ath/ath12k/pci.c-1498-\t.power_down = ath12k_pci_power_down,\ndrivers/net/wireless/ath/ath12k/pci.c:1499:\t.power_up = ath12k_pci_power_up,\ndrivers/net/wireless/ath/ath12k/pci.c-1500-\t.suspend = ath12k_pci_hif_suspend,\n--\ndrivers/net/wireless/ath/ath12k/pci.h=174=int ath12k_pci_start(struct ath12k_base *ab);\ndrivers/net/wireless/ath/ath12k/pci.h:175:int ath12k_pci_power_up(struct ath12k_base *ab);\ndrivers/net/wireless/ath/ath12k/pci.h-176-void ath12k_pci_power_down(struct ath12k_base *ab, bool is_suspend);\n"
}

23/2 2026/07/13 08:04 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 49571
							output: 36
							thoughts: 38
						

Thoughts:
Here's my summary, as though I were thinking through the problem:

**Tracing the ath12k PCI Power-Up Sequence**

Okay, so `ath12k_pci_power_up` is defined as a callback function within the `hif_ops` structure, right? Now the interesting part is, I need to figure out the **call chain**. I'm assuming that it is called when the hardware requires power, so I need to find where `hif_ops->power_up` is actually invoked within the driver's code. I'll need to go hunting for the references, the places that actually *use* that particular member of the `hif_ops` structure. Time to break out the grep, or my IDE's search function. I'll focus on the places where `hif_ops` is used, and look for a direct call or indirect call to the `power_up` function pointer. This should be a fairly contained piece of the driver, so finding it shouldn't be too complex. Let's see... the `hif_ops` struct itself is likely defined in the driver's header files, so I need to navigate to that location and find the reference to the `power_up` function pointer. Let's start digging!



24/2 2026/07/13 08:04 tool grepper
0m Args:
{
  "Expression": "power_up",
  "PathPrefix": "drivers/net/wireless/ath/ath12k/"
}

Results:
{
  "Output": "drivers/net/wireless/ath/ath12k/ahb.c=323=static void ath12k_ahb_stop(struct ath12k_base *ab)\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-332-\ndrivers/net/wireless/ath/ath12k/ahb.c:333:static int ath12k_ahb_power_up(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/ahb.c-334-{\n--\ndrivers/net/wireless/ath/ath12k/ahb.c=705=static const struct ath12k_hif_ops ath12k_ahb_hif_ops = {\n--\ndrivers/net/wireless/ath/ath12k/ahb.c-712-\t.map_service_to_pipe = ath12k_ahb_map_service_to_pipe,\ndrivers/net/wireless/ath/ath12k/ahb.c:713:\t.power_up = ath12k_ahb_power_up,\ndrivers/net/wireless/ath/ath12k/ahb.c-714-\t.power_down = ath12k_ahb_power_down,\n--\ndrivers/net/wireless/ath/ath12k/core.c=181=int ath12k_core_resume_early(struct ath12k_base *ab)\n--\ndrivers/net/wireless/ath/ath12k/core.c-189-\treinit_completion(\u0026ab-\u003erestart_completed);\ndrivers/net/wireless/ath/ath12k/core.c:190:\tret = ath12k_hif_power_up(ab);\ndrivers/net/wireless/ath/ath12k/core.c-191-\tif (ret)\n--\ndrivers/net/wireless/ath/ath12k/core.c=817=static int ath12k_core_soc_create(struct ath12k_base *ab)\n--\ndrivers/net/wireless/ath/ath12k/core.c-833-\ndrivers/net/wireless/ath/ath12k/core.c:834:\tret = ath12k_hif_power_up(ab);\ndrivers/net/wireless/ath/ath12k/core.c-835-\tif (ret) {\n--\ndrivers/net/wireless/ath/ath12k/core.c=1682=static void ath12k_core_reset(struct work_struct *work)\n--\ndrivers/net/wireless/ath/ath12k/core.c-1767-\ndrivers/net/wireless/ath/ath12k/core.c:1768:\t\tath12k_hif_power_up(ab);\ndrivers/net/wireless/ath/ath12k/core.c-1769-\t\tath12k_dbg(ab, ATH12K_DBG_BOOT, \"reset started\\n\");\n--\ndrivers/net/wireless/ath/ath12k/core.h=624=struct ath12k {\n--\ndrivers/net/wireless/ath/ath12k/core.h-769-\tstruct ath12k_fw_stats fw_stats;\ndrivers/net/wireless/ath/ath12k/core.h:770:\tunsigned long last_tx_power_update;\ndrivers/net/wireless/ath/ath12k/core.h-771-\n--\ndrivers/net/wireless/ath/ath12k/hif.h=12=struct ath12k_hif_ops {\n--\ndrivers/net/wireless/ath/ath12k/hif.h-18-\tvoid (*stop)(struct ath12k_base *ab);\ndrivers/net/wireless/ath/ath12k/hif.h:19:\tint (*power_up)(struct ath12k_base *ab);\ndrivers/net/wireless/ath/ath12k/hif.h-20-\tvoid (*power_down)(struct ath12k_base *ab, bool is_suspend);\n--\ndrivers/net/wireless/ath/ath12k/hif.h=130=static inline void ath12k_hif_write32(struct ath12k_base *ab, u32 address,\n--\ndrivers/net/wireless/ath/ath12k/hif.h-135-\ndrivers/net/wireless/ath/ath12k/hif.h:136:static inline int ath12k_hif_power_up(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/hif.h-137-{\ndrivers/net/wireless/ath/ath12k/hif.h:138:\tif (!ab-\u003ehif.ops-\u003epower_up)\ndrivers/net/wireless/ath/ath12k/hif.h-139-\t\treturn -EOPNOTSUPP;\ndrivers/net/wireless/ath/ath12k/hif.h-140-\ndrivers/net/wireless/ath/ath12k/hif.h:141:\treturn ab-\u003ehif.ops-\u003epower_up(ab);\ndrivers/net/wireless/ath/ath12k/hif.h-142-}\n--\ndrivers/net/wireless/ath/ath12k/mac.c=5467=int ath12k_mac_op_get_txpower(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/ath/ath12k/mac.c-5504-\t\t\tmsecs_to_jiffies(ATH12K_PDEV_TX_POWER_REFRESH_TIME_MSECS) +\ndrivers/net/wireless/ath/ath12k/mac.c:5505:\t\t\t\t\t ar-\u003elast_tx_power_update))\ndrivers/net/wireless/ath/ath12k/mac.c-5506-\t\tgoto send_tx_power;\n--\ndrivers/net/wireless/ath/ath12k/mac.c-5527-\tspin_unlock_bh(\u0026ar-\u003edata_lock);\ndrivers/net/wireless/ath/ath12k/mac.c:5528:\tar-\u003elast_tx_power_update = jiffies;\ndrivers/net/wireless/ath/ath12k/mac.c-5529-\tath12k_fw_stats_reset(ar);\n--\ndrivers/net/wireless/ath/ath12k/mhi.c=406=static int ath12k_mhi_set_state(struct ath12k_pci *ab_pci,\n--\ndrivers/net/wireless/ath/ath12k/mhi.c-420-\tcase ATH12K_MHI_INIT:\ndrivers/net/wireless/ath/ath12k/mhi.c:421:\t\tret = mhi_prepare_for_power_up(ab_pci-\u003emhi_ctrl);\ndrivers/net/wireless/ath/ath12k/mhi.c-422-\t\tbreak;\n--\ndrivers/net/wireless/ath/ath12k/mhi.c-438-\t\t */\ndrivers/net/wireless/ath/ath12k/mhi.c:439:\t\tret = mhi_sync_power_up(ab_pci-\u003emhi_ctrl);\ndrivers/net/wireless/ath/ath12k/mhi.c-440-\t\tbreak;\n--\ndrivers/net/wireless/ath/ath12k/pci.c=1326=static void ath12k_pci_coredump_download(struct ath12k_base *ab)\n--\ndrivers/net/wireless/ath/ath12k/pci.c-1437-\ndrivers/net/wireless/ath/ath12k/pci.c:1438:int ath12k_pci_power_up(struct ath12k_base *ab)\ndrivers/net/wireless/ath/ath12k/pci.c-1439-{\n--\ndrivers/net/wireless/ath/ath12k/pci.c=1493=static const struct ath12k_hif_ops ath12k_pci_hif_ops = {\n--\ndrivers/net/wireless/ath/ath12k/pci.c-1498-\t.power_down = ath12k_pci_power_down,\ndrivers/net/wireless/ath/ath12k/pci.c:1499:\t.power_up = ath12k_pci_power_up,\ndrivers/net/wireless/ath/ath12k/pci.c-1500-\t.suspend = ath12k_pci_hif_suspend,\n--\ndrivers/net/wireless/ath/ath12k/pci.h=174=int ath12k_pci_start(struct ath12k_base *ab);\ndrivers/net/wireless/ath/ath12k/pci.h:175:int ath12k_pci_power_up(struct ath12k_base *ab);\ndrivers/net/wireless/ath/ath12k/pci.h-176-void ath12k_pci_power_down(struct ath12k_base *ab, bool is_suspend);\n"
}

25/2 2026/07/13 08:04 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 52304
							output: 41
							thoughts: 508
						

Thoughts:
**Analyzing the `ath12k` Probe Failure**

Okay, so here's the breakdown as I see it. The `ath12k_pci_power_up` function is the initial culprit. It calls `ath12k_mhi_start`, which in turn calls `mhi_prepare_for_power_up` and then `mhi_sync_power_up`. The key problem here is `mhi_sync_power_up`. It's waiting for the device to signal that it has entered the AMSS state, indicating the firmware has successfully loaded and is running. If that signal doesn't come, `mhi_sync_power_up` times out and fails.

That timeout causes a cascade of failures. `ath12k_pci_power_up` fails, `ath12k_core_soc_create` fails, and ultimately, the driver probe fails. It's pretty clear that without a real Qualcomm Wi-Fi device or an extremely sophisticated emulator that can perfectly mimic the MHI state machine and the firmware loading process, there's no way `ath12k` can be probed successfully.

Now, my mind starts racing. I remember syzkaller's `syz_pcidev` function that simulates PCI devices. But does it simulate MHI? No, it's a generic PCI fuzzer. It returns random bytes for MMIO reads. Sure, if `mhi_sync_power_up` is just waiting for a specific bit to be set in a register, the fuzzer might eventually return the right value by chance. However, the MHI protocol is far more complex. The host writes to BHI registers, the device is supposed to DMA the firmware from host memory, and then the device updates a state register. A generic fuzzer has zero chance of fulfilling this protocol by luck.

This means that `ath12k`'s probe will *always* fail in a syzkaller environment, and consequently, the critical `mac80211` callbacks, like `ath12k_mac_op_sta_state`, will never be registered. It's a fundamental limitation.

But wait, if the probe is destined to fail, why did syzkaller apply *that* patch in the first place? I know syzkaller applies patches automatically if they are sent to the mailing list with the syzbot CC'd, or if it's fixing a bug that syzbot has already found.

That leads me to a critical point: syzbot *does* find bugs in `ath12k`! This suggests that even though it can't fully probe, it's still exercising *some* code paths, enough to trigger those bugs. So, let me search for syzbot reports on bugs in `ath12k`. Let's see what's actually getting hit.



26/2 2026/07/13 08:04 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "Reported-by: syzbot",
  "PathPrefix": "drivers/net/wireless/ath/ath12k/"
}

Results:
{
  "error": "no matches"
}

27/2 2026/07/13 08:04 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 53487
							output: 39
							thoughts: 710
						

Thoughts:
**WorthFuzzing=false for this Patch**

Okay, so I'm thinking through this `ath12k` patch and whether it's worth fuzzing. Initially, I was thinking *maybe* `syzbot` just missed some bugs, but the prompt's pretty clear: I need to flag `WorthFuzzing=false` if the changes are unreachable in virtualized environments like GCE or QEMU. And `ath12k` is a hardware-specific driver – it's all about Qualcomm Wi-Fi 7 devices. No software emulation, and it relies on that complex firmware loading through MHI.

So, first I quickly double-checked if there was some hidden `hwsim` or `dummy` mode buried in the code. I searched for "hwsim|sim|dummy" and found a few debugfs commands like `simulate_fw_crash` and others related to emulating interference and radar, but those *still* need the firmware running. Then I found an `alloc_netdev_dummy(0)` call in `ath12k_ahb_config_ext_irq` and `ath12k_pci_ext_irq_config`, but that's just for NAPI. Nothing that could allow it to run without the hardware. Bottom line, there's no `hwsim` for `ath12k`.

Therefore, the code paths in `mac.c`, `dp_htt.c`, `dp_peer.c`, and so on, that this patch touches are *definitely* unreachable in a virtualized environment.

Now, wait a sec, is there *any* way to get `ath12k` fuzzed *through* something like `mac80211_hwsim`? But no, `mac80211_hwsim` is a completely separate driver. It's in `drivers/net/wireless/mac80211_hwsim.c` and simulates a Wi-Fi device at the mac80211 layer. It doesn't use *any* `ath12k` code.

What about `nl80211` testmode? No, those commands are handled by `ath12k_testmode_cmd`, but the driver needs to be probed and the device present.

So, yeah, `WorthFuzzing=false` is the correct answer.

Let's review the prompt to make sure: Yep, the prompt says "return `WorthFuzzing=false` if the patch only contains... code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware". That's `ath12k` to a T.

Just to be absolutely sure, I'll quickly confirm if there is any `CONFIG_ATH12K_SIM` or similar in the Kconfig.

I am confident, `ath12k` is a hardware driver for Qualcomm Wi-Fi 7 devices and requires a physical PCI or AHB device and the firmware to function. It cannot be reached in virtualized environments.



28/2 2026/07/13 08:04 tool grepper
0m Args:
{
  "Expression": "CONFIG_ATH12K",
  "PathPrefix": "drivers/net/wireless/ath/ath12k/"
}

Results:
{
  "Output": "drivers/net/wireless/ath/ath12k/Makefile-1-# SPDX-License-Identifier: BSD-3-Clause-Clear\ndrivers/net/wireless/ath/ath12k/Makefile:2:obj-$(CONFIG_ATH12K) += ath12k.o\ndrivers/net/wireless/ath/ath12k/Makefile-3-ath12k-y += core.o \\\n--\ndrivers/net/wireless/ath/ath12k/Makefile-24-\ndrivers/net/wireless/ath/ath12k/Makefile:25:ath12k-$(CONFIG_ATH12K_AHB) += ahb.o\ndrivers/net/wireless/ath/ath12k/Makefile-26-\ndrivers/net/wireless/ath/ath12k/Makefile:27:obj-$(CONFIG_ATH12K) += wifi7/\ndrivers/net/wireless/ath/ath12k/Makefile-28-\ndrivers/net/wireless/ath/ath12k/Makefile:29:ath12k-$(CONFIG_ATH12K_DEBUGFS) += debugfs.o debugfs_htt_stats.o debugfs_sta.o\ndrivers/net/wireless/ath/ath12k/Makefile-30-ath12k-$(CONFIG_ACPI) += acpi.o\ndrivers/net/wireless/ath/ath12k/Makefile:31:ath12k-$(CONFIG_ATH12K_TRACING) += trace.o\ndrivers/net/wireless/ath/ath12k/Makefile-32-ath12k-$(CONFIG_PM) += wow.o\ndrivers/net/wireless/ath/ath12k/Makefile:33:ath12k-$(CONFIG_ATH12K_COREDUMP) += coredump.o\ndrivers/net/wireless/ath/ath12k/Makefile-34-ath12k-$(CONFIG_NL80211_TESTMODE) += testmode.o\n--\ndrivers/net/wireless/ath/ath12k/core.h=624=struct ath12k {\n--\ndrivers/net/wireless/ath/ath12k/core.h-741-\tu32 cached_ppdu_id;\ndrivers/net/wireless/ath/ath12k/core.h:742:#ifdef CONFIG_ATH12K_DEBUGFS\ndrivers/net/wireless/ath/ath12k/core.h-743-\tstruct ath12k_debug debug;\n--\ndrivers/net/wireless/ath/ath12k/core.h=957=struct ath12k_base {\n--\ndrivers/net/wireless/ath/ath12k/core.h-1055-\tenum ath12k_dfs_region dfs_region;\ndrivers/net/wireless/ath/ath12k/core.h:1056:#ifdef CONFIG_ATH12K_DEBUGFS\ndrivers/net/wireless/ath/ath12k/core.h-1057-\tstruct dentry *debugfs_soc;\n--\ndrivers/net/wireless/ath/ath12k/coredump.h=37=struct ath12k_dump_file_data {\n--\ndrivers/net/wireless/ath/ath12k/coredump.h-59-\ndrivers/net/wireless/ath/ath12k/coredump.h:60:#ifdef CONFIG_ATH12K_COREDUMP\ndrivers/net/wireless/ath/ath12k/coredump.h-61-enum ath12k_fw_crash_dump_type ath12k_coredump_get_dump_type\n--\ndrivers/net/wireless/ath/ath12k/debug.c=55=EXPORT_SYMBOL(__ath12k_warn);\ndrivers/net/wireless/ath/ath12k/debug.c-56-\ndrivers/net/wireless/ath/ath12k/debug.c:57:#ifdef CONFIG_ATH12K_DEBUG\ndrivers/net/wireless/ath/ath12k/debug.c-58-\n--\ndrivers/net/wireless/ath/ath12k/debug.c=108=EXPORT_SYMBOL(ath12k_dbg_dump);\ndrivers/net/wireless/ath/ath12k/debug.c-109-\ndrivers/net/wireless/ath/ath12k/debug.c:110:#endif /* CONFIG_ATH12K_DEBUG */\n--\ndrivers/net/wireless/ath/ath12k/debug.h=41=extern bool ath12k_ftm_mode;\ndrivers/net/wireless/ath/ath12k/debug.h-42-\ndrivers/net/wireless/ath/ath12k/debug.h:43:#ifdef CONFIG_ATH12K_DEBUG\ndrivers/net/wireless/ath/ath12k/debug.h-44-__printf(3, 4) void __ath12k_dbg(struct ath12k_base *ab,\n--\ndrivers/net/wireless/ath/ath12k/debug.h=47=void ath12k_dbg_dump(struct ath12k_base *ab,\n--\ndrivers/net/wireless/ath/ath12k/debug.h-50-\t\t     const void *buf, size_t len);\ndrivers/net/wireless/ath/ath12k/debug.h:51:#else /* CONFIG_ATH12K_DEBUG */\ndrivers/net/wireless/ath/ath12k/debug.h-52-static inline void __ath12k_dbg(struct ath12k_base *ab,\n--\ndrivers/net/wireless/ath/ath12k/debug.h=58=static inline void ath12k_dbg_dump(struct ath12k_base *ab,\n--\ndrivers/net/wireless/ath/ath12k/debug.h-63-}\ndrivers/net/wireless/ath/ath12k/debug.h:64:#endif /* CONFIG_ATH12K_DEBUG */\ndrivers/net/wireless/ath/ath12k/debug.h-65-\n--\ndrivers/net/wireless/ath/ath12k/debugfs.h-9-\ndrivers/net/wireless/ath/ath12k/debugfs.h:10:#ifdef CONFIG_ATH12K_DEBUGFS\ndrivers/net/wireless/ath/ath12k/debugfs.h-11-void ath12k_debugfs_soc_create(struct ath12k_base *ab);\n--\ndrivers/net/wireless/ath/ath12k/debugfs.h=142=static inline void ath12k_debugfs_pdev_create(struct ath12k_base *ab)\n--\ndrivers/net/wireless/ath/ath12k/debugfs.h-144-}\ndrivers/net/wireless/ath/ath12k/debugfs.h:145:#endif /* CONFIG_ATH12K_DEBUGFS */\ndrivers/net/wireless/ath/ath12k/debugfs.h-146-\n--\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.h=26=void ath12k_debugfs_htt_stats_register(struct ath12k *ar);\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.h-27-\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.h:28:#ifdef CONFIG_ATH12K_DEBUGFS\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.h-29-void ath12k_debugfs_htt_ext_stats_handler(struct ath12k_base *ab,\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.h-30-\t\t\t\t\t  struct sk_buff *skb);\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.h:31:#else /* CONFIG_ATH12K_DEBUGFS */\ndrivers/net/wireless/ath/ath12k/debugfs_htt_stats.h-32-static inline void ath12k_debugfs_htt_ext_stats_handler(struct ath12k_base *ab,\n--\ndrivers/net/wireless/ath/ath12k/debugfs_sta.h-14-\ndrivers/net/wireless/ath/ath12k/debugfs_sta.h:15:#ifdef CONFIG_ATH12K_DEBUGFS\ndrivers/net/wireless/ath/ath12k/debugfs_sta.h-16-\ndrivers/net/wireless/ath/ath12k/debugfs_sta.h=17=void ath12k_debugfs_link_sta_op_add(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/ath/ath12k/debugfs_sta.h-21-\ndrivers/net/wireless/ath/ath12k/debugfs_sta.h:22:#endif /* CONFIG_ATH12K_DEBUGFS */\ndrivers/net/wireless/ath/ath12k/debugfs_sta.h-23-\n--\ndrivers/net/wireless/ath/ath12k/pci.c=1212=void ath12k_pci_write32(struct ath12k_base *ab, u32 offset, u32 value)\n--\ndrivers/net/wireless/ath/ath12k/pci.c-1257-\ndrivers/net/wireless/ath/ath12k/pci.c:1258:#ifdef CONFIG_ATH12K_COREDUMP\ndrivers/net/wireless/ath/ath12k/pci.c-1259-static int ath12k_pci_coredump_calculate_size(struct ath12k_base *ab, u32 *dump_seg_sz)\n--\ndrivers/net/wireless/ath/ath12k/pci.c=1493=static const struct ath12k_hif_ops ath12k_pci_hif_ops = {\n--\ndrivers/net/wireless/ath/ath12k/pci.c-1510-\t.panic_handler = ath12k_pci_panic_handler,\ndrivers/net/wireless/ath/ath12k/pci.c:1511:#ifdef CONFIG_ATH12K_COREDUMP\ndrivers/net/wireless/ath/ath12k/pci.c-1512-\t.coredump_download = ath12k_pci_coredump_download,\n--\ndrivers/net/wireless/ath/ath12k/trace.h-14-/* create empty functions when tracing is disabled */\ndrivers/net/wireless/ath/ath12k/trace.h:15:#if !defined(CONFIG_ATH12K_TRACING)\ndrivers/net/wireless/ath/ath12k/trace.h-16-#undef TRACE_EVENT\n--\ndrivers/net/wireless/ath/ath12k/trace.h=18=static inline void trace_ ## name(proto) {}\ndrivers/net/wireless/ath/ath12k/trace.h:19:#endif /* !CONFIG_ATH12K_TRACING || __CHECKER__ */\ndrivers/net/wireless/ath/ath12k/trace.h-20-\n--\ndrivers/net/wireless/ath/ath12k/wifi7/Makefile-1-# SPDX-License-Identifier: BSD-3-Clause-Clear\ndrivers/net/wireless/ath/ath12k/wifi7/Makefile:2:obj-$(CONFIG_ATH12K) += ath12k_wifi7.o\ndrivers/net/wireless/ath/ath12k/wifi7/Makefile-3-ath12k_wifi7-y += core.o \\\n--\ndrivers/net/wireless/ath/ath12k/wifi7/Makefile-19-\ndrivers/net/wireless/ath/ath12k/wifi7/Makefile:20:ath12k_wifi7-$(CONFIG_ATH12K_AHB) += ahb.o\n--\ndrivers/net/wireless/ath/ath12k/wifi7/ahb.h-8-\ndrivers/net/wireless/ath/ath12k/wifi7/ahb.h:9:#ifdef CONFIG_ATH12K_AHB\ndrivers/net/wireless/ath/ath12k/wifi7/ahb.h-10-int ath12k_wifi7_ahb_init(void);\n--\ndrivers/net/wireless/ath/ath12k/wifi7/hw.c=1147=static const struct ieee80211_ops ath12k_ops_wifi7 = {\n--\ndrivers/net/wireless/ath/ath12k/wifi7/hw.c-1195-#endif\ndrivers/net/wireless/ath/ath12k/wifi7/hw.c:1196:#ifdef CONFIG_ATH12K_DEBUGFS\ndrivers/net/wireless/ath/ath12k/wifi7/hw.c-1197-\t.vif_add_debugfs                = ath12k_debugfs_op_vif_add,\n--\ndrivers/net/wireless/ath/ath12k/wifi7/hw.c-1199-\tCFG80211_TESTMODE_CMD(ath12k_tm_cmd)\ndrivers/net/wireless/ath/ath12k/wifi7/hw.c:1200:#ifdef CONFIG_ATH12K_DEBUGFS\ndrivers/net/wireless/ath/ath12k/wifi7/hw.c-1201-\t.link_sta_add_debugfs           = ath12k_debugfs_link_sta_op_add,\n--\ndrivers/net/wireless/ath/ath12k/wmi.c=9654=static void ath12k_wmi_event_teardown_complete(struct ath12k_base *ab,\n--\ndrivers/net/wireless/ath/ath12k/wmi.c-9672-\ndrivers/net/wireless/ath/ath12k/wmi.c:9673:#ifdef CONFIG_ATH12K_DEBUGFS\ndrivers/net/wireless/ath/ath12k/wmi.c-9674-static int ath12k_wmi_tpc_stats_copy_buffer(struct ath12k_base *ab,\n"
}

29/2 2026/07/13 08:04 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 58448
							output: 34
							thoughts: 225
						

Thoughts:
**My Assessment of the Fuzzing Suitability**

Okay, so I'm looking at this and it's clear: there's no way to simulate this, no `CONFIG_ATH12K_SIM` or anything like that. This driver, the `ath12k` one, is *definitely* hardware-dependent. It needs the real deal. So, the `WorthFuzzing=false` tag, right out of the gate, seems spot on.

Let me just solidify this in my mind. Right, it's modifying the `ath12k` driver. That's specifically for Qualcomm Wi-Fi 7 hardware – real PCI or AHB devices, and importantly, needs that firmware to actually *do* anything.  This isn't going to work in some virtualized setup like GCE or QEMU, even with something like `mac80211_hwsim`. 

So, yeah, not worth the effort for Syzkaller.

Hold on, I remember Syzkaller has `syz_pcidev`, which allows you to simulate PCI devices. But, hang on. The more I think about it, `ath12k` does the complex firmware loading via MHI. Syz_pcidev doesn't do that. Does syzkaller even have an MHI emulator?

I need to quickly check if there is any MHI emulator in the kernel to be sure.



30/2 2026/07/13 08:05 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "mhi_emulator|mhi_sim|dummy_mhi",
  "PathPrefix": ""
}

Results:
{
  "error": "no matches"
}

31/2 2026/07/13 08:05 llm patch-evaluator
0m Model:
gemini-3.1-pro-preview

Args:
null

Results:
null

Tokens:
							input: 59027
							output: 110
							thoughts: 80
						

Thoughts:
**My Assessment of the ath12k Driver's Fuzzability**

Okay, so there's no MHI emulator available. That's a critical piece of information.  Without that, it's immediately clear that the `ath12k` driver is effectively inaccessible for fuzzing using syzkaller.  The whole process hinges on the ability to interact with the hardware and load its firmware, and the MHI is central to that.

Since syzkaller relies on environments like GCE or QEMU, which are virtualized and can't handle these specific hardware interactions, I have to conclude that we can't reliably fuzz this driver. My recommendation is to set `WorthFuzzing=false`. The reasoning is straightforward: `ath12k` is a very specific hardware driver. Its dependence on a physical device, and the complex firmware loading process it uses through MHI, are insurmountable obstacles in our current fuzzing setup. There's just no practical path to execute the necessary code within a virtualized environment.



32/2 2026/07/13 08:05 tool set-results
0m Args:
{
  "EnableConfigs": [],
  "FocusSymbols": [],
  "Reasoning": "The patch modifies the ath12k driver, which is a hardware-specific driver for Qualcomm Wi-Fi 7 devices. It requires a physical PCI or AHB device and complex firmware loading via MHI to function. It cannot be reached in virtualized environments like GCE or QEMU, even with software-emulated hardware like mac80211_hwsim.",
  "WorthFuzzing": false
}

Results:
{
  "EnableConfigs": null,
  "FocusSymbols": [],
  "Reasoning": "The patch modifies the ath12k driver, which is a hardware-specific driver for Qualcomm Wi-Fi 7 devices. It requires a physical PCI or AHB device and complex firmware loading via MHI to function. It cannot be reached in virtualized environments like GCE or QEMU, even with software-emulated hardware like mac80211_hwsim.",
  "WorthFuzzing": false
}

LLM Calls Summary:
Total Calls Total Tokens Avg Tokens Total Duration (Seconds) Avg Duration (Seconds)
Tool Calls Summary:
Total Calls Total Duration (Seconds) Avg Duration (Seconds)