AI Trajectory


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

Results:
{
  "EnableConfigs": [
    "CFG80211",
    "MAC80211",
    "MAC80211_HWSIM",
    "ATH11K"
  ],
  "FocusSymbols": [
    "drv_sta_state",
    "sta_apply_parameters",
    "ieee80211_add_station",
    "ieee80211_change_station",
    "sta_info_insert_rcu"
  ],
  "KMSANReasoning": "The patch adds beacon protection and airtime fairness (ATF) support to the ath11k driver and mac80211 subsystem, expands supported cipher suites and key table indices, and exposes WMI services via debugfs.\n\nThere are no uninitialized memory risks or kernel-to-user info-leak vectors introduced:\n- All new struct fields (`beacon_prot` in `struct ath11k_vif`, `airtime_weight` in `struct ath11k_sta`, and the expanded `keys` array in `struct ath11k_peer`) are part of structures allocated via `kzalloc` (or explicitly cleared via `memset` in `ath11k_mac_op_sta_state`) and set to well-defined default constants (`IEEE80211_DEFAULT_AIRTIME_WEIGHT`).\n- In `ath11k_mac_atf_update()`, local structs use designated initializers (zeroing remaining fields) and buffers are allocated using `kcalloc`.\n- WMI command skbs are allocated using `ath11k_wmi_alloc_skb()`, which explicitly zeroes the buffer (`memset(skb-\u003edata, 0, round_len)`).\n- The debugfs attribute `ath11k_wmi_services_show()` iterates over `ab-\u003ewmi_ab.svc_map` (part of kzalloc'd `ath11k_base`) using `for_each_set_bit()` up to `WMI_MAX_EXT2_SERVICE` and prints bit indices; it does not read uninitialized data.\n- Beacon parsing in `ath11k_mac_bcn_prot_enabled()` parses IE buffers; any potential indexing issues or bounds errors would be out-of-bounds reads covered by KASAN.\n\nBecause the changes do not expose uninitialized memory reads or information leaks to userspace, a dedicated KMSAN fuzzing run is not justified; standard KASAN fuzzing is sufficient.",
  "NeedsKMSAN": false,
  "Reasoning": "The patch introduces driver callbacks and core mac80211 support for configuring station airtime weights, alongside ath11k driver support. Although ath11k requires physical hardware, the modifications to the mac80211 core networking subsystem (in net/mac80211/cfg.c, driver-ops.c, driver-ops.h, and sta_info.c) are executable in standard virtualized environments via mac80211_hwsim and nl80211 netlink commands. The new helper drv_sta_set_airtime_weight introduces runtime checks (might_sleep() and lockdep_assert_wiphy()) and is triggered upon station insertion and parameter modification, making it worth fuzzing.",
  "WorthFuzzing": true
}

1/1 2026/10/03 16:08 action read-patch-diff
0m Args:
null

Results:
{
  "PatchDiff": "commit 8ccba6d098a12ba25e898d574a025ed50ab6c191\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate:   Sat Oct 3 16:08:28 2026 +0000\n\n    syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h\nindex a0d725923ef24..bb5f730c88202 100644\n--- a/drivers/net/wireless/ath/ath11k/core.h\n+++ b/drivers/net/wireless/ath/ath11k/core.h\n@@ -408,6 +408,7 @@ struct ath11k_vif {\n \tint txpower;\n \tbool rsnie_present;\n \tbool wpaie_present;\n+\tbool beacon_prot;\n \tbool bcca_zero_sent;\n \tbool do_not_send_tmpl;\n \tstruct ath11k_arp_ns_offload arp_ns_offload;\n@@ -541,6 +542,7 @@ struct ath11k_per_peer_cfr_capture {\n \n struct ath11k_sta {\n \tstruct ath11k_vif *arvif;\n+\tu16 airtime_weight;\n \n \t/* the following are protected by ar-\u003edata_lock */\n \tu32 changed; /* IEEE80211_RC_* */\ndiff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c\nindex 70922612d3fb9..75d2e81c77743 100644\n--- a/drivers/net/wireless/ath/ath11k/debugfs.c\n+++ b/drivers/net/wireless/ath/ath11k/debugfs.c\n@@ -851,6 +851,18 @@ static const struct file_operations fops_sram_dump = {\n \t.llseek = default_llseek,\n };\n \n+static int ath11k_wmi_services_show(struct seq_file *m, void *v)\n+{\n+\tstruct ath11k_base *ab = m-\u003eprivate;\n+\tunsigned int i;\n+\n+\tfor_each_set_bit(i, ab-\u003ewmi_ab.svc_map, WMI_MAX_EXT2_SERVICE)\n+\t\tseq_printf(m, \"%u\\n\", i);\n+\n+\treturn 0;\n+}\n+DEFINE_SHOW_ATTRIBUTE(ath11k_wmi_services);\n+\n int ath11k_debugfs_pdev_create(struct ath11k_base *ab)\n {\n \tif (test_bit(ATH11K_FLAG_REGISTERED, \u0026ab-\u003edev_flags))\n@@ -862,6 +874,9 @@ int ath11k_debugfs_pdev_create(struct ath11k_base *ab)\n \tdebugfs_create_file(\"soc_dp_stats\", 0400, ab-\u003edebugfs_soc, ab,\n \t\t\t    \u0026fops_soc_dp_stats);\n \n+\tdebugfs_create_file(\"wmi_services\", 0400, ab-\u003edebugfs_soc, ab,\n+\t\t\t    \u0026ath11k_wmi_services_fops);\n+\n \tif (ab-\u003ehw_params.sram_dump.start != 0)\n \t\tdebugfs_create_file(\"sram\", 0400, ab-\u003edebugfs_soc, ab,\n \t\t\t\t    \u0026fops_sram_dump);\ndiff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c\nindex c1fa42edd3630..7a03c12d2ebd4 100644\n--- a/drivers/net/wireless/ath/ath11k/mac.c\n+++ b/drivers/net/wireless/ath/ath11k/mac.c\n@@ -1495,6 +1495,44 @@ static int ath11k_mac_remove_vendor_ie(struct sk_buff *skb, unsigned int oui,\n \treturn 0;\n }\n \n+static bool ath11k_mac_ext_capa_bcn_prot(const struct element *ext_capa)\n+{\n+\treturn ext_capa \u0026\u0026 ext_capa-\u003edatalen \u003e= 11 \u0026\u0026\n+\t       (ext_capa-\u003edata[10] \u0026 WLAN_EXT_CAPA11_BCN_PROTECT);\n+}\n+\n+/* Beacon protection covers the whole beacon, so enable it when the\n+ * transmitted BSS or any nontransmitted profile in it advertises it.\n+ */\n+static bool ath11k_mac_bcn_prot_enabled(struct sk_buff *bcn)\n+{\n+\tstruct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)bcn-\u003edata;\n+\tconst u8 *ies = mgmt-\u003eu.beacon.variable;\n+\tint ies_len = skb_tail_pointer(bcn) - ies;\n+\tconst struct element *elem, *profile;\n+\n+\tif (ath11k_mac_ext_capa_bcn_prot(cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY,\n+\t\t\t\t\t\t\t    ies, ies_len)))\n+\t\treturn true;\n+\n+\tfor_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, ies, ies_len) {\n+\t\tif (elem-\u003edatalen \u003c 1)\n+\t\t\tcontinue;\n+\n+\t\tfor_each_element(profile, elem-\u003edata + 1, elem-\u003edatalen - 1) {\n+\t\t\tif (profile-\u003eid != 0)\n+\t\t\t\tcontinue;\n+\n+\t\t\tif (ath11k_mac_ext_capa_bcn_prot(cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY,\n+\t\t\t\t\t\t\t\t\t    profile-\u003edata,\n+\t\t\t\t\t\t\t\t\t    profile-\u003edatalen)))\n+\t\t\t\treturn true;\n+\t\t}\n+\t}\n+\n+\treturn false;\n+}\n+\n static int ath11k_mac_set_vif_params(struct ath11k_vif *arvif,\n \t\t\t\t     struct sk_buff *bcn)\n {\n@@ -1598,6 +1636,7 @@ static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif,\n \t\tparams |= ((!i ? 1 : 0) \u003c\u003c WMI_EMA_FIRST_TMPL_SHIFT);\n \t\tparams |= ((i + 1 == beacons-\u003ecnt ? 1 : 0) \u003c\u003c WMI_EMA_LAST_TMPL_SHIFT);\n \n+\t\ttx_arvif-\u003ebeacon_prot = ath11k_mac_bcn_prot_enabled(beacons-\u003ebcn[i].skb);\n \t\tret = ath11k_wmi_bcn_tmpl(tx_arvif-\u003ear, tx_arvif-\u003evdev_id,\n \t\t\t\t\t  \u0026beacons-\u003ebcn[i].offs,\n \t\t\t\t\t  beacons-\u003ebcn[i].skb, params);\n@@ -1651,6 +1690,7 @@ static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif,\n \t\tgoto free;\n \t}\n \n+\tarvif-\u003ebeacon_prot = ath11k_mac_bcn_prot_enabled(bcn);\n \tret = ath11k_wmi_bcn_tmpl(ar, arvif-\u003evdev_id, \u0026offs, bcn, 0);\n \tif (ret)\n \t\tath11k_warn(ab, \"failed to submit beacon template command: %d\\n\",\n@@ -4412,6 +4452,14 @@ static int ath11k_install_key(struct ath11k_vif *arvif,\n \t\targ.key_cipher = WMI_CIPHER_AES_GCM;\n \t\tkey-\u003eflags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;\n \t\tbreak;\n+\tcase WLAN_CIPHER_SUITE_AES_CMAC:\n+\tcase WLAN_CIPHER_SUITE_BIP_CMAC_256:\n+\t\targ.key_cipher = WMI_CIPHER_AES_CMAC;\n+\t\tbreak;\n+\tcase WLAN_CIPHER_SUITE_BIP_GMAC_128:\n+\tcase WLAN_CIPHER_SUITE_BIP_GMAC_256:\n+\t\targ.key_cipher = WMI_CIPHER_AES_GMAC;\n+\t\tbreak;\n \tdefault:\n \t\tath11k_warn(ar-\u003eab, \"cipher %d is not supported\\n\", key-\u003ecipher);\n \t\treturn -EOPNOTSUPP;\n@@ -4523,11 +4571,10 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,\n \tint ret = 0;\n \tu32 flags = 0;\n \n-\t/* BIP needs to be done in software */\n-\tif (key-\u003ecipher == WLAN_CIPHER_SUITE_AES_CMAC ||\n-\t    key-\u003ecipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||\n-\t    key-\u003ecipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||\n-\t    key-\u003ecipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)\n+\t/* The IGTK protects management frames, which are done in software;\n+\t * only the BIGTK (index 6/7) goes to the firmware, which signs beacons.\n+\t */\n+\tif (key-\u003ekeyidx == 4 || key-\u003ekeyidx == 5)\n \t\treturn 1;\n \n \tif (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, \u0026ar-\u003eab-\u003edev_flags))\n@@ -6685,6 +6732,16 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw)\n \t\tgoto err;\n \t}\n \n+\tif (test_bit(WMI_TLV_SERVICE_ATF, ab-\u003ewmi_ab.svc_map)) {\n+\t\tret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_ATF_DYNAMIC_ENABLE,\n+\t\t\t\t\t\t1, pdev-\u003epdev_id);\n+\t\tif (ret) {\n+\t\t\tath11k_err(ab, \"failed to enable airtime fairness: %d\\n\",\n+\t\t\t\t   ret);\n+\t\t\tgoto err;\n+\t\t}\n+\t}\n+\n \tret = ath11k_wmi_send_dfs_phyerr_offload_enable_cmd(ar, pdev-\u003epdev_id);\n \tif (ret) {\n \t\tath11k_err(ab, \"failed to offload radar detection: %d\\n\",\n@@ -9938,6 +9995,90 @@ static int ath11k_mac_station_remove(struct ath11k *ar,\n \treturn ret;\n }\n \n+#define ATH11K_ATF_PEERS_PER_CMD 32\n+\n+struct ath11k_mac_atf_iter {\n+\tstruct ath11k_wmi_atf_peer_arg *peers;\n+\tu16 *weights;\n+\tu32 num, max, total;\n+};\n+\n+static void ath11k_mac_atf_iter(void *data, struct ieee80211_sta *sta)\n+{\n+\tstruct ath11k_mac_atf_iter *it = data;\n+\tstruct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);\n+\n+\tif (it-\u003enum == it-\u003emax || !arsta-\u003earvif ||\n+\t    arsta-\u003earvif-\u003evdev_type != WMI_VDEV_TYPE_AP)\n+\t\treturn;\n+\n+\tether_addr_copy(it-\u003epeers[it-\u003enum].addr, sta-\u003eaddr);\n+\tit-\u003epeers[it-\u003enum].vdev_id = arsta-\u003earvif-\u003evdev_id;\n+\tit-\u003eweights[it-\u003enum] = arsta-\u003eairtime_weight;\n+\tit-\u003etotal += arsta-\u003eairtime_weight;\n+\tit-\u003enum++;\n+}\n+\n+/* Firmware airtime fairness: give every station of the radio its share of\n+ * the airtime, in proportion to its airtime weight. The firmware schedules\n+ * a station only by the share of its group, so group 0 (every station's)\n+ * gets the whole radio first.\n+ */\n+static int ath11k_mac_atf_update(struct ath11k *ar)\n+{\n+\tstruct ath11k_mac_atf_iter it = { .max = ar-\u003emax_num_stations };\n+\tu32 i, n;\n+\tint ret = 0;\n+\n+\tlockdep_assert_held(\u0026ar-\u003econf_mutex);\n+\n+\tif (!test_bit(WMI_TLV_SERVICE_ATF, ar-\u003eab-\u003ewmi_ab.svc_map))\n+\t\treturn 0;\n+\n+\tit.peers = kcalloc(it.max, sizeof(*it.peers), GFP_KERNEL);\n+\tit.weights = kcalloc(it.max, sizeof(*it.weights), GFP_KERNEL);\n+\tif (!it.peers || !it.weights) {\n+\t\tret = -ENOMEM;\n+\t\tgoto out;\n+\t}\n+\n+\tieee80211_iterate_stations_atomic(ar-\u003ehw, ath11k_mac_atf_iter, \u0026it);\n+\n+\tfor (i = 0; i \u003c it.num; i++)\n+\t\tit.peers[i].units = max_t(u32, 1, div_u64((u64)WMI_ATF_DENOMINATION *\n+\t\t\t\t\t\t\t  it.weights[i], it.total));\n+\n+\tret = ath11k_wmi_send_atf_group(ar, 0, WMI_ATF_DENOMINATION);\n+\tif (ret)\n+\t\tgoto out;\n+\n+\tfor (i = 0; i \u003c it.num; i += n) {\n+\t\tn = min_t(u32, it.num - i, ATH11K_ATF_PEERS_PER_CMD);\n+\t\tret = ath11k_wmi_send_peer_atf_request(ar, \u0026it.peers[i], n,\n+\t\t\t\t\t\t       i + n \u003c it.num);\n+\t\tif (ret)\n+\t\t\tbreak;\n+\t}\n+\n+out:\n+\tkfree(it.weights);\n+\tkfree(it.peers);\n+\treturn ret;\n+}\n+\n+static void ath11k_mac_op_sta_set_airtime_weight(struct ieee80211_hw *hw,\n+\t\t\t\t\t\t struct ieee80211_vif *vif,\n+\t\t\t\t\t\t struct ieee80211_sta *sta, u16 weight)\n+{\n+\tstruct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);\n+\tstruct ath11k *ar = hw-\u003epriv;\n+\n+\tmutex_lock(\u0026ar-\u003econf_mutex);\n+\tarsta-\u003eairtime_weight = weight;\n+\tath11k_mac_atf_update(ar);\n+\tmutex_unlock(\u0026ar-\u003econf_mutex);\n+}\n+\n static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,\n \t\t\t\t   struct ieee80211_vif *vif,\n \t\t\t\t   struct ieee80211_sta *sta,\n@@ -9965,6 +10106,7 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,\n \t    new_state == IEEE80211_STA_NONE) {\n \t\tmemset(arsta, 0, sizeof(*arsta));\n \t\tarsta-\u003earvif = arvif;\n+\t\tarsta-\u003eairtime_weight = IEEE80211_DEFAULT_AIRTIME_WEIGHT;\n \t\tarsta-\u003epeer_ps_state = WMI_PEER_PS_STATE_DISABLED;\n \t\tINIT_WORK(\u0026arsta-\u003eupdate_wk, ath11k_sta_rc_update_wk);\n \t\tINIT_WORK(\u0026arsta-\u003eset_4addr_wk, ath11k_sta_set_4addr_wk);\n@@ -9996,6 +10138,9 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,\n \t\tmutex_unlock(\u0026ar-\u003eab-\u003etbl_mtx_lock);\n \n \t\tath11k_cfr_decrement_peer_count(ar, arsta);\n+\n+\t\tif (vif-\u003etype == NL80211_IFTYPE_AP)\n+\t\t\tath11k_mac_atf_update(ar);\n \t} else if (old_state == IEEE80211_STA_AUTH \u0026\u0026\n \t\t   new_state == IEEE80211_STA_ASSOC \u0026\u0026\n \t\t   (vif-\u003etype == NL80211_IFTYPE_AP ||\n@@ -10005,6 +10150,8 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,\n \t\tif (ret)\n \t\t\tath11k_warn(ar-\u003eab, \"Failed to associate station: %pM\\n\",\n \t\t\t\t    sta-\u003eaddr);\n+\t\telse if (vif-\u003etype == NL80211_IFTYPE_AP)\n+\t\t\tath11k_mac_atf_update(ar);\n \n \t\tspin_lock_bh(\u0026ar-\u003edata_lock);\n \t\t/* Set arsta bw and prev bw */\n@@ -10096,6 +10243,7 @@ static const struct ieee80211_ops ath11k_ops = {\n \t.sta_state                      = ath11k_mac_op_sta_state,\n \t.sta_set_4addr                  = ath11k_mac_op_sta_set_4addr,\n \t.sta_set_txpwr\t\t\t= ath11k_mac_op_sta_set_txpwr,\n+\t.sta_set_airtime_weight\t\t= ath11k_mac_op_sta_set_airtime_weight,\n \t.link_sta_rc_update\t\t= ath11k_mac_op_sta_rc_update,\n \t.conf_tx                        = ath11k_mac_op_conf_tx,\n \t.set_antenna\t\t\t= ath11k_mac_op_set_antenna,\n@@ -10633,6 +10781,14 @@ static int __ath11k_mac_register(struct ath11k *ar)\n \t\twiphy_ext_feature_set(ar-\u003ehw-\u003ewiphy,\n \t\t\t\t      NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);\n \n+\tif (test_bit(WMI_TLV_SERVICE_BEACON_PROTECTION_SUPPORT, ar-\u003eab-\u003ewmi_ab.svc_map))\n+\t\twiphy_ext_feature_set(ar-\u003ehw-\u003ewiphy,\n+\t\t\t\t      NL80211_EXT_FEATURE_BEACON_PROTECTION);\n+\n+\tif (test_bit(WMI_TLV_SERVICE_ATF, ar-\u003eab-\u003ewmi_ab.svc_map))\n+\t\twiphy_ext_feature_set(ar-\u003ehw-\u003ewiphy,\n+\t\t\t\t      NL80211_EXT_FEATURE_AIRTIME_FAIRNESS);\n+\n \tar-\u003ehw-\u003ewiphy-\u003embssid_max_interfaces = TARGET_NUM_VDEVS(ab);\n \tar-\u003ehw-\u003ewiphy-\u003eema_max_profile_periodicity = TARGET_EMA_MAX_PROFILE_PERIOD;\n \ndiff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c\nindex 08fd6795ed9e7..28f5d606ae039 100644\n--- a/drivers/net/wireless/ath/ath11k/wmi.c\n+++ b/drivers/net/wireless/ath/ath11k/wmi.c\n@@ -1811,6 +1811,8 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,\n \tcmd-\u003ebuf_len = bcn-\u003elen;\n \tcmd-\u003embssid_ie_offset = offs-\u003embssid_off;\n \tcmd-\u003eema_params = ema_params;\n+\tif (arvif-\u003ebeacon_prot)\n+\t\tcmd-\u003efeature_enable_bitmap |= WMI_BCN_TMPL_BEACON_PROTECTION_EN;\n \n \tptr = skb-\u003edata + sizeof(*cmd);\n \n@@ -4466,6 +4468,100 @@ int ath11k_wmi_set_hw_mode(struct ath11k_base *ab,\n \treturn 0;\n }\n \n+int ath11k_wmi_send_atf_group(struct ath11k *ar, u32 group_id, u32 units)\n+{\n+\tstruct ath11k_pdev_wmi *wmi = ar-\u003ewmi;\n+\tstruct wmi_atf_ssid_grp_request_cmd *cmd;\n+\tstruct wmi_atf_group_info *grp;\n+\tstruct wmi_tlv *tlv;\n+\tstruct sk_buff *skb;\n+\tint ret;\n+\n+\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd) + TLV_HDR_SIZE + sizeof(*grp));\n+\tif (!skb)\n+\t\treturn -ENOMEM;\n+\n+\tcmd = (struct wmi_atf_ssid_grp_request_cmd *)skb-\u003edata;\n+\tcmd-\u003etlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ATF_SSID_GRP_REQUEST) |\n+\t\t\t  FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);\n+\tcmd-\u003epdev_id = ar-\u003epdev-\u003epdev_id;\n+\n+\ttlv = (struct wmi_tlv *)(skb-\u003edata + sizeof(*cmd));\n+\ttlv-\u003eheader = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) |\n+\t\t      FIELD_PREP(WMI_TLV_LEN, sizeof(*grp));\n+\tgrp = (struct wmi_atf_group_info *)tlv-\u003evalue;\n+\tgrp-\u003etlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ATF_GROUP_INFO) |\n+\t\t\t  FIELD_PREP(WMI_TLV_LEN, sizeof(*grp) - TLV_HDR_SIZE);\n+\tgrp-\u003eatf_group_id = group_id;\n+\tgrp-\u003eatf_group_units = units;\n+\tgrp-\u003eatf_group_flags = WMI_ATF_GROUP_POLICY_FAIR;\n+\n+\tret = ath11k_wmi_cmd_send(wmi, skb, WMI_ATF_SSID_GROUPING_REQUEST_CMDID);\n+\tif (ret) {\n+\t\tath11k_warn(ar-\u003eab, \"failed to send atf group request: %d\\n\", ret);\n+\t\tdev_kfree_skb(skb);\n+\t\treturn ret;\n+\t}\n+\n+\tath11k_dbg(ar-\u003eab, ATH11K_DBG_WMI, \"cmd atf group %u units %u\\n\", group_id, units);\n+\n+\treturn 0;\n+}\n+\n+int ath11k_wmi_send_peer_atf_request(struct ath11k *ar,\n+\t\t\t\t     const struct ath11k_wmi_atf_peer_arg *peers,\n+\t\t\t\t     u32 num_peers, bool more)\n+{\n+\tstruct ath11k_pdev_wmi *wmi = ar-\u003ewmi;\n+\tstruct wmi_peer_atf_request_cmd *cmd;\n+\tstruct wmi_atf_peer_info *info;\n+\tstruct wmi_tlv *tlv;\n+\tstruct sk_buff *skb;\n+\tu32 i, pdev_id = ar-\u003epdev-\u003epdev_id;\n+\tint ret, len;\n+\n+\tlen = sizeof(*cmd) + TLV_HDR_SIZE + num_peers * sizeof(*info);\n+\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, len);\n+\tif (!skb)\n+\t\treturn -ENOMEM;\n+\n+\tcmd = (struct wmi_peer_atf_request_cmd *)skb-\u003edata;\n+\tcmd-\u003etlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_PEER_ATF_REQUEST) |\n+\t\t\t  FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);\n+\tcmd-\u003enum_peers = num_peers;\n+\tcmd-\u003epdev_id = pdev_id;\n+\tcmd-\u003eatf_flags = WMI_PEER_ATF_REQ_FLAG_FULL_UPDATE |\n+\t\t\t WMI_PEER_ATF_REQ_FLAG_PDEV_ID_VALID;\n+\tif (more)\n+\t\tcmd-\u003eatf_flags |= WMI_PEER_ATF_REQ_FLAG_PENDING_CMDS;\n+\n+\ttlv = (struct wmi_tlv *)(skb-\u003edata + sizeof(*cmd));\n+\ttlv-\u003eheader = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) |\n+\t\t      FIELD_PREP(WMI_TLV_LEN, num_peers * sizeof(*info));\n+\tinfo = (struct wmi_atf_peer_info *)tlv-\u003evalue;\n+\n+\tfor (i = 0; i \u003c num_peers; i++, info++) {\n+\t\tinfo-\u003etlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ATF_PEER_INFO) |\n+\t\t\t\t   FIELD_PREP(WMI_TLV_LEN, sizeof(*info) - TLV_HDR_SIZE);\n+\t\tether_addr_copy(info-\u003epeer_macaddr.addr, peers[i].addr);\n+\t\tinfo-\u003eatf_units = peers[i].units;\n+\t\tinfo-\u003evdev_id = peers[i].vdev_id;\n+\t\tinfo-\u003epdev_id = pdev_id;\n+\t}\n+\n+\tret = ath11k_wmi_cmd_send(wmi, skb, WMI_PEER_ATF_REQUEST_CMDID);\n+\tif (ret) {\n+\t\tath11k_warn(ar-\u003eab, \"failed to send peer atf request: %d\\n\", ret);\n+\t\tdev_kfree_skb(skb);\n+\t\treturn ret;\n+\t}\n+\n+\tath11k_dbg(ar-\u003eab, ATH11K_DBG_WMI, \"cmd peer atf request pdev %u peers %u%s\\n\",\n+\t\t   pdev_id, num_peers, more ? \" (more)\" : \"\");\n+\n+\treturn 0;\n+}\n+\n int ath11k_wmi_cmd_init(struct ath11k_base *ab)\n {\n \tstruct ath11k_wmi_base *wmi_ab = \u0026ab-\u003ewmi_ab;\n@@ -4481,6 +4577,9 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)\n \t\t     ab-\u003ewmi_ab.svc_map))\n \t\tconfig.is_reg_cc_ext_event_supported = 1;\n \n+\tif (test_bit(WMI_TLV_SERVICE_ATF, ab-\u003ewmi_ab.svc_map))\n+\t\tconfig.flag1 |= WMI_RSRC_CFG_FLAG1_ATF_CONFIG_ENABLE;\n+\n \tmemcpy(\u0026wmi_ab-\u003ewlan_resource_config, \u0026config, sizeof(config));\n \n \tinit_param.res_cfg = \u0026wmi_ab-\u003ewlan_resource_config;\ndiff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h\nindex b2dade0516ac7..53cce7fd7dff3 100644\n--- a/drivers/net/wireless/ath/ath11k/wmi.h\n+++ b/drivers/net/wireless/ath/ath11k/wmi.h\n@@ -212,6 +212,7 @@ enum wmi_cmd_group {\n \tWMI_GRP_TWT            = 0x3e,\n \tWMI_GRP_MOTION_DET     = 0x3f,\n \tWMI_GRP_SPATIAL_REUSE  = 0x40,\n+\tWMI_GRP_ATM            = 0x45,\n };\n \n #define WMI_CMD_GRP(grp_id) (((grp_id) \u003c\u003c 12) | 0x1)\n@@ -2128,6 +2129,7 @@ enum wmi_tlv_service {\n \tWMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET = 213,\n \tWMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219,\n \tWMI_TLV_SERVICE_EXT2_MSG = 220,\n+\tWMI_TLV_SERVICE_BEACON_PROTECTION_SUPPORT = 244,\n \tWMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT = 246,\n \tWMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249,\n \tWMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253,\n@@ -2353,6 +2355,7 @@ struct wmi_init_cmd {\n } __packed;\n \n #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5)\n+#define WMI_RSRC_CFG_FLAG1_ATF_CONFIG_ENABLE BIT(6)\n #define WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET BIT(9)\n #define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18)\n \n@@ -3628,6 +3631,55 @@ struct ath11k_wmi_p2p_noa_info {\n #define WMI_EMA_FIRST_TMPL_SHIFT          16\n #define WMI_EMA_LAST_TMPL_SHIFT           24\n \n+#define WMI_BCN_TMPL_BEACON_PROTECTION_EN BIT(0)\n+\n+/* Airtime fairness: a share is in parts per thousand of the radio's airtime */\n+#define WMI_ATF_DENOMINATION\t\t\t1000\n+#define WMI_PEER_ATF_REQ_FLAG_FULL_UPDATE\tBIT(0)\n+#define WMI_PEER_ATF_REQ_FLAG_PENDING_CMDS\tBIT(1)\n+#define WMI_PEER_ATF_REQ_FLAG_PDEV_ID_VALID\tBIT(2)\n+#define WMI_ATF_GROUP_POLICY_FAIR\t\t0\n+\n+#define WMI_ATF_SSID_GROUPING_REQUEST_CMDID\tWMI_TLV_CMD(WMI_GRP_ATM)\n+/* Outside enum wmi_tlv_tag: its WMI_TAG_MAX sizes the TLV policy table. */\n+#define WMI_TAG_ATF_SSID_GRP_REQUEST\t\t0x346\n+#define WMI_TAG_ATF_GROUP_INFO\t\t\t0x347\n+\n+struct wmi_atf_ssid_grp_request_cmd {\n+\tu32 tlv_header;\n+\tu32 pdev_id;\n+} __packed;\n+\n+struct wmi_atf_group_info {\n+\tu32 tlv_header;\n+\tu32 atf_group_id;\n+\tu32 atf_group_units;\n+\tu32 atf_group_flags;\n+} __packed;\n+\n+struct wmi_peer_atf_request_cmd {\n+\tu32 tlv_header;\n+\tu32 num_peers;\n+\tu32 pdev_id;\n+\tu32 atf_flags;\n+} __packed;\n+\n+struct wmi_atf_peer_info {\n+\tu32 tlv_header;\n+\tstruct wmi_mac_addr peer_macaddr;\n+\tu32 atf_units;\n+\tu32 atf_groupid;\n+\tu32 atf_units_reserved;\n+\tu32 vdev_id;\n+\tu32 pdev_id;\n+} __packed;\n+\n+struct ath11k_wmi_atf_peer_arg {\n+\tu8 addr[ETH_ALEN];\n+\tu32 vdev_id;\n+\tu32 units;\n+};\n+\n struct wmi_bcn_tmpl_cmd {\n \tu32 tlv_header;\n \tu32 vdev_id;\n@@ -5237,7 +5289,7 @@ enum wmi_ap_ps_peer_param {\n \n #define DISABLE_SIFS_RESPONSE_TRIGGER 0\n \n-#define WMI_MAX_KEY_INDEX   3\n+#define WMI_MAX_KEY_INDEX   7\n #define WMI_MAX_KEY_LEN     32\n \n #define WMI_KEY_PAIRWISE 0x00\n@@ -6450,6 +6502,10 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,\n \t\t\t  bool restart);\n int ath11k_wmi_set_peer_param(struct ath11k *ar, const u8 *peer_addr,\n \t\t\t      u32 vdev_id, u32 param_id, u32 param_val);\n+int ath11k_wmi_send_atf_group(struct ath11k *ar, u32 group_id, u32 units);\n+int ath11k_wmi_send_peer_atf_request(struct ath11k *ar,\n+\t\t\t\t     const struct ath11k_wmi_atf_peer_arg *peers,\n+\t\t\t\t     u32 num_peers, bool more);\n int ath11k_wmi_pdev_set_param(struct ath11k *ar, u32 param_id,\n \t\t\t      u32 param_value, u8 pdev_id);\n int ath11k_wmi_pdev_set_ps_mode(struct ath11k *ar, int vdev_id,\ndiff --git a/include/net/mac80211.h b/include/net/mac80211.h\nindex cb9f8e14b3b62..aab98d92ee5e1 100644\n--- a/include/net/mac80211.h\n+++ b/include/net/mac80211.h\n@@ -4694,6 +4694,8 @@ struct ieee80211_prep_tx_info {\n  * @set_sar_specs: Update the SAR (TX power) settings.\n  * @sta_set_decap_offload: Called to notify the driver when a station is allowed\n  *\tto use rx decapsulation offload\n+ * @sta_set_airtime_weight: Called to notify the driver of a change to a\n+ *\tstation's airtime fairness weight, so it can be programmed in hardware.\n  * @add_twt_setup: Update hw with TWT agreement parameters received from the peer.\n  *\tThis callback allows the hw to check if requested parameters\n  *\tare supported and if there is enough room for a new agreement.\n@@ -5108,6 +5110,9 @@ struct ieee80211_ops {\n \tvoid (*sta_set_decap_offload)(struct ieee80211_hw *hw,\n \t\t\t\t      struct ieee80211_vif *vif,\n \t\t\t\t      struct ieee80211_sta *sta, bool enabled);\n+\tvoid (*sta_set_airtime_weight)(struct ieee80211_hw *hw,\n+\t\t\t\t       struct ieee80211_vif *vif,\n+\t\t\t\t       struct ieee80211_sta *sta, u16 weight);\n \tvoid (*add_twt_setup)(struct ieee80211_hw *hw,\n \t\t\t      struct ieee80211_sta *sta,\n \t\t\t      struct ieee80211_twt_setup *twt);\ndiff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c\nindex bd1a857c812d4..28f99a8f8acce 100644\n--- a/net/mac80211/cfg.c\n+++ b/net/mac80211/cfg.c\n@@ -2616,8 +2616,12 @@ static int sta_apply_parameters(struct ieee80211_local *local,\n \tif (ieee80211_vif_is_mesh(\u0026sdata-\u003evif))\n \t\tsta_apply_mesh_params(local, sta, params);\n \n-\tif (params-\u003eairtime_weight)\n+\tif (params-\u003eairtime_weight) {\n \t\tsta-\u003eairtime_weight = params-\u003eairtime_weight;\n+\t\tif (sta-\u003euploaded)\n+\t\t\tdrv_sta_set_airtime_weight(local, sdata, \u0026sta-\u003esta,\n+\t\t\t\t\t\t   sta-\u003eairtime_weight);\n+\t}\n \n \tif (params-\u003enmi_mac) {\n \t\tstruct ieee80211_sub_if_data *nmi =\ndiff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c\nindex 49753b73aba26..083c2651754fd 100644\n--- a/net/mac80211/driver-ops.c\n+++ b/net/mac80211/driver-ops.c\n@@ -157,6 +157,10 @@ int drv_sta_state(struct ieee80211_local *local,\n \t\t\tsta-\u003euploaded = true;\n \t\t\tif (rcu_access_pointer(sta-\u003esta.rates))\n \t\t\t\tdrv_sta_rate_tbl_update(local, sdata, \u0026sta-\u003esta);\n+\t\t\tif (sta-\u003eairtime_weight != IEEE80211_DEFAULT_AIRTIME_WEIGHT)\n+\t\t\t\tdrv_sta_set_airtime_weight(local, sdata,\n+\t\t\t\t\t\t\t   \u0026sta-\u003esta,\n+\t\t\t\t\t\t\t   sta-\u003eairtime_weight);\n \t\t}\n \t} else if (old_state == IEEE80211_STA_ASSOC \u0026\u0026\n \t\t   new_state == IEEE80211_STA_AUTH) {\ndiff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h\nindex f1c0b87fddd5f..bd5c9d1edcf57 100644\n--- a/net/mac80211/driver-ops.h\n+++ b/net/mac80211/driver-ops.h\n@@ -1633,6 +1633,25 @@ static inline void drv_sta_set_decap_offload(struct ieee80211_local *local,\n \ttrace_drv_return_void(local);\n }\n \n+static inline void drv_sta_set_airtime_weight(struct ieee80211_local *local,\n+\t\t\t\t\t      struct ieee80211_sub_if_data *sdata,\n+\t\t\t\t\t      struct ieee80211_sta *sta,\n+\t\t\t\t\t      u16 weight)\n+{\n+\tsdata = get_bss_sdata(sdata);\n+\n+\tmight_sleep();\n+\tlockdep_assert_wiphy(local-\u003ehw.wiphy);\n+\tif (!check_sdata_in_driver(sdata))\n+\t\treturn;\n+\n+\ttrace_drv_sta_set_airtime_weight(local, sdata, sta, weight);\n+\tif (local-\u003eops-\u003esta_set_airtime_weight)\n+\t\tlocal-\u003eops-\u003esta_set_airtime_weight(\u0026local-\u003ehw, \u0026sdata-\u003evif, sta,\n+\t\t\t\t\t\t   weight);\n+\ttrace_drv_return_void(local);\n+}\n+\n static inline void drv_add_twt_setup(struct ieee80211_local *local,\n \t\t\t\t     struct ieee80211_sub_if_data *sdata,\n \t\t\t\t     struct ieee80211_sta *sta,\ndiff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c\nindex e81cd155197b9..2ce3ef905f15c 100644\n--- a/net/mac80211/sta_info.c\n+++ b/net/mac80211/sta_info.c\n@@ -872,8 +872,13 @@ static int sta_info_insert_drv_state(struct ieee80211_local *local,\n \t\t * Drivers using legacy sta_add/sta_remove callbacks only\n \t\t * get uploaded set to true after sta_add is called.\n \t\t */\n-\t\tif (!local-\u003eops-\u003esta_add)\n+\t\tif (!local-\u003eops-\u003esta_add) {\n \t\t\tsta-\u003euploaded = true;\n+\t\t\tif (sta-\u003eairtime_weight != IEEE80211_DEFAULT_AIRTIME_WEIGHT)\n+\t\t\t\tdrv_sta_set_airtime_weight(local, sdata,\n+\t\t\t\t\t\t\t   \u0026sta-\u003esta,\n+\t\t\t\t\t\t\t   sta-\u003eairtime_weight);\n+\t\t}\n \t\treturn 0;\n \t}\n \ndiff --git a/net/mac80211/trace.h b/net/mac80211/trace.h\nindex 562a4964afa3a..3ae7e78de715c 100644\n--- a/net/mac80211/trace.h\n+++ b/net/mac80211/trace.h\n@@ -2462,6 +2462,33 @@ DEFINE_EVENT(sta_flag_evt, drv_sta_set_decap_offload,\n \tTP_ARGS(local, sdata, sta, enabled)\n );\n \n+TRACE_EVENT(drv_sta_set_airtime_weight,\n+\tTP_PROTO(struct ieee80211_local *local,\n+\t\t struct ieee80211_sub_if_data *sdata,\n+\t\t struct ieee80211_sta *sta, u16 weight),\n+\n+\tTP_ARGS(local, sdata, sta, weight),\n+\n+\tTP_STRUCT__entry(\n+\t\tLOCAL_ENTRY\n+\t\tVIF_ENTRY\n+\t\tSTA_ENTRY\n+\t\t__field(u16, weight)\n+\t),\n+\n+\tTP_fast_assign(\n+\t\tLOCAL_ASSIGN;\n+\t\tVIF_ASSIGN;\n+\t\tSTA_ASSIGN;\n+\t\t__entry-\u003eweight = weight;\n+\t),\n+\n+\tTP_printk(\n+\t\tLOCAL_PR_FMT  VIF_PR_FMT  STA_PR_FMT \" weight:%u\",\n+\t\tLOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry-\u003eweight\n+\t)\n+);\n+\n TRACE_EVENT(drv_add_twt_setup,\n \tTP_PROTO(struct ieee80211_local *local,\n \t\t struct ieee80211_sta *sta,\n"
}

2/1 2026/10/03 16:08 agent patch-evaluator
2m Model:
core

Args:
null

Results:
{
  "EnableConfigs": [
    "CFG80211",
    "MAC80211",
    "MAC80211_HWSIM",
    "ATH11K"
  ],
  "FocusSymbols": [
    "drv_sta_state",
    "sta_apply_parameters",
    "ieee80211_add_station",
    "ieee80211_change_station",
    "sta_info_insert_rcu"
  ],
  "Reasoning": "The patch introduces driver callbacks and core mac80211 support for configuring station airtime weights, alongside ath11k driver support. Although ath11k requires physical hardware, the modifications to the mac80211 core networking subsystem (in net/mac80211/cfg.c, driver-ops.c, driver-ops.h, and sta_info.c) are executable in standard virtualized environments via mac80211_hwsim and nl80211 netlink commands. The new helper drv_sta_set_airtime_weight introduces runtime checks (might_sleep() and lockdep_assert_wiphy()) and is triggered upon station insertion and parameter modification, making it worth fuzzing.",
  "WorthFuzzing": true
}

Instruction:
You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.

IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.

================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.

- REACHABILITY IS THE PRIMARY GATE:
  Fuzzing can only discover bugs in code that can actually execute in standard virtualized
  environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
  If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
  regardless of whether it adds assertions or complex logic.

- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
  Patch authors routinely label changes as "cleanups", "refactorings", or state
  "No functional change intended". Do NOT take these claims at face value.
  Code refactorings that rearrange logic, introduce helper functions, or alter state management
  in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
  If reachable executable code is modified or refactored, it MUST be fuzzed.

- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
  When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
  BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
  Even if the author believes the invariant always holds, fuzzing is essential to verify whether
  an unusual sequence of operations can violate it.

================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:

- Non-kernel and non-executable changes:
  * Modifications to Documentation/, comments, or spelling fixes.
  * User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
    that do not affect the compiled kernel image (vmlinux) or kernel modules.
  * Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
    that do not alter control flow or data structures.
  * Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
  * Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
    ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
  * Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
    physical PCI hot-unplug or manual sysfs driver unbinding.
  * Code paths exclusive to architectures other than the target architecture.

================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
  * Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
    BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
  * Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
  * Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
  * Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).

================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:

- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
  Do NOT list generic, ubiquitous functions called by almost every program in the corpus
  (including, but not limited to: general memory allocators and deallocators, page fault
  and trap handlers, or core synchronization primitives; this is not an exhaustive list).
  Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
  which severely dilutes fuzzing effort away from the actual changes.

- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
  List functions that specifically implement the logic being added or altered, or direct API entrypoints
  for the subsystem feature under review.

- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
  Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
  distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
  If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
  functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).

================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.


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

Prompt:
Target architecture: amd64

For your convenience, here is the diff of the changes:
commit 8ccba6d098a12ba25e898d574a025ed50ab6c191
Author: syz-cluster <triage@syzkaller.com>
Date:   Sat Oct 3 16:08:28 2026 +0000

    syz-cluster: applied patch under review

diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index a0d725923ef24..bb5f730c88202 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -408,6 +408,7 @@ struct ath11k_vif {
 	int txpower;
 	bool rsnie_present;
 	bool wpaie_present;
+	bool beacon_prot;
 	bool bcca_zero_sent;
 	bool do_not_send_tmpl;
 	struct ath11k_arp_ns_offload arp_ns_offload;
@@ -541,6 +542,7 @@ struct ath11k_per_peer_cfr_capture {
 
 struct ath11k_sta {
 	struct ath11k_vif *arvif;
+	u16 airtime_weight;
 
 	/* the following are protected by ar->data_lock */
 	u32 changed; /* IEEE80211_RC_* */
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
index 70922612d3fb9..75d2e81c77743 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
@@ -851,6 +851,18 @@ static const struct file_operations fops_sram_dump = {
 	.llseek = default_llseek,
 };
 
+static int ath11k_wmi_services_show(struct seq_file *m, void *v)
+{
+	struct ath11k_base *ab = m->private;
+	unsigned int i;
+
+	for_each_set_bit(i, ab->wmi_ab.svc_map, WMI_MAX_EXT2_SERVICE)
+		seq_printf(m, "%u\n", i);
+
+	return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(ath11k_wmi_services);
+
 int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
 {
 	if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
@@ -862,6 +874,9 @@ int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
 	debugfs_create_file("soc_dp_stats", 0400, ab->debugfs_soc, ab,
 			    &fops_soc_dp_stats);
 
+	debugfs_create_file("wmi_services", 0400, ab->debugfs_soc, ab,
+			    &ath11k_wmi_services_fops);
+
 	if (ab->hw_params.sram_dump.start != 0)
 		debugfs_create_file("sram", 0400, ab->debugfs_soc, ab,
 				    &fops_sram_dump);
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index c1fa42edd3630..7a03c12d2ebd4 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -1495,6 +1495,44 @@ static int ath11k_mac_remove_vendor_ie(struct sk_buff *skb, unsigned int oui,
 	return 0;
 }
 
+static bool ath11k_mac_ext_capa_bcn_prot(const struct element *ext_capa)
+{
+	return ext_capa && ext_capa->datalen >= 11 &&
+	       (ext_capa->data[10] & WLAN_EXT_CAPA11_BCN_PROTECT);
+}
+
+/* Beacon protection covers the whole beacon, so enable it when the
+ * transmitted BSS or any nontransmitted profile in it advertises it.
+ */
+static bool ath11k_mac_bcn_prot_enabled(struct sk_buff *bcn)
+{
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)bcn->data;
+	const u8 *ies = mgmt->u.beacon.variable;
+	int ies_len = skb_tail_pointer(bcn) - ies;
+	const struct element *elem, *profile;
+
+	if (ath11k_mac_ext_capa_bcn_prot(cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY,
+							    ies, ies_len)))
+		return true;
+
+	for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, ies, ies_len) {
+		if (elem->datalen < 1)
+			continue;
+
+		for_each_element(profile, elem->data + 1, elem->datalen - 1) {
+			if (profile->id != 0)
+				continue;
+
+			if (ath11k_mac_ext_capa_bcn_prot(cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY,
+									    profile->data,
+									    profile->datalen)))
+				return true;
+		}
+	}
+
+	return false;
+}
+
 static int ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
 				     struct sk_buff *bcn)
 {
@@ -1598,6 +1636,7 @@ static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif,
 		params |= ((!i ? 1 : 0) << WMI_EMA_FIRST_TMPL_SHIFT);
 		params |= ((i + 1 == beacons->cnt ? 1 : 0) << WMI_EMA_LAST_TMPL_SHIFT);
 
+		tx_arvif->beacon_prot = ath11k_mac_bcn_prot_enabled(beacons->bcn[i].skb);
 		ret = ath11k_wmi_bcn_tmpl(tx_arvif->ar, tx_arvif->vdev_id,
 					  &beacons->bcn[i].offs,
 					  beacons->bcn[i].skb, params);
@@ -1651,6 +1690,7 @@ static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif,
 		goto free;
 	}
 
+	arvif->beacon_prot = ath11k_mac_bcn_prot_enabled(bcn);
 	ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, 0);
 	if (ret)
 		ath11k_warn(ab, "failed to submit beacon template command: %d\n",
@@ -4412,6 +4452,14 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
 		arg.key_cipher = WMI_CIPHER_AES_GCM;
 		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
 		break;
+	case WLAN_CIPHER_SUITE_AES_CMAC:
+	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+		arg.key_cipher = WMI_CIPHER_AES_CMAC;
+		break;
+	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+		arg.key_cipher = WMI_CIPHER_AES_GMAC;
+		break;
 	default:
 		ath11k_warn(ar->ab, "cipher %d is not supported\n", key->cipher);
 		return -EOPNOTSUPP;
@@ -4523,11 +4571,10 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	int ret = 0;
 	u32 flags = 0;
 
-	/* BIP needs to be done in software */
-	if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
-	    key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
-	    key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||
-	    key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)
+	/* The IGTK protects management frames, which are done in software;
+	 * only the BIGTK (index 6/7) goes to the firmware, which signs beacons.
+	 */
+	if (key->keyidx == 4 || key->keyidx == 5)
 		return 1;
 
 	if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
@@ -6685,6 +6732,16 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw)
 		goto err;
 	}
 
+	if (test_bit(WMI_TLV_SERVICE_ATF, ab->wmi_ab.svc_map)) {
+		ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_ATF_DYNAMIC_ENABLE,
+						1, pdev->pdev_id);
+		if (ret) {
+			ath11k_err(ab, "failed to enable airtime fairness: %d\n",
+				   ret);
+			goto err;
+		}
+	}
+
 	ret = ath11k_wmi_send_dfs_phyerr_offload_enable_cmd(ar, pdev->pdev_id);
 	if (ret) {
 		ath11k_err(ab, "failed to offload radar detection: %d\n",
@@ -9938,6 +9995,90 @@ static int ath11k_mac_station_remove(struct ath11k *ar,
 	return ret;
 }
 
+#define ATH11K_ATF_PEERS_PER_CMD 32
+
+struct ath11k_mac_atf_iter {
+	struct ath11k_wmi_atf_peer_arg *peers;
+	u16 *weights;
+	u32 num, max, total;
+};
+
+static void ath11k_mac_atf_iter(void *data, struct ieee80211_sta *sta)
+{
+	struct ath11k_mac_atf_iter *it = data;
+	struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
+
+	if (it->num == it->max || !arsta->arvif ||
+	    arsta->arvif->vdev_type != WMI_VDEV_TYPE_AP)
+		return;
+
+	ether_addr_copy(it->peers[it->num].addr, sta->addr);
+	it->peers[it->num].vdev_id = arsta->arvif->vdev_id;
+	it->weights[it->num] = arsta->airtime_weight;
+	it->total += arsta->airtime_weight;
+	it->num++;
+}
+
+/* Firmware airtime fairness: give every station of the radio its share of
+ * the airtime, in proportion to its airtime weight. The firmware schedules
+ * a station only by the share of its group, so group 0 (every station's)
+ * gets the whole radio first.
+ */
+static int ath11k_mac_atf_update(struct ath11k *ar)
+{
+	struct ath11k_mac_atf_iter it = { .max = ar->max_num_stations };
+	u32 i, n;
+	int ret = 0;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	if (!test_bit(WMI_TLV_SERVICE_ATF, ar->ab->wmi_ab.svc_map))
+		return 0;
+
+	it.peers = kcalloc(it.max, sizeof(*it.peers), GFP_KERNEL);
+	it.weights = kcalloc(it.max, sizeof(*it.weights), GFP_KERNEL);
+	if (!it.peers || !it.weights) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ieee80211_iterate_stations_atomic(ar->hw, ath11k_mac_atf_iter, &it);
+
+	for (i = 0; i < it.num; i++)
+		it.peers[i].units = max_t(u32, 1, div_u64((u64)WMI_ATF_DENOMINATION *
+							  it.weights[i], it.total));
+
+	ret = ath11k_wmi_send_atf_group(ar, 0, WMI_ATF_DENOMINATION);
+	if (ret)
+		goto out;
+
+	for (i = 0; i < it.num; i += n) {
+		n = min_t(u32, it.num - i, ATH11K_ATF_PEERS_PER_CMD);
+		ret = ath11k_wmi_send_peer_atf_request(ar, &it.peers[i], n,
+						       i + n < it.num);
+		if (ret)
+			break;
+	}
+
+out:
+	kfree(it.weights);
+	kfree(it.peers);
+	return ret;
+}
+
+static void ath11k_mac_op_sta_set_airtime_weight(struct ieee80211_hw *hw,
+						 struct ieee80211_vif *vif,
+						 struct ieee80211_sta *sta, u16 weight)
+{
+	struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
+	struct ath11k *ar = hw->priv;
+
+	mutex_lock(&ar->conf_mutex);
+	arsta->airtime_weight = weight;
+	ath11k_mac_atf_update(ar);
+	mutex_unlock(&ar->conf_mutex);
+}
+
 static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif,
 				   struct ieee80211_sta *sta,
@@ -9965,6 +10106,7 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
 	    new_state == IEEE80211_STA_NONE) {
 		memset(arsta, 0, sizeof(*arsta));
 		arsta->arvif = arvif;
+		arsta->airtime_weight = IEEE80211_DEFAULT_AIRTIME_WEIGHT;
 		arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
 		INIT_WORK(&arsta->update_wk, ath11k_sta_rc_update_wk);
 		INIT_WORK(&arsta->set_4addr_wk, ath11k_sta_set_4addr_wk);
@@ -9996,6 +10138,9 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
 		mutex_unlock(&ar->ab->tbl_mtx_lock);
 
 		ath11k_cfr_decrement_peer_count(ar, arsta);
+
+		if (vif->type == NL80211_IFTYPE_AP)
+			ath11k_mac_atf_update(ar);
 	} else if (old_state == IEEE80211_STA_AUTH &&
 		   new_state == IEEE80211_STA_ASSOC &&
 		   (vif->type == NL80211_IFTYPE_AP ||
@@ -10005,6 +10150,8 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
 		if (ret)
 			ath11k_warn(ar->ab, "Failed to associate station: %pM\n",
 				    sta->addr);
+		else if (vif->type == NL80211_IFTYPE_AP)
+			ath11k_mac_atf_update(ar);
 
 		spin_lock_bh(&ar->data_lock);
 		/* Set arsta bw and prev bw */
@@ -10096,6 +10243,7 @@ static const struct ieee80211_ops ath11k_ops = {
 	.sta_state                      = ath11k_mac_op_sta_state,
 	.sta_set_4addr                  = ath11k_mac_op_sta_set_4addr,
 	.sta_set_txpwr			= ath11k_mac_op_sta_set_txpwr,
+	.sta_set_airtime_weight		= ath11k_mac_op_sta_set_airtime_weight,
 	.link_sta_rc_update		= ath11k_mac_op_sta_rc_update,
 	.conf_tx                        = ath11k_mac_op_conf_tx,
 	.set_antenna			= ath11k_mac_op_set_antenna,
@@ -10633,6 +10781,14 @@ static int __ath11k_mac_register(struct ath11k *ar)
 		wiphy_ext_feature_set(ar->hw->wiphy,
 				      NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
 
+	if (test_bit(WMI_TLV_SERVICE_BEACON_PROTECTION_SUPPORT, ar->ab->wmi_ab.svc_map))
+		wiphy_ext_feature_set(ar->hw->wiphy,
+				      NL80211_EXT_FEATURE_BEACON_PROTECTION);
+
+	if (test_bit(WMI_TLV_SERVICE_ATF, ar->ab->wmi_ab.svc_map))
+		wiphy_ext_feature_set(ar->hw->wiphy,
+				      NL80211_EXT_FEATURE_AIRTIME_FAIRNESS);
+
 	ar->hw->wiphy->mbssid_max_interfaces = TARGET_NUM_VDEVS(ab);
 	ar->hw->wiphy->ema_max_profile_periodicity = TARGET_EMA_MAX_PROFILE_PERIOD;
 
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 08fd6795ed9e7..28f5d606ae039 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -1811,6 +1811,8 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
 	cmd->buf_len = bcn->len;
 	cmd->mbssid_ie_offset = offs->mbssid_off;
 	cmd->ema_params = ema_params;
+	if (arvif->beacon_prot)
+		cmd->feature_enable_bitmap |= WMI_BCN_TMPL_BEACON_PROTECTION_EN;
 
 	ptr = skb->data + sizeof(*cmd);
 
@@ -4466,6 +4468,100 @@ int ath11k_wmi_set_hw_mode(struct ath11k_base *ab,
 	return 0;
 }
 
+int ath11k_wmi_send_atf_group(struct ath11k *ar, u32 group_id, u32 units)
+{
+	struct ath11k_pdev_wmi *wmi = ar->wmi;
+	struct wmi_atf_ssid_grp_request_cmd *cmd;
+	struct wmi_atf_group_info *grp;
+	struct wmi_tlv *tlv;
+	struct sk_buff *skb;
+	int ret;
+
+	skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd) + TLV_HDR_SIZE + sizeof(*grp));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_atf_ssid_grp_request_cmd *)skb->data;
+	cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ATF_SSID_GRP_REQUEST) |
+			  FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
+	cmd->pdev_id = ar->pdev->pdev_id;
+
+	tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd));
+	tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) |
+		      FIELD_PREP(WMI_TLV_LEN, sizeof(*grp));
+	grp = (struct wmi_atf_group_info *)tlv->value;
+	grp->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ATF_GROUP_INFO) |
+			  FIELD_PREP(WMI_TLV_LEN, sizeof(*grp) - TLV_HDR_SIZE);
+	grp->atf_group_id = group_id;
+	grp->atf_group_units = units;
+	grp->atf_group_flags = WMI_ATF_GROUP_POLICY_FAIR;
+
+	ret = ath11k_wmi_cmd_send(wmi, skb, WMI_ATF_SSID_GROUPING_REQUEST_CMDID);
+	if (ret) {
+		ath11k_warn(ar->ab, "failed to send atf group request: %d\n", ret);
+		dev_kfree_skb(skb);
+		return ret;
+	}
+
+	ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd atf group %u units %u\n", group_id, units);
+
+	return 0;
+}
+
+int ath11k_wmi_send_peer_atf_request(struct ath11k *ar,
+				     const struct ath11k_wmi_atf_peer_arg *peers,
+				     u32 num_peers, bool more)
+{
+	struct ath11k_pdev_wmi *wmi = ar->wmi;
+	struct wmi_peer_atf_request_cmd *cmd;
+	struct wmi_atf_peer_info *info;
+	struct wmi_tlv *tlv;
+	struct sk_buff *skb;
+	u32 i, pdev_id = ar->pdev->pdev_id;
+	int ret, len;
+
+	len = sizeof(*cmd) + TLV_HDR_SIZE + num_peers * sizeof(*info);
+	skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_peer_atf_request_cmd *)skb->data;
+	cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_PEER_ATF_REQUEST) |
+			  FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
+	cmd->num_peers = num_peers;
+	cmd->pdev_id = pdev_id;
+	cmd->atf_flags = WMI_PEER_ATF_REQ_FLAG_FULL_UPDATE |
+			 WMI_PEER_ATF_REQ_FLAG_PDEV_ID_VALID;
+	if (more)
+		cmd->atf_flags |= WMI_PEER_ATF_REQ_FLAG_PENDING_CMDS;
+
+	tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd));
+	tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) |
+		      FIELD_PREP(WMI_TLV_LEN, num_peers * sizeof(*info));
+	info = (struct wmi_atf_peer_info *)tlv->value;
+
+	for (i = 0; i < num_peers; i++, info++) {
+		info->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ATF_PEER_INFO) |
+				   FIELD_PREP(WMI_TLV_LEN, sizeof(*info) - TLV_HDR_SIZE);
+		ether_addr_copy(info->peer_macaddr.addr, peers[i].addr);
+		info->atf_units = peers[i].units;
+		info->vdev_id = peers[i].vdev_id;
+		info->pdev_id = pdev_id;
+	}
+
+	ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PEER_ATF_REQUEST_CMDID);
+	if (ret) {
+		ath11k_warn(ar->ab, "failed to send peer atf request: %d\n", ret);
+		dev_kfree_skb(skb);
+		return ret;
+	}
+
+	ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd peer atf request pdev %u peers %u%s\n",
+		   pdev_id, num_peers, more ? " (more)" : "");
+
+	return 0;
+}
+
 int ath11k_wmi_cmd_init(struct ath11k_base *ab)
 {
 	struct ath11k_wmi_base *wmi_ab = &ab->wmi_ab;
@@ -4481,6 +4577,9 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
 		     ab->wmi_ab.svc_map))
 		config.is_reg_cc_ext_event_supported = 1;
 
+	if (test_bit(WMI_TLV_SERVICE_ATF, ab->wmi_ab.svc_map))
+		config.flag1 |= WMI_RSRC_CFG_FLAG1_ATF_CONFIG_ENABLE;
+
 	memcpy(&wmi_ab->wlan_resource_config, &config, sizeof(config));
 
 	init_param.res_cfg = &wmi_ab->wlan_resource_config;
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index b2dade0516ac7..53cce7fd7dff3 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -212,6 +212,7 @@ enum wmi_cmd_group {
 	WMI_GRP_TWT            = 0x3e,
 	WMI_GRP_MOTION_DET     = 0x3f,
 	WMI_GRP_SPATIAL_REUSE  = 0x40,
+	WMI_GRP_ATM            = 0x45,
 };
 
 #define WMI_CMD_GRP(grp_id) (((grp_id) << 12) | 0x1)
@@ -2128,6 +2129,7 @@ enum wmi_tlv_service {
 	WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET = 213,
 	WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219,
 	WMI_TLV_SERVICE_EXT2_MSG = 220,
+	WMI_TLV_SERVICE_BEACON_PROTECTION_SUPPORT = 244,
 	WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT = 246,
 	WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249,
 	WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253,
@@ -2353,6 +2355,7 @@ struct wmi_init_cmd {
 } __packed;
 
 #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5)
+#define WMI_RSRC_CFG_FLAG1_ATF_CONFIG_ENABLE BIT(6)
 #define WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET BIT(9)
 #define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18)
 
@@ -3628,6 +3631,55 @@ struct ath11k_wmi_p2p_noa_info {
 #define WMI_EMA_FIRST_TMPL_SHIFT          16
 #define WMI_EMA_LAST_TMPL_SHIFT           24
 
+#define WMI_BCN_TMPL_BEACON_PROTECTION_EN BIT(0)
+
+/* Airtime fairness: a share is in parts per thousand of the radio's airtime */
+#define WMI_ATF_DENOMINATION			1000
+#define WMI_PEER_ATF_REQ_FLAG_FULL_UPDATE	BIT(0)
+#define WMI_PEER_ATF_REQ_FLAG_PENDING_CMDS	BIT(1)
+#define WMI_PEER_ATF_REQ_FLAG_PDEV_ID_VALID	BIT(2)
+#define WMI_ATF_GROUP_POLICY_FAIR		0
+
+#define WMI_ATF_SSID_GROUPING_REQUEST_CMDID	WMI_TLV_CMD(WMI_GRP_ATM)
+/* Outside enum wmi_tlv_tag: its WMI_TAG_MAX sizes the TLV policy table. */
+#define WMI_TAG_ATF_SSID_GRP_REQUEST		0x346
+#define WMI_TAG_ATF_GROUP_INFO			0x347
+
+struct wmi_atf_ssid_grp_request_cmd {
+	u32 tlv_header;
+	u32 pdev_id;
+} __packed;
+
+struct wmi_atf_group_info {
+	u32 tlv_header;
+	u32 atf_group_id;
+	u32 atf_group_units;
+	u32 atf_group_flags;
+} __packed;
+
+struct wmi_peer_atf_request_cmd {
+	u32 tlv_header;
+	u32 num_peers;
+	u32 pdev_id;
+	u32 atf_flags;
+} __packed;
+
+struct wmi_atf_peer_info {
+	u32 tlv_header;
+	struct wmi_mac_addr peer_macaddr;
+	u32 atf_units;
+	u32 atf_groupid;
+	u32 atf_units_reserved;
+	u32 vdev_id;
+	u32 pdev_id;
+} __packed;
+
+struct ath11k_wmi_atf_peer_arg {
+	u8 addr[ETH_ALEN];
+	u32 vdev_id;
+	u32 units;
+};
+
 struct wmi_bcn_tmpl_cmd {
 	u32 tlv_header;
 	u32 vdev_id;
@@ -5237,7 +5289,7 @@ enum wmi_ap_ps_peer_param {
 
 #define DISABLE_SIFS_RESPONSE_TRIGGER 0
 
-#define WMI_MAX_KEY_INDEX   3
+#define WMI_MAX_KEY_INDEX   7
 #define WMI_MAX_KEY_LEN     32
 
 #define WMI_KEY_PAIRWISE 0x00
@@ -6450,6 +6502,10 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
 			  bool restart);
 int ath11k_wmi_set_peer_param(struct ath11k *ar, const u8 *peer_addr,
 			      u32 vdev_id, u32 param_id, u32 param_val);
+int ath11k_wmi_send_atf_group(struct ath11k *ar, u32 group_id, u32 units);
+int ath11k_wmi_send_peer_atf_request(struct ath11k *ar,
+				     const struct ath11k_wmi_atf_peer_arg *peers,
+				     u32 num_peers, bool more);
 int ath11k_wmi_pdev_set_param(struct ath11k *ar, u32 param_id,
 			      u32 param_value, u8 pdev_id);
 int ath11k_wmi_pdev_set_ps_mode(struct ath11k *ar, int vdev_id,
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index cb9f8e14b3b62..aab98d92ee5e1 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4694,6 +4694,8 @@ struct ieee80211_prep_tx_info {
  * @set_sar_specs: Update the SAR (TX power) settings.
  * @sta_set_decap_offload: Called to notify the driver when a station is allowed
  *	to use rx decapsulation offload
+ * @sta_set_airtime_weight: Called to notify the driver of a change to a
+ *	station's airtime fairness weight, so it can be programmed in hardware.
  * @add_twt_setup: Update hw with TWT agreement parameters received from the peer.
  *	This callback allows the hw to check if requested parameters
  *	are supported and if there is enough room for a new agreement.
@@ -5108,6 +5110,9 @@ struct ieee80211_ops {
 	void (*sta_set_decap_offload)(struct ieee80211_hw *hw,
 				      struct ieee80211_vif *vif,
 				      struct ieee80211_sta *sta, bool enabled);
+	void (*sta_set_airtime_weight)(struct ieee80211_hw *hw,
+				       struct ieee80211_vif *vif,
+				       struct ieee80211_sta *sta, u16 weight);
 	void (*add_twt_setup)(struct ieee80211_hw *hw,
 			      struct ieee80211_sta *sta,
 			      struct ieee80211_twt_setup *twt);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index bd1a857c812d4..28f99a8f8acce 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2616,8 +2616,12 @@ static int sta_apply_parameters(struct ieee80211_local *local,
 	if (ieee80211_vif_is_mesh(&sdata->vif))
 		sta_apply_mesh_params(local, sta, params);
 
-	if (params->airtime_weight)
+	if (params->airtime_weight) {
 		sta->airtime_weight = params->airtime_weight;
+		if (sta->uploaded)
+			drv_sta_set_airtime_weight(local, sdata, &sta->sta,
+						   sta->airtime_weight);
+	}
 
 	if (params->nmi_mac) {
 		struct ieee80211_sub_if_data *nmi =
diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
index 49753b73aba26..083c2651754fd 100644
--- a/net/mac80211/driver-ops.c
+++ b/net/mac80211/driver-ops.c
@@ -157,6 +157,10 @@ int drv_sta_state(struct ieee80211_local *local,
 			sta->uploaded = true;
 			if (rcu_access_pointer(sta->sta.rates))
 				drv_sta_rate_tbl_update(local, sdata, &sta->sta);
+			if (sta->airtime_weight != IEEE80211_DEFAULT_AIRTIME_WEIGHT)
+				drv_sta_set_airtime_weight(local, sdata,
+							   &sta->sta,
+							   sta->airtime_weight);
 		}
 	} else if (old_state == IEEE80211_STA_ASSOC &&
 		   new_state == IEEE80211_STA_AUTH) {
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index f1c0b87fddd5f..bd5c9d1edcf57 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1633,6 +1633,25 @@ static inline void drv_sta_set_decap_offload(struct ieee80211_local *local,
 	trace_drv_return_void(local);
 }
 
+static inline void drv_sta_set_airtime_weight(struct ieee80211_local *local,
+					      struct ieee80211_sub_if_data *sdata,
+					      struct ieee80211_sta *sta,
+					      u16 weight)
+{
+	sdata = get_bss_sdata(sdata);
+
+	might_sleep();
+	lockdep_assert_wiphy(local->hw.wiphy);
+	if (!check_sdata_in_driver(sdata))
+		return;
+
+	trace_drv_sta_set_airtime_weight(local, sdata, sta, weight);
+	if (local->ops->sta_set_airtime_weight)
+		local->ops->sta_set_airtime_weight(&local->hw, &sdata->vif, sta,
+						   weight);
+	trace_drv_return_void(local);
+}
+
 static inline void drv_add_twt_setup(struct ieee80211_local *local,
 				     struct ieee80211_sub_if_data *sdata,
 				     struct ieee80211_sta *sta,
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index e81cd155197b9..2ce3ef905f15c 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -872,8 +872,13 @@ static int sta_info_insert_drv_state(struct ieee80211_local *local,
 		 * Drivers using legacy sta_add/sta_remove callbacks only
 		 * get uploaded set to true after sta_add is called.
 		 */
-		if (!local->ops->sta_add)
+		if (!local->ops->sta_add) {
 			sta->uploaded = true;
+			if (sta->airtime_weight != IEEE80211_DEFAULT_AIRTIME_WEIGHT)
+				drv_sta_set_airtime_weight(local, sdata,
+							   &sta->sta,
+							   sta->airtime_weight);
+		}
 		return 0;
 	}
 
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 562a4964afa3a..3ae7e78de715c 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -2462,6 +2462,33 @@ DEFINE_EVENT(sta_flag_evt, drv_sta_set_decap_offload,
 	TP_ARGS(local, sdata, sta, enabled)
 );
 
+TRACE_EVENT(drv_sta_set_airtime_weight,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sub_if_data *sdata,
+		 struct ieee80211_sta *sta, u16 weight),
+
+	TP_ARGS(local, sdata, sta, weight),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		VIF_ENTRY
+		STA_ENTRY
+		__field(u16, weight)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		VIF_ASSIGN;
+		STA_ASSIGN;
+		__entry->weight = weight;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT  VIF_PR_FMT  STA_PR_FMT " weight:%u",
+		LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->weight
+	)
+);
+
 TRACE_EVENT(drv_add_twt_setup,
 	TP_PROTO(struct ieee80211_local *local,
 		 struct ieee80211_sta *sta,

3/2 2026/10/03 16:08 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 13949
							output: 42
							thoughts: 2428
						

Thoughts:
**Analysis of the Patch Series for Fuzzing Eligibility**

Okay, let's break this down systematically. My primary concern here is determining if this patch series is suitable for fuzzing, given the instructions. The guiding principle is reachability in standard virtualized environments.

First, I examine the instructions. They clearly state that code must be *reachable* to warrant fuzzing, particularly emphasizing "reachable drivers and protocols accessible via virtual buses". That's key. We avoid blindly trusting claims of "no functional change" or "refactoring." Assertions and modifications in reachable code are always worth a look. The negative criteria section gives us a list of "no go" areas; specifically, hardware requiring physical ASICs or PCI-e cards not emulated in standard QEMU.

Next, I need to understand what code has changed. The files listed point directly to the `ath11k` wireless driver and its core components, along with some critical `mac80211` files. My immediate thought is, *is this a complete dependency, or is this related to a larger component?*

The presence of `net/mac80211/` files is a significant clue. `mac80211` is the Linux wireless core, and that opens up a lot of potential. Specifically, `mac80211_hwsim` and nl80211 are the important pieces here.

The crucial question is whether the changes in this patch can be reached through `nl80211` or `mac80211_hwsim`. Let's dig deeper into the code modifications. The changes center around `sta_apply_parameters` and the `drv_sta_set_airtime_weight` function which looks like a driver-specific callout. I need to understand what triggers the execution of this `drv_sta_set_airtime_weight`. It looks like it is called from `net/mac80211/cfg.c` via the `NL80211_CMD_SET_STATION` command.

The critical piece here is whether `ath11k` itself is reachable in standard QEMU. It appears to require specialized hardware, so it is probably a non-starter according to the fuzzing rules. However, the changes to the mac80211 core *might* be reachable! The code changes include `might_sleep()`, `lockdep_assert_wiphy()`, `check_sdata_in_driver()`, and tracepoints in `drv_sta_set_airtime_weight`, which could be interesting to fuzz.

I need to determine if `drv_sta_set_airtime_weight` is actually *called* through a virtualized environment. The code looks like it is called directly via `sta_apply_parameters`, which would be called when setting parameters for a station, such as with `NL80211_CMD_SET_STATION`.

The function has important implications: `might_sleep()` indicates a potential for blocking operations and context switching. `lockdep_assert_wiphy()` could indicate locking issues in the wiphy or data race problems. I need to assess whether these functions are called from an atomic context.

To conclude, the `net/mac80211` changes *are* worth fuzzing due to the fact that those changes may be exercised by the fuzzer.



4/2 2026/10/03 16:08 tool read-file
0m Args:
{
  "File": "net/mac80211/driver-ops.c",
  "FirstLine": 140,
  "LineCount": 40
}

Results:
{
  "Contents": " 140:\t\tint ret = 0;\n 141:\t\n 142:\t\tmight_sleep();\n 143:\t\tlockdep_assert_wiphy(local-\u003ehw.wiphy);\n 144:\t\n 145:\t\tsdata = get_bss_sdata(sdata);\n 146:\t\tif (!check_sdata_in_driver(sdata))\n 147:\t\t\treturn -EIO;\n 148:\t\n 149:\t\ttrace_drv_sta_state(local, sdata, \u0026sta-\u003esta, old_state, new_state);\n 150:\t\tif (local-\u003eops-\u003esta_state) {\n 151:\t\t\tret = local-\u003eops-\u003esta_state(\u0026local-\u003ehw, \u0026sdata-\u003evif, \u0026sta-\u003esta,\n 152:\t\t\t\t\t\t    old_state, new_state);\n 153:\t\t} else if (old_state == IEEE80211_STA_AUTH \u0026\u0026\n 154:\t\t\t   new_state == IEEE80211_STA_ASSOC) {\n 155:\t\t\tret = drv_sta_add(local, sdata, \u0026sta-\u003esta);\n 156:\t\t\tif (ret == 0) {\n 157:\t\t\t\tsta-\u003euploaded = true;\n 158:\t\t\t\tif (rcu_access_pointer(sta-\u003esta.rates))\n 159:\t\t\t\t\tdrv_sta_rate_tbl_update(local, sdata, \u0026sta-\u003esta);\n 160:\t\t\t\tif (sta-\u003eairtime_weight != IEEE80211_DEFAULT_AIRTIME_WEIGHT)\n 161:\t\t\t\t\tdrv_sta_set_airtime_weight(local, sdata,\n 162:\t\t\t\t\t\t\t\t   \u0026sta-\u003esta,\n 163:\t\t\t\t\t\t\t\t   sta-\u003eairtime_weight);\n 164:\t\t\t}\n 165:\t\t} else if (old_state == IEEE80211_STA_ASSOC \u0026\u0026\n 166:\t\t\t   new_state == IEEE80211_STA_AUTH) {\n 167:\t\t\tdrv_sta_remove(local, sdata, \u0026sta-\u003esta);\n 168:\t\t}\n 169:\t\ttrace_drv_return_int(local, ret);\n 170:\t\treturn ret;\n 171:\t}\n 172:\t\n 173:\t__must_check\n 174:\tint drv_sta_set_txpwr(struct ieee80211_local *local,\n 175:\t\t\t      struct ieee80211_sub_if_data *sdata,\n 176:\t\t\t      struct sta_info *sta)\n 177:\t{\n 178:\t\tint ret = -EOPNOTSUPP;\n 179:\t\n"
}

5/2 2026/10/03 16:08 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 17864
							output: 42
							thoughts: 33
						

Thoughts:
Okay, let's dive into this. Here's my thought process on what we've got:

**Examining `sta_info_insert_drv_state` in `net/mac80211/sta_info.c`**

Alright, I see we're looking at `sta_info_insert_drv_state`. That function name itself is immediately interesting. It screams "driver state" and "station info," so it's probably critical for how the mac80211 layer handles per-station configuration as perceived by the driver. Given my familiarity with the architecture, I need to understand exactly how the driver is informing mac80211 about the state of a station. Is this called during association? Re-association? De-authentication? Is this used to track link quality, or maybe power save modes as it is described? Understanding *when* and *why* this function is called is going to be key to grasping its purpose. This means tracing the call stack from different scenarios and studying the structure it is working on, which is undoubtedly `struct sta_info`. I'll want to quickly check the data types involved, particularly any associated driver-specific structures being passed around. The location of the file in the kernel tree confirms that this is directly relevant to how station information is handled at a low level by the driver in the wireless stack.



6/2 2026/10/03 16:08 tool read-file
0m Args:
{
  "File": "net/mac80211/sta_info.c",
  "FirstLine": 855,
  "LineCount": 40
}

Results:
{
  "Contents": " 855:\t}\n 856:\t\n 857:\tstatic int sta_info_insert_drv_state(struct ieee80211_local *local,\n 858:\t\t\t\t\t     struct ieee80211_sub_if_data *sdata,\n 859:\t\t\t\t\t     struct sta_info *sta)\n 860:\t{\n 861:\t\tenum ieee80211_sta_state state;\n 862:\t\tint err = 0;\n 863:\t\n 864:\t\tfor (state = IEEE80211_STA_NOTEXIST; state \u003c sta-\u003esta_state; state++) {\n 865:\t\t\terr = drv_sta_state(local, sdata, sta, state, state + 1);\n 866:\t\t\tif (err)\n 867:\t\t\t\tbreak;\n 868:\t\t}\n 869:\t\n 870:\t\tif (!err) {\n 871:\t\t\t/*\n 872:\t\t\t * Drivers using legacy sta_add/sta_remove callbacks only\n 873:\t\t\t * get uploaded set to true after sta_add is called.\n 874:\t\t\t */\n 875:\t\t\tif (!local-\u003eops-\u003esta_add) {\n 876:\t\t\t\tsta-\u003euploaded = true;\n 877:\t\t\t\tif (sta-\u003eairtime_weight != IEEE80211_DEFAULT_AIRTIME_WEIGHT)\n 878:\t\t\t\t\tdrv_sta_set_airtime_weight(local, sdata,\n 879:\t\t\t\t\t\t\t\t   \u0026sta-\u003esta,\n 880:\t\t\t\t\t\t\t\t   sta-\u003eairtime_weight);\n 881:\t\t\t}\n 882:\t\t\treturn 0;\n 883:\t\t}\n 884:\t\n 885:\t\tif (sdata-\u003evif.type == NL80211_IFTYPE_ADHOC) {\n 886:\t\t\tsdata_info(sdata,\n 887:\t\t\t\t   \"failed to move IBSS STA %pM to state %d (%d) - keeping it anyway\\n\",\n 888:\t\t\t\t   sta-\u003esta.addr, state + 1, err);\n 889:\t\t\terr = 0;\n 890:\t\t}\n 891:\t\n 892:\t\t/* unwind on error */\n 893:\t\tfor (; state \u003e IEEE80211_STA_NOTEXIST; state--)\n 894:\t\t\tWARN_ON(drv_sta_state(local, sdata, sta, state, state - 1));\n"
}

7/2 2026/10/03 16:08 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 18886
							output: 41
							thoughts: 26
						

Thoughts:
Okay, let's dive in.

**Checking `sta_apply_parameters` in `net/mac80211/cfg.c`**

Alright, time to get to work. I need to take a look at how station parameters are being applied within the mac80211 framework. Specifically, I'm starting with `sta_apply_parameters` in `net/mac80211/cfg.c`. I need to understand exactly how the driver handles STA configurations, what the implications are for performance and stability, and if there are any obvious areas for optimization. I'm hoping I can get a clear picture of the parameter application flow from this function and see how it interacts with other modules, especially regarding power management and rate control.



8/2 2026/10/03 16:08 tool read-file
0m Args:
{
  "File": "net/mac80211/cfg.c",
  "FirstLine": 2600,
  "LineCount": 40
}

Results:
{
  "Contents": "2600:\t\t\tsta-\u003elisten_interval = params-\u003elisten_interval;\n2601:\t\n2602:\t\tif (params-\u003eeml_cap_present)\n2603:\t\t\tsta-\u003esta.eml_cap = params-\u003eeml_cap;\n2604:\t\n2605:\t\tif (params-\u003esta_flags_set \u0026 BIT(NL80211_STA_FLAG_CIP))\n2606:\t\t\tsta-\u003esta.cip = true;\n2607:\t\n2608:\t\tret = sta_link_apply_parameters(local, sta, STA_LINK_MODE_STA_MODIFY,\n2609:\t\t\t\t\t\t\u0026params-\u003elink_sta_params);\n2610:\t\tif (ret)\n2611:\t\t\treturn ret;\n2612:\t\n2613:\t\tif (params-\u003esupport_p2p_ps \u003e= 0)\n2614:\t\t\tsta-\u003esta.support_p2p_ps = params-\u003esupport_p2p_ps;\n2615:\t\n2616:\t\tif (ieee80211_vif_is_mesh(\u0026sdata-\u003evif))\n2617:\t\t\tsta_apply_mesh_params(local, sta, params);\n2618:\t\n2619:\t\tif (params-\u003eairtime_weight) {\n2620:\t\t\tsta-\u003eairtime_weight = params-\u003eairtime_weight;\n2621:\t\t\tif (sta-\u003euploaded)\n2622:\t\t\t\tdrv_sta_set_airtime_weight(local, sdata, \u0026sta-\u003esta,\n2623:\t\t\t\t\t\t\t   sta-\u003eairtime_weight);\n2624:\t\t}\n2625:\t\n2626:\t\tif (params-\u003enmi_mac) {\n2627:\t\t\tstruct ieee80211_sub_if_data *nmi =\n2628:\t\t\t\trcu_dereference_wiphy(local-\u003ehw.wiphy,\n2629:\t\t\t\t\t\t      sdata-\u003eu.nan_data.nmi);\n2630:\t\t\tstruct sta_info *nmi_sta;\n2631:\t\n2632:\t\t\tif (WARN_ON(!nmi))\n2633:\t\t\t\treturn -EINVAL;\n2634:\t\n2635:\t\t\tnmi_sta = sta_info_get(nmi, params-\u003enmi_mac);\n2636:\t\t\tif (!nmi_sta)\n2637:\t\t\t\treturn -ENOENT;\n2638:\t\t\trcu_assign_pointer(sta-\u003esta.nmi, \u0026nmi_sta-\u003esta);\n2639:\t\n"
}

9/2 2026/10/03 16:08 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 19790
							output: 33
							thoughts: 13
						

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

**Analyzing the Calls to `sta_apply_parameters`**

Okay, so I'm diving into the codebase to understand where and how `sta_apply_parameters` is being utilized. My initial focus is on pinpointing all the instances where this function is called. I need to map out its usage to grasp its role within the broader system. I'm looking at potential control flow scenarios, trying to determine the context in which specific parameter sets are applied. I'm paying close attention to the data types being passed in and the expected outputs. Understanding the call stack will be crucial. I'm thinking about potential side effects too, wondering if this function is modifying any global state or triggering any other important operations that I need to be aware of. I'm essentially reverse-engineering its impact on the system's behavior.



10/2 2026/10/03 16:08 tool grepper
0m Args:
{
  "Expression": "sta_apply_parameters",
  "PathPrefix": "net/mac80211"
}

Results:
{
  "Output": "net/mac80211/cfg.c=2285=static int sta_link_apply_parameters(struct ieee80211_local *local,\n--\nnet/mac80211/cfg.c-2478-\nnet/mac80211/cfg.c:2479:static int sta_apply_parameters(struct ieee80211_local *local,\nnet/mac80211/cfg.c-2480-\t\t\t\tstruct sta_info *sta,\n--\nnet/mac80211/cfg.c=2670=static int ieee80211_add_station(struct wiphy *wiphy, struct wireless_dev *wdev,\n--\nnet/mac80211/cfg.c-2720-\t/* Though the mutex is not needed here (since the station is not\nnet/mac80211/cfg.c:2721:\t * visible yet), sta_apply_parameters (and inner functions) require\nnet/mac80211/cfg.c-2722-\t * the mutex due to other paths.\nnet/mac80211/cfg.c-2723-\t */\nnet/mac80211/cfg.c:2724:\terr = sta_apply_parameters(local, sta, params);\nnet/mac80211/cfg.c-2725-\tif (err) {\n--\nnet/mac80211/cfg.c-2741-\t/*\nnet/mac80211/cfg.c:2742:\t * ieee80211_nan_update_ndi_carrier was called from sta_apply_parameters,\nnet/mac80211/cfg.c-2743-\t * but then we did not have the STA in the list.\n--\nnet/mac80211/cfg.c=2823=static int ieee80211_change_station(struct wiphy *wiphy,\n--\nnet/mac80211/cfg.c-2916-\nnet/mac80211/cfg.c:2917:\terr = sta_apply_parameters(local, sta, params);\nnet/mac80211/cfg.c-2918-\tif (err)\n"
}

11/2 2026/10/03 16:08 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 20618
							output: 22
							thoughts: 144
						

Thoughts:
**Analyzing Station Management in mac80211 and Potential Syzkaller Coverage**

Okay, so I'm thinking about how station management works within the mac80211 framework and how it might relate to fuzzing efforts. Specifically, I'm noting that `ieee80211_add_station` and `ieee80211_change_station` are directly responsible for handling the `nl80211` commands related to creating and modifying stations, namely `NL80211_CMD_NEW_STATION` and `NL80211_CMD_SET_STATION`. That's a key starting point.

And here's an interesting point – I recall that Syzkaller already has descriptions for these nl80211 commands concerning adding and changing stations. This immediately makes me think that there's potential for existing coverage, or at least a good foundation to build on.

But, I need to dig deeper. I want to check something specific: I'm curious if `sta_set_airtime_weight` is actually implemented by the `mac80211_hwsim` driver, or if it is implemented in other drivers. This is important to determine what types of drivers might have this functionality to be tested, so I'm going to run a `grep` for `sta_set_airtime_weight` across the relevant codebase. That'll give me a clearer picture of its usage and implementation across different drivers within the mac80211 ecosystem.



12/2 2026/10/03 16:08 tool grepper
0m Args:
{
  "Expression": "sta_set_airtime_weight"
}

Results:
{
  "Output": "drivers/net/wireless/ath/ath11k/mac.c=10027=static int ath11k_mac_atf_update(struct ath11k *ar)\n--\ndrivers/net/wireless/ath/ath11k/mac.c-10068-\ndrivers/net/wireless/ath/ath11k/mac.c:10069:static void ath11k_mac_op_sta_set_airtime_weight(struct ieee80211_hw *hw,\ndrivers/net/wireless/ath/ath11k/mac.c-10070-\t\t\t\t\t\t struct ieee80211_vif *vif,\n--\ndrivers/net/wireless/ath/ath11k/mac.c=10227=static const struct ieee80211_ops ath11k_ops = {\n--\ndrivers/net/wireless/ath/ath11k/mac.c-10245-\t.sta_set_txpwr\t\t\t= ath11k_mac_op_sta_set_txpwr,\ndrivers/net/wireless/ath/ath11k/mac.c:10246:\t.sta_set_airtime_weight\t\t= ath11k_mac_op_sta_set_airtime_weight,\ndrivers/net/wireless/ath/ath11k/mac.c-10247-\t.link_sta_rc_update\t\t= ath11k_mac_op_sta_rc_update,\n--\ninclude/net/mac80211.h=4077=struct ieee80211_prep_tx_info {\n--\ninclude/net/mac80211.h-4696- *\tto use rx decapsulation offload\ninclude/net/mac80211.h:4697: * @sta_set_airtime_weight: Called to notify the driver of a change to a\ninclude/net/mac80211.h-4698- *\tstation's airtime fairness weight, so it can be programmed in hardware.\n--\ninclude/net/mac80211.h=4753=struct ieee80211_ops {\n--\ninclude/net/mac80211.h-5112-\t\t\t\t      struct ieee80211_sta *sta, bool enabled);\ninclude/net/mac80211.h:5113:\tvoid (*sta_set_airtime_weight)(struct ieee80211_hw *hw,\ninclude/net/mac80211.h-5114-\t\t\t\t       struct ieee80211_vif *vif,\n--\nnet/mac80211/cfg.c=2479=static int sta_apply_parameters(struct ieee80211_local *local,\n--\nnet/mac80211/cfg.c-2621-\t\tif (sta-\u003euploaded)\nnet/mac80211/cfg.c:2622:\t\t\tdrv_sta_set_airtime_weight(local, sdata, \u0026sta-\u003esta,\nnet/mac80211/cfg.c-2623-\t\t\t\t\t\t   sta-\u003eairtime_weight);\n--\nnet/mac80211/driver-ops.c=134=int drv_sta_state(struct ieee80211_local *local,\n--\nnet/mac80211/driver-ops.c-160-\t\t\tif (sta-\u003eairtime_weight != IEEE80211_DEFAULT_AIRTIME_WEIGHT)\nnet/mac80211/driver-ops.c:161:\t\t\t\tdrv_sta_set_airtime_weight(local, sdata,\nnet/mac80211/driver-ops.c-162-\t\t\t\t\t\t\t   \u0026sta-\u003esta,\n--\nnet/mac80211/driver-ops.h=1617=static inline void drv_sta_set_decap_offload(struct ieee80211_local *local,\n--\nnet/mac80211/driver-ops.h-1635-\nnet/mac80211/driver-ops.h:1636:static inline void drv_sta_set_airtime_weight(struct ieee80211_local *local,\nnet/mac80211/driver-ops.h-1637-\t\t\t\t\t      struct ieee80211_sub_if_data *sdata,\n--\nnet/mac80211/driver-ops.h-1647-\nnet/mac80211/driver-ops.h:1648:\ttrace_drv_sta_set_airtime_weight(local, sdata, sta, weight);\nnet/mac80211/driver-ops.h:1649:\tif (local-\u003eops-\u003esta_set_airtime_weight)\nnet/mac80211/driver-ops.h:1650:\t\tlocal-\u003eops-\u003esta_set_airtime_weight(\u0026local-\u003ehw, \u0026sdata-\u003evif, sta,\nnet/mac80211/driver-ops.h-1651-\t\t\t\t\t\t   weight);\n--\nnet/mac80211/sta_info.c=857=static int sta_info_insert_drv_state(struct ieee80211_local *local,\n--\nnet/mac80211/sta_info.c-877-\t\t\tif (sta-\u003eairtime_weight != IEEE80211_DEFAULT_AIRTIME_WEIGHT)\nnet/mac80211/sta_info.c:878:\t\t\t\tdrv_sta_set_airtime_weight(local, sdata,\nnet/mac80211/sta_info.c-879-\t\t\t\t\t\t\t   \u0026sta-\u003esta,\n--\nnet/mac80211/trace.h=2457=DEFINE_EVENT(sta_flag_evt, drv_sta_set_decap_offload,\n--\nnet/mac80211/trace.h-2464-\nnet/mac80211/trace.h:2465:TRACE_EVENT(drv_sta_set_airtime_weight,\nnet/mac80211/trace.h-2466-\tTP_PROTO(struct ieee80211_local *local,\n"
}

13/2 2026/10/03 16:08 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 22723
							output: 48
							thoughts: 455
						

Thoughts:
**Analyzing Airtime Weight Implementation**

Okay, so I'm looking into how airtime weights are handled in the wireless stack. Interesting, *only* ath11k seems to directly implement `ops->sta_set_airtime_weight`. That's a bit unusual. Now, I need to understand what mac80211 does in this context.

Let's dive into the mac80211 code itself. It seems `drv_sta_set_airtime_weight` is the crucial function. I see it's called from three places: `sta_apply_parameters` within `cfg.c`, `drv_sta_state` in `driver-ops.c`, and `sta_info_insert_drv_state` in `sta_info.c`. So, these are the points where the driver's airtime weight setting might be triggered.

Now, considering the general case when any driver – like, say, mac80211_hwsim – is involved, let's examine the `drv_sta_set_airtime_weight` function's implementation. Here's what's happening:

```c
static inline void drv_sta_set_airtime_weight(struct ieee80211_local *local,
					      struct ieee80211_sub_if_data *sdata,
					      struct ieee80211_sta *sta,
					      u16 weight)
{
	sdata = get_bss_sdata(sdata);

	might_sleep();
	lockdep_assert_wiphy(local->hw.wiphy);
	if (!check_sdata_in_driver(sdata))
		return;

	trace_drv_sta_set_airtime_weight(local, sdata, sta, weight);
	if (local->ops->sta_set_airtime_weight)
		local->ops->sta_set_airtime_weight(&local->hw, &sdata->vif, sta,
						   weight);
	trace_drv_return_void(local);
}
```

Okay, so mac80211 calls the driver-specific implementation, *if* the driver supports it, indicated by `local->ops->sta_set_airtime_weight`. This is key. The `if` statement right there, that's what we expect: it checks for the driver's specific implementation. Now I am more sure that ath11k is the *only* driver implementing it.

Aha! So it delegates. That is interesting, it is also interesting to think about which drivers this implementation is called for.

Now, a related thought... I wonder if ath11k itself can be simulated in a QEMU environment. I need to check if it supports any virtual or simulated bus, or if it's strictly tied to PCI or AHB hardware. This simulation aspect is important to test or debug without physical hardware. That is where I will go next.



14/2 2026/10/03 16:09 tool grepper
0m Args:
{
  "Expression": "module_init|module_pci_driver|module_platform_driver",
  "PathPrefix": "drivers/net/wireless/ath/ath11k"
}

Results:
{
  "Output": "drivers/net/wireless/ath/ath11k/ahb.c=1343=static struct platform_driver ath11k_ahb_driver = {\n--\ndrivers/net/wireless/ath/ath11k/ahb.c-1352-\ndrivers/net/wireless/ath/ath11k/ahb.c:1353:module_platform_driver(ath11k_ahb_driver);\ndrivers/net/wireless/ath/ath11k/ahb.c-1354-\n--\ndrivers/net/wireless/ath/ath11k/pci.c=1294=static int ath11k_pci_init(void)\n--\ndrivers/net/wireless/ath/ath11k/pci.c-1304-}\ndrivers/net/wireless/ath/ath11k/pci.c:1305:module_init(ath11k_pci_init);\ndrivers/net/wireless/ath/ath11k/pci.c-1306-\n"
}

15/2 2026/10/03 16:09 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 24160
							output: 42
							thoughts: 1839
						

Thoughts:
**Fuzzing Decision for net/mac80211 Patch**

Okay, let's break this down systematically. I was initially looking at `ath11k`, but that's a dead end – it's all PCI and AHB drivers, which are impossible to probe without the actual Qualcomm hardware, which we don't have for fuzzing. However, that got me thinking: what about `net/mac80211` itself? Is that even accessible in Syzkaller?

Aha! `mac80211_hwsim` to the rescue! It's that fantastic virtual software radio that Syzkaller leans on heavily for fuzzing 802.11 and mac80211, great! But before I get excited, I need to carefully evaluate if the change is significant enough to warrant fuzzing.

Let's revisit the triage guidelines. I need to make sure this meets the criteria to determine if this is WorthFuzzing.

The most important part is the "reachability" gate. Code that can't be executed in a standard virtualized environment gets a pass. So, I need to check the *negative criteria*, to make sure this doesn't fall into the category of "WorthFuzzing=false".

The negative criteria are pretty explicit: no non-kernel changes, unreachable hardware, or unreachable execution paths. I need to check to make sure the changes to `net/mac80211` don't match those categories.

Now, let's analyze the patch. The relevant changes are focused around airtime weight management and station setup:

*   `net/mac80211/cfg.c`, `net/mac80211/driver-ops.c`, `net/mac80211/driver-ops.h`, and `net/mac80211/sta_info.c` are affected.

Crucially, in `net/mac80211/driver-ops.h`, `drv_sta_set_airtime_weight` is modified. And I see it introduces `might_sleep()` and `lockdep_assert_wiphy(local->hw.wiphy);`.

Wait a second... That's a runtime assertion, specifically a `lockdep_assert_wiphy`. According to the guidelines, "NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED"! They are essential for detecting unexpected sequences of operations!

Now, does the `mac80211_hwsim` driver, which is what Syzkaller is using, use `local->ops->sta_add` or `local->ops->sta_state`? We have to check this, in `mac80211_hwsim.c`.

Looks like it's worth it after all!



16/2 2026/10/03 16:09 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "\\.sta_",
  "PathPrefix": "drivers/net/wireless/virtual/mac80211_hwsim.c"
}

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

17/2 2026/10/03 16:09 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 26668
							output: 18
							thoughts: 19
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**Hunting Down `mac80211_hwsim.c`**

Alright, let's get down to brass tacks. I need to locate the source code for `mac80211_hwsim.c`. That name alone screams "hardware simulation within the mac80211 framework," so it's a critical component for debugging, testing, and understanding the interaction between the mac80211 core and simulated wireless hardware. Given the nature of these sorts of modules, I'm expecting this file to reside somewhere within the Linux kernel source tree. My initial instinct is to look within the relevant driver or staging areas, likely under `drivers/net/wireless` or perhaps in a staging directory, as `hwsim` could be considered experimental or not yet fully mainline. It could also potentially be in a related test directory. Let's start there. I'll probably be using my standard method, some find and grepping. I could try `find . -name "mac80211_hwsim.c"` starting at the top of the kernel source directory. Then, if that doesn't yield anything immediately, I'll broaden the search to include some more general terms and start using `grep` to filter things. I'll need to remember to check any potential `Kconfig` files along the way, to verify that `hwsim` is enabled when I go looking through these directories. After I find the path I can start reading the code!



18/2 2026/10/03 16:09 tool grepper
0m Args:
{
  "Expression": "hwsim_ops"
}

Results:
{
  "Output": "drivers/net/ieee802154/mac802154_hwsim.c=312=hwsim_set_promiscuous_mode(struct ieee802154_hw *hw, const bool on)\n--\ndrivers/net/ieee802154/mac802154_hwsim.c-331-\ndrivers/net/ieee802154/mac802154_hwsim.c:332:static const struct ieee802154_ops hwsim_ops = {\ndrivers/net/ieee802154/mac802154_hwsim.c-333-\t.owner = THIS_MODULE,\n--\ndrivers/net/ieee802154/mac802154_hwsim.c=899=static int hwsim_add_one(struct genl_info *info, struct device *dev,\n--\ndrivers/net/ieee802154/mac802154_hwsim.c-909-\ndrivers/net/ieee802154/mac802154_hwsim.c:910:\thw = ieee802154_alloc_hw(sizeof(*phy), \u0026hwsim_ops);\ndrivers/net/ieee802154/mac802154_hwsim.c-911-\tif (!hw)\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c=4279=static int mac80211_hwsim_set_radar_background(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-4344-\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c:4345:static const struct ieee80211_ops mac80211_hwsim_ops = {\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-4346-\tHWSIM_COMMON_OPS\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c=5715=static int mac80211_hwsim_new_radio(struct genl_info *info,\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-5722-\tenum nl80211_band band;\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c:5723:\tconst struct ieee80211_ops *ops = \u0026mac80211_hwsim_ops;\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-5724-\tstruct net *net;\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c=7147=static int hwsim_dump_radio_nl(struct sk_buff *skb,\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-7198-/* Generic Netlink operations array */\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c:7199:static const struct genl_small_ops hwsim_ops[] = {\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-7200-\t{\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c=7241=static struct genl_family hwsim_genl_family __ro_after_init = {\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-7247-\t.module = THIS_MODULE,\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c:7248:\t.small_ops = hwsim_ops,\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c:7249:\t.n_small_ops = ARRAY_SIZE(hwsim_ops),\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-7250-\t.resv_start_op = HWSIM_CMD_REPORT_PMSR + 1, // match with __HWSIM_CMD_MAX\n"
}

19/2 2026/10/03 16:09 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 28174
							output: 48
							thoughts: 41
						

Thoughts:
Here's my take on the thought process, considering I'm an expert:

**Diving into the `mac80211_hwsim_ops` Structure**

Okay, I'm thinking I need to refresh my memory on the interactions in `drivers/net/wireless/virtual/mac80211_hwsim_main.c`. Specifically, I'm zeroing in on `mac80211_hwsim_ops`. I know this is the central structure for emulating hardware within the mac80211 framework. I want to see what's being defined there – what operations are being implemented to simulate the behaviour of a wireless network card. Knowing that structure inside and out is key to understanding how the hardware simulation works. It is the bridge between the simulated hardware and the mac80211 core, and its definition gives us the blueprint for the virtual driver. Let's see what’s going on... I need to remember the specific function pointers, the key callbacks, and how they map to actual hardware functions – a mental refresh is in order.



20/2 2026/10/03 16:09 tool grepper
0m Args:
{
  "Expression": "HWSIM_COMMON_OPS",
  "PathPrefix": "drivers/net/wireless/virtual/mac80211_hwsim_main.c"
}

Results:
{
  "Output": "drivers/net/wireless/virtual/mac80211_hwsim_main.c=4279=static int mac80211_hwsim_set_radar_background(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-4303-\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c:4304:#define HWSIM_COMMON_OPS\t\t\t\t\t\\\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-4305-\t.tx = mac80211_hwsim_tx,\t\t\t\t\\\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c=4345=static const struct ieee80211_ops mac80211_hwsim_ops = {\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c:4346:\tHWSIM_COMMON_OPS\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-4347-\tHWSIM_NON_MLO_OPS\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c=4368=static const struct ieee80211_ops mac80211_hwsim_mchan_ops = {\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c:4369:\tHWSIM_COMMON_OPS\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-4370-\tHWSIM_NON_MLO_OPS\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c=4374=static const struct ieee80211_ops mac80211_hwsim_mlo_ops = {\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c:4375:\tHWSIM_COMMON_OPS\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-4376-\tHWSIM_CHANCTX_OPS\n"
}

21/2 2026/10/03 16:09 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 29075
							output: 50
							thoughts: 16
						

Thoughts:
Okay, let's dive into this. Here's my take on those thoughts, as if they're my own:

**Investigating `HWSIM_COMMON_OPS`**

Right, let's get down to brass tacks. I need to understand the composition of `HWSIM_COMMON_OPS`. This variable, or whatever construct it represents, is central to the operational flow of this simulation or hardware modeling environment. Therefore, before I proceed with any further analysis or debugging, I need to know the specific types of operations, parameters, and relevant data structures that are encapsulated within `HWSIM_COMMON_OPS`. Depending on its contents, I can form my next hypothesis. This also informs my next step for the overall architecture. 



22/2 2026/10/03 16:09 tool read-file
0m Args:
{
  "File": "drivers/net/wireless/virtual/mac80211_hwsim_main.c",
  "FirstLine": 4304,
  "LineCount": 40
}

Results:
{
  "Contents": "4304:\t#define HWSIM_COMMON_OPS\t\t\t\t\t\\\n4305:\t\t.tx = mac80211_hwsim_tx,\t\t\t\t\\\n4306:\t\t.wake_tx_queue = ieee80211_hwsim_wake_tx_queue,\t\t\\\n4307:\t\t.start = mac80211_hwsim_start,\t\t\t\t\\\n4308:\t\t.stop = mac80211_hwsim_stop,\t\t\t\t\\\n4309:\t\t.add_interface = mac80211_hwsim_add_interface,\t\t\\\n4310:\t\t.change_interface = mac80211_hwsim_change_interface,\t\\\n4311:\t\t.remove_interface = mac80211_hwsim_remove_interface,\t\\\n4312:\t\t.config = mac80211_hwsim_config,\t\t\t\\\n4313:\t\t.configure_filter = mac80211_hwsim_configure_filter,\t\\\n4314:\t\t.vif_cfg_changed = mac80211_hwsim_vif_info_changed,\t\\\n4315:\t\t.link_info_changed = mac80211_hwsim_link_info_changed,  \\\n4316:\t\t.tx_last_beacon = mac80211_hwsim_tx_last_beacon,\t\\\n4317:\t\t.sta_notify = mac80211_hwsim_sta_notify,\t\t\\\n4318:\t\t.link_sta_rc_update = mac80211_hwsim_sta_rc_update,\t\\\n4319:\t\t.conf_tx = mac80211_hwsim_conf_tx,\t\t\t\\\n4320:\t\t.get_survey = mac80211_hwsim_get_survey,\t\t\\\n4321:\t\tCFG80211_TESTMODE_CMD(mac80211_hwsim_testmode_cmd)\t\\\n4322:\t\t.ampdu_action = mac80211_hwsim_ampdu_action,\t\t\\\n4323:\t\t.flush = mac80211_hwsim_flush,\t\t\t\t\\\n4324:\t\t.get_et_sset_count = mac80211_hwsim_get_et_sset_count,\t\\\n4325:\t\t.get_et_stats = mac80211_hwsim_get_et_stats,\t\t\\\n4326:\t\t.get_et_strings = mac80211_hwsim_get_et_strings,\t\\\n4327:\t\t.start_pmsr = mac80211_hwsim_start_pmsr,\t\t\\\n4328:\t\t.abort_pmsr = mac80211_hwsim_abort_pmsr,\t\t\\\n4329:\t\t.set_radar_background = mac80211_hwsim_set_radar_background, \\\n4330:\t\t.set_key = mac80211_hwsim_set_key,\t\t\t\\\n4331:\t\t.set_rts_threshold = mac80211_hwsim_set_rts_threshold,\t\\\n4332:\t\t.start_nan = mac80211_hwsim_nan_start,\t\t\t\\\n4333:\t\t.stop_nan = mac80211_hwsim_nan_stop,\t\t\t\\\n4334:\t\t.nan_change_conf = mac80211_hwsim_nan_change_config,\t\\\n4335:\t\t.nan_peer_sched_changed = mac80211_hwsim_nan_peer_sched_changed, \\\n4336:\t\tHWSIM_DEBUGFS_OPS\n4337:\t\n4338:\t#define HWSIM_NON_MLO_OPS\t\t\t\t\t\\\n4339:\t\t.sta_add = mac80211_hwsim_sta_add,\t\t\t\\\n4340:\t\t.sta_remove = mac80211_hwsim_sta_remove,\t\t\\\n4341:\t\t.set_tim = mac80211_hwsim_set_tim,\t\t\t\\\n4342:\t\t.get_tsf = mac80211_hwsim_get_tsf,\t\t\t\\\n4343:\t\t.set_tsf = mac80211_hwsim_set_tsf,\n"
}

23/2 2026/10/03 16:09 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 30442
							output: 49
							thoughts: 890
						

Thoughts:
**Analyzing Airtime Weight Updates in mac80211 with HWSIM**

Okay, let's break this down. I'm focusing on how airtime weight updates are handled, especially within the context of the mac80211 hardware simulator, `mac80211_hwsim`. First, I see that `mac80211_hwsim_ops` defines `.sta_add` and `.sta_remove` functions. I need to understand how this interacts with the `drv_sta_state` mechanism, so let's re-examine that.

Right, `drv_sta_state` seems to be the key.  If a driver defines a `.sta_state` callback, that's used. However, if not, and the station transitions from authentication to association, we have this conditional logic. Essentially, if `drv_sta_add` succeeds: `sta->uploaded` is set to `true`, and the airtime weight is updated, if it's set differently to the default.

Now, I'm thinking about what happens when the airtime weight *changes* after association.  When a station's parameters are updated via `sta_apply_parameters`, we see this: if the `airtime_weight` field is set in the parameters and the station is 'uploaded', then `drv_sta_set_airtime_weight` is called *again*. Crucially, `sta->uploaded` becomes true on a successful `drv_sta_add`.

Inside `drv_sta_set_airtime_weight`, we are ultimately calling the driver's specific implementation via `local->ops->sta_set_airtime_weight`. This looks like the right place to start debugging further, but I need to check something else.

Okay, let's switch gears and check out `mac80211_hwsim_mlo_ops`.  Aha! This one includes `HWSIM_CHANCTX_OPS`. This suggests there's channel context involved here. So, it's starting to look like these callbacks are where all the magic happens when updating a STA's airtime weight. Now I need to see exactly how these callbacks are defined.



24/2 2026/10/03 16:09 tool grepper
0m Args:
{
  "Expression": "HWSIM_CHANCTX_OPS",
  "PathPrefix": "drivers/net/wireless/virtual/mac80211_hwsim_main.c"
}

Results:
{
  "Output": "drivers/net/wireless/virtual/mac80211_hwsim_main.c=4345=static const struct ieee80211_ops mac80211_hwsim_ops = {\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-4355-\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c:4356:#define HWSIM_CHANCTX_OPS\t\t\t\t\t\\\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-4357-\t.hw_scan = mac80211_hwsim_hw_scan,\t\t\t\\\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c=4368=static const struct ieee80211_ops mac80211_hwsim_mchan_ops = {\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-4370-\tHWSIM_NON_MLO_OPS\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c:4371:\tHWSIM_CHANCTX_OPS\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-4372-};\n--\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c=4374=static const struct ieee80211_ops mac80211_hwsim_mlo_ops = {\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-4375-\tHWSIM_COMMON_OPS\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c:4376:\tHWSIM_CHANCTX_OPS\ndrivers/net/wireless/virtual/mac80211_hwsim_main.c-4377-\t.change_vif_links = mac80211_hwsim_change_vif_links,\n"
}

25/2 2026/10/03 16:09 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 32389
							output: 37
							thoughts: 769
						

Thoughts:
**Analyzing the WorthFuzzing Criteria for a Wireless Patch**

Okay, so I'm looking at this patch and trying to determine if it's "WorthFuzzing." My initial thought is that there's a problem in `mac80211_hwsim_mlo_ops` because neither `sta_state` nor `sta_add` is set. Hang on, let me look closer. Ah, here's `sta_info_insert_drv_state`. It looks like if the driver doesn't implement `sta_add` (which is true for `mac80211_hwsim_mlo_ops` and other drivers), then it executes a specific branch.

Specifically, it sets `sta->uploaded = true`. Also, if the `airtime_weight` isn't the default, it calls `drv_sta_set_airtime_weight`. Okay, let's see where that's used. It's a static inline, defined in `net/mac80211/driver-ops.h` and inlined into several functions in the mac80211 core, including `sta_apply_parameters`, `drv_sta_state`, and `sta_info_insert_drv_state`.

Now, the important part: the fuzzing criteria. The instructions specify that a patch is *not* worth fuzzing ONLY IF *all* the modified code falls into certain categories. The categories include things like vendor-specific hardware that's not easily emulated or unreachable execution paths. This patch has modifications in `drivers/net/wireless/ath/ath11k/...`, which is vendor-specific hardware, so that looks like it could be a blocker. However, it *also* modifies `include/net/mac80211.h` and parts of the `net/mac80211/...` core stack! That's a key point. Mac80211 itself is definitely reachable in standard virtualized environments. Syzkaller is actively fuzzing mac80211 via `mac80211_hwsim` and netlink/nl80211.

Let's confirm that `MAC80211` and `MAC80211_HWSIM` are standard in syzkaller. Yes! Syzkaller has `MAC80211_HWSIM` enabled by default in its kernel configs, and uses it for wireless netlink and 802.11 fuzzing. Good, that's what I thought. To be absolutely sure, I'll need to check the syzkaller configuration. Let's look at the Kconfig for MAC80211.



26/2 2026/10/03 16:09 tool grepper
0m Args:
{
  "Expression": "config MAC80211\\b",
  "PathPrefix": "net/mac80211"
}

Results:
{
  "Output": "net/mac80211/Kconfig-1-# SPDX-License-Identifier: GPL-2.0-only\nnet/mac80211/Kconfig:2:config MAC80211\nnet/mac80211/Kconfig-3-\ttristate \"Generic IEEE 802.11 Networking Stack (mac80211)\"\n"
}

27/2 2026/10/03 16:09 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 33885
							output: 38
							thoughts: 20
						

Thoughts:
Here's my thought process, as if I were considering this myself:

**Kconfig Check for MAC80211_HWSIM**

Okay, before I proceed further, I need to make absolutely certain that the configuration options are correct. Given the nature of this project, a thorough audit is paramount. Specifically, I should double-check the Kconfig file for `MAC80211_HWSIM`. I need to ensure it's defined, that there aren't any obvious dependencies I've overlooked, and confirm the default values (if any) are what I expect. A simple, quick check now could prevent a rather annoying debugging session later. It's the standard practice, really, to verify the fundamentals before moving on to the more complex implementation details. This is especially true when integrating hardware simulation; the configuration aspect is critical for proper operation.



28/2 2026/10/03 16:09 tool grepper
0m Args:
{
  "Expression": "config MAC80211_HWSIM\\b",
  "PathPrefix": "drivers/net/wireless"
}

Results:
{
  "Output": "drivers/net/wireless/virtual/Kconfig:1:config MAC80211_HWSIM\ndrivers/net/wireless/virtual/Kconfig-2-\ttristate \"Simulated radio testing tool for mac80211\"\n"
}

29/2 2026/10/03 16:09 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 34195
							output: 37
							thoughts: 28
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**Diving into the MAC80211 Dependencies**

Right, let's get down to brass tacks. I need to understand the dependencies of the MAC80211 subsystem in this kernel build. Time to crack open the `net/mac80211/Kconfig` file. I'm not just looking for a casual overview; I want to *pinpoint* the critical relationships. I want to see what other configurations hinge on MAC80211, which other features or hardware bring it in, and what the branching logic is within its own configuration options. I'm expecting to see a complex web of dependencies and conditionals, and I'll be ready to parse it all to understand the build implications.



30/2 2026/10/03 16:09 tool read-file
0m Args:
{
  "File": "net/mac80211/Kconfig",
  "FirstLine": 1,
  "LineCount": 40
}

Results:
{
  "Contents": "   1:\t# SPDX-License-Identifier: GPL-2.0-only\n   2:\tconfig MAC80211\n   3:\t\ttristate \"Generic IEEE 802.11 Networking Stack (mac80211)\"\n   4:\t\tdepends on CFG80211\n   5:\t\tselect CRYPTO\n   6:\t\tselect CRYPTO_LIB_AES_CBC_MACS\n   7:\t\tselect CRYPTO_LIB_ARC4\n   8:\t\tselect CRYPTO_AES\n   9:\t\tselect CRYPTO_CCM\n  10:\t\tselect CRYPTO_GCM\n  11:\t\tselect CRC32\n  12:\t\thelp\n  13:\t\t  This option enables the hardware independent IEEE 802.11\n  14:\t\t  networking stack.\n  15:\t\n  16:\tcomment \"CFG80211 needs to be enabled for MAC80211\"\n  17:\t\tdepends on CFG80211=n\n  18:\t\n  19:\tif MAC80211 != n\n  20:\t\n  21:\tconfig MAC80211_HAS_RC\n  22:\t\tbool\n  23:\t\n  24:\tconfig MAC80211_RC_MINSTREL\n  25:\t\tbool \"Minstrel\" if EXPERT\n  26:\t\tselect MAC80211_HAS_RC\n  27:\t\tdefault y\n  28:\t\thelp\n  29:\t\t  This option enables the 'minstrel' TX rate control algorithm\n  30:\t\n  31:\tchoice\n  32:\t\tprompt \"Default rate control algorithm\"\n  33:\t\tdepends on MAC80211_HAS_RC\n  34:\t\tdefault MAC80211_RC_DEFAULT_MINSTREL\n  35:\t\thelp\n  36:\t\t  This option selects the default rate control algorithm\n  37:\t\t  mac80211 will use. Note that this default can still be\n  38:\t\t  overridden through the ieee80211_default_rc_algo module\n  39:\t\t  parameter if different algorithms are available.\n  40:\t\n"
}

31/2 2026/10/03 16:09 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 34986
							output: 33
							thoughts: 16
						

Thoughts:
Okay, here's my summary, tailored for an expert audience, in the first person, reflecting the given thought process:

**Diving Deeper into Wireless Configuration**

Alright, so we're looking at this issue and I think we need to broaden our scope just a bit. We've got our leads, but I'm feeling like we might be missing something fundamental. Given the nature of the problem, I'm thinking we can't ignore the core wireless configuration layer. Specifically, I need to check `CFG80211`. That module is the bedrock for so much of the wireless setup and management in the kernel, so it’s the logical place to start digging deeper. It touches *everything* wireless related so, before we go down some rabbit hole, let's make sure that layer is behaving as expected. Let's see what `CFG80211` is telling us.



32/2 2026/10/03 16:09 tool grepper
0m Args:
{
  "Expression": "config CFG80211\\b",
  "PathPrefix": "net/wireless"
}

Results:
{
  "Output": "net/wireless/Kconfig=14=config WEXT_PRIV\n--\nnet/wireless/Kconfig-16-\nnet/wireless/Kconfig:17:config CFG80211\nnet/wireless/Kconfig-18-\ttristate \"cfg80211 - wireless configuration API\"\n"
}

33/2 2026/10/03 16:09 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 35316
							output: 36
							thoughts: 17
						

Thoughts:
Okay, let's dive into this. Here's how I'd approach this task, as if these were my internal thoughts:

**Analyzing the Kconfig File for Wireless Virtual Drivers**

Alright, time to get to it. My next step in this investigation is clear: I'm going to carefully examine the `drivers/net/wireless/virtual/Kconfig` file. This is where the configuration options for the virtual wireless drivers are defined, right? I need to understand what features are enabled, disabled, and configurable here. I'll be looking for dependencies, default values, any conditional logic, and how these settings might interact with the broader kernel configuration. Essentially, I'm trying to map out the configuration landscape for these virtual drivers and get a handle on how to influence their behavior at build time. This Kconfig file will act as the key to understanding how we can control and utilize these drivers within a broader system.



34/2 2026/10/03 16:09 tool read-file
0m Args:
{
  "File": "drivers/net/wireless/virtual/Kconfig",
  "FirstLine": 1,
  "LineCount": 40
}

Results:
{
  "Contents": "   1:\tconfig MAC80211_HWSIM\n   2:\t\ttristate \"Simulated radio testing tool for mac80211\"\n   3:\t\tdepends on MAC80211\n   4:\t\thelp\n   5:\t\t  This driver is a developer testing tool that can be used to test\n   6:\t\t  IEEE 802.11 networking stack (mac80211) functionality. This is not\n   7:\t\t  needed for normal wireless LAN usage and is only for testing. See\n   8:\t\t  Documentation/networking/mac80211_hwsim for more information on how\n   9:\t\t  to use this tool.\n  10:\t\n  11:\t\t  To compile this driver as a module, choose M here: the module will be\n  12:\t\t  called mac80211_hwsim.  If unsure, say N.\n  13:\t\n  14:\tconfig VIRT_WIFI\n  15:\t\ttristate \"Wifi wrapper for ethernet drivers\"\n  16:\t\tdepends on CFG80211\n  17:\t\thelp\n  18:\t\t  This option adds support for ethernet connections to appear as if they\n  19:\t\t  are wifi connections through a special rtnetlink device.\n  20:\t\n"
}

35/2 2026/10/03 16:09 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 35887
							output: 39
							thoughts: 30
						

Thoughts:
Okay, here's my take on those thoughts, tailored for an expert audience:

**Diving into the Atheros Wireless Configuration**

Alright, before we proceed any further, I want to take a quick peek at the `drivers/net/wireless/ath/ath11k/Kconfig` file. It's always a good idea to refresh my understanding of the relevant configuration options within a specific driver, especially before committing to any assumptions or making any changes. I need to make sure I know what configuration options are available and what they control within the ath11k driver. Sometimes a crucial setting is hidden in a seemingly unrelated section. I’m thinking particularly about the impact of any changes on other wireless components within the overall kernel. A quick scan of the Kconfig will likely give me some important context and prevent any obvious gotchas down the line. I always want to make sure I am working with the most up to date information.



36/2 2026/10/03 16:09 tool grepper
0m Args:
{
  "Expression": "config ATH11K\\b",
  "PathPrefix": "drivers/net/wireless/ath/ath11k"
}

Results:
{
  "Output": "drivers/net/wireless/ath/ath11k/Kconfig-1-# SPDX-License-Identifier: BSD-3-Clause-Clear\ndrivers/net/wireless/ath/ath11k/Kconfig:2:config ATH11K\ndrivers/net/wireless/ath/ath11k/Kconfig-3-\ttristate \"Qualcomm 802.11ax chipset support\"\n"
}

37/2 2026/10/03 16:09 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 36256
							output: 41
							thoughts: 2257
						

Thoughts:
**WorthFuzzing Analysis and FocusSymbol Determination**

Okay, let's break this down. First, I need to figure out if this patch introduces code worth fuzzing. The initial dependency analysis, looking at `ath11k` and its dependencies on `CRYPTO`, `QRTR`, etc., is helpful in setting the context, but the key is understanding the reachability of the modified code.  The fact that `ath11k` is tied to specific Qualcomm hardware is a red herring in this context, because the changes I am concerned with are *not* limited to the ath11k driver, but also extend into the `mac80211` core.

My focus is on the modified code: `include/net/mac80211.h`, `net/mac80211/cfg.c`, `net/mac80211/driver-ops.c`, `net/mac80211/driver-ops.h`, and `net/mac80211/sta_info.c`. The instructions say to only return `WorthFuzzing=false` if *all* modified code falls into the unreachable hardware category.  Since `mac80211` is part of the core wireless networking subsystem, and, importantly, can be exercised with `mac80211_hwsim`, this isn't true. Section 3 of the instructions specifically calls out *core subsystems* and *reachable drivers* as reasons to return `WorthFuzzing=true`.

Now, digging deeper, the introduction of `drv_sta_set_airtime_weight()` and its calls within `net/mac80211/cfg.c`, `net/mac80211/driver-ops.c`, and `net/mac80211/sta_info.c` is the core of the change.  Importantly, I need to figure out how these functions are reached.  `sta_apply_parameters()` called from `ieee80211_add_station` and `ieee80211_change_station` which are callbacks for `cfg80211_ops`, which are registered by mac80211. Crucially, these functions are called when a user process sends netlink messages, such as `NL80211_CMD_NEW_STATION` or `NL80211_CMD_SET_STATION` with `NL80211_ATTR_AIRTIME_WEIGHT`. This means that the added functionality is directly reachable from userspace, which is fantastic!  The call stack is: `nl80211_set_station` -> `rdev_change_station` -> `local->ops->change_station` (i.e. `ieee80211_change_station`) -> `sta_apply_parameters()`.  The same is true for `drv_sta_state()` and `sta_info_insert_drv_state()`.

The `drv_sta_set_airtime_weight()` function itself includes `might_sleep()`, `lockdep_assert_wiphy()`, and tracepoints.  This is significant. If these checks have a chance of triggering, there's a possibility of finding locking or sleeping violations. That makes this code *very* interesting from a fuzzing perspective, because it can find locking and sleeping violations. This is reachable and executable code within the wireless networking core.

Therefore, `WorthFuzzing=true`.

Now, I need to determine the `FocusSymbols`. Per the instructions, I need to avoid ubiquitous functions, and target specific feature logic and entry points.  So, looking at the `net/mac80211/cfg.c` changes, `sta_apply_parameters()` itself is a candidate. To prevent diluting the fuzzing effort with ubiquitous functions, I should identify the entry points to `sta_apply_parameters()`, which are `ieee80211_add_station` and `ieee80211_change_station`, because they are the non-static functions that call `sta_apply_parameters`.  I need to double-check their static/non-static status in `cfg.c` though, just to be sure.  Let's add these to the FocusSymbols.



38/2 2026/10/03 16:09 tool read-file
0m Args:
{
  "File": "net/mac80211/cfg.c",
  "FirstLine": 2668,
  "LineCount": 30
}

Results:
{
  "Contents": "2668:\t}\n2669:\t\n2670:\tstatic int ieee80211_add_station(struct wiphy *wiphy, struct wireless_dev *wdev,\n2671:\t\t\t\t\t const u8 *mac,\n2672:\t\t\t\t\t struct station_parameters *params)\n2673:\t{\n2674:\t\tstruct ieee80211_local *local = wiphy_priv(wiphy);\n2675:\t\tstruct sta_info *sta;\n2676:\t\tstruct ieee80211_sub_if_data *sdata;\n2677:\t\tint err;\n2678:\t\n2679:\t\tlockdep_assert_wiphy(local-\u003ehw.wiphy);\n2680:\t\n2681:\t\tif (params-\u003evlan) {\n2682:\t\t\tsdata = IEEE80211_DEV_TO_SUB_IF(params-\u003evlan);\n2683:\t\n2684:\t\t\tif (sdata-\u003evif.type != NL80211_IFTYPE_AP_VLAN \u0026\u0026\n2685:\t\t\t    sdata-\u003evif.type != NL80211_IFTYPE_AP)\n2686:\t\t\t\treturn -EINVAL;\n2687:\t\t} else\n2688:\t\t\tsdata = IEEE80211_WDEV_TO_SUB_IF(wdev);\n2689:\t\n2690:\t\tif (ether_addr_equal(mac, sdata-\u003evif.addr))\n2691:\t\t\treturn -EINVAL;\n2692:\t\n2693:\t\tif (!is_valid_ether_addr(mac))\n2694:\t\t\treturn -EINVAL;\n2695:\t\n2696:\t\tif (params-\u003esta_flags_set \u0026 BIT(NL80211_STA_FLAG_TDLS_PEER) \u0026\u0026\n2697:\t\t    sdata-\u003evif.type == NL80211_IFTYPE_STATION \u0026\u0026\n"
}

39/2 2026/10/03 16:09 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 40028
							output: 33
							thoughts: 96
						

Thoughts:
Here's my thought process, as it stands:

**Navigating the mac80211 Driver State**

Okay, so I need to check the `drv_sta_state` function. Let's start by looking at its implementation, which I believe should be in `net/mac80211/driver-ops.c`. Hold on, is this a static function, or is it exposed? I can't immediately recall. Right, it's not static! The declaration is `int drv_sta_state(struct ieee80211_local *local, ...)`. Now I should pop over to `net/mac80211/driver-ops.h` to confirm the declaration and any associated structures. That'll be the best way to get a solid grasp of its purpose.



40/2 2026/10/03 16:09 tool grepper
0m Args:
{
  "Expression": "drv_sta_state",
  "PathPrefix": "net/mac80211"
}

Results:
{
  "Output": "net/mac80211/cfg.c=2154=static int sta_apply_auth_flags(struct ieee80211_local *local,\n--\nnet/mac80211/cfg.c-2173-\t\t * well. Some drivers require rate control initialized\nnet/mac80211/cfg.c:2174:\t\t * before drv_sta_state() is called.\nnet/mac80211/cfg.c-2175-\t\t */\n--\nnet/mac80211/driver-ops.c=133=__must_check\nnet/mac80211/driver-ops.c:134:int drv_sta_state(struct ieee80211_local *local,\nnet/mac80211/driver-ops.c-135-\t\t  struct ieee80211_sub_if_data *sdata,\n--\nnet/mac80211/driver-ops.c-148-\nnet/mac80211/driver-ops.c:149:\ttrace_drv_sta_state(local, sdata, \u0026sta-\u003esta, old_state, new_state);\nnet/mac80211/driver-ops.c-150-\tif (local-\u003eops-\u003esta_state) {\n--\nnet/mac80211/driver-ops.h=589=__must_check\nnet/mac80211/driver-ops.h:590:int drv_sta_state(struct ieee80211_local *local,\nnet/mac80211/driver-ops.h-591-\t\t  struct ieee80211_sub_if_data *sdata,\n--\nnet/mac80211/sta_info.c=857=static int sta_info_insert_drv_state(struct ieee80211_local *local,\n--\nnet/mac80211/sta_info.c-864-\tfor (state = IEEE80211_STA_NOTEXIST; state \u003c sta-\u003esta_state; state++) {\nnet/mac80211/sta_info.c:865:\t\terr = drv_sta_state(local, sdata, sta, state, state + 1);\nnet/mac80211/sta_info.c-866-\t\tif (err)\n--\nnet/mac80211/sta_info.c-893-\tfor (; state \u003e IEEE80211_STA_NOTEXIST; state--)\nnet/mac80211/sta_info.c:894:\t\tWARN_ON(drv_sta_state(local, sdata, sta, state, state - 1));\nnet/mac80211/sta_info.c-895-\n--\nnet/mac80211/sta_info.c=1400=static int _sta_info_move_state(struct sta_info *sta,\n--\nnet/mac80211/sta_info.c-1447-\t    test_sta_flag(sta, WLAN_STA_INSERTED)) {\nnet/mac80211/sta_info.c:1448:\t\tint err = drv_sta_state(sta-\u003elocal, sta-\u003esdata, sta,\nnet/mac80211/sta_info.c-1449-\t\t\t\t\tsta-\u003esta_state, new_state);\n--\nnet/mac80211/sta_info.c-1528-\t    test_sta_flag(sta, WLAN_STA_INSERTED)) {\nnet/mac80211/sta_info.c:1529:\t\tint err = drv_sta_state(sta-\u003elocal, sta-\u003esdata, sta,\nnet/mac80211/sta_info.c-1530-\t\t\t\t\tsta-\u003esta_state, new_state);\n--\nnet/mac80211/sta_info.c=1548=static void __sta_info_destroy_part2(struct sta_info *sta, bool recalc)\n--\nnet/mac80211/sta_info.c-1607-\tif (sta-\u003euploaded) {\nnet/mac80211/sta_info.c:1608:\t\tret = drv_sta_state(local, sdata, sta, IEEE80211_STA_NONE,\nnet/mac80211/sta_info.c-1609-\t\t\t\t    IEEE80211_STA_NOTEXIST);\n--\nnet/mac80211/trace.h=880=TRACE_EVENT(drv_sta_notify,\n--\nnet/mac80211/trace.h-907-\nnet/mac80211/trace.h:908:TRACE_EVENT(drv_sta_state,\nnet/mac80211/trace.h-909-\tTP_PROTO(struct ieee80211_local *local,\n--\nnet/mac80211/util.c=1751=static void ieee80211_reconfig_stations(struct ieee80211_sub_if_data *sdata)\n--\nnet/mac80211/util.c-1766-\t\t     state \u003c sta-\u003esta_state; state++)\nnet/mac80211/util.c:1767:\t\t\tWARN_ON(drv_sta_state(local, sta-\u003esdata, sta, state,\nnet/mac80211/util.c-1768-\t\t\t\t\t      state + 1));\n--\nnet/mac80211/util.c=1806=static int ieee80211_reconfig_nan(struct ieee80211_sub_if_data *sdata)\n--\nnet/mac80211/util.c-1839-\t\t     state++) {\nnet/mac80211/util.c:1840:\t\t\tres = drv_sta_state(local, sdata, sta, state,\nnet/mac80211/util.c-1841-\t\t\t\t\t    state + 1);\n--\nnet/mac80211/util.c-1867-\t\t     state++) {\nnet/mac80211/util.c:1868:\t\t\tres = drv_sta_state(local, sta-\u003esdata, sta, state,\nnet/mac80211/util.c-1869-\t\t\t\t\t    state + 1);\n"
}

41/2 2026/10/03 16:09 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 41998
							output: 37
							thoughts: 89
						

Thoughts:
Here's my thought process, as if I were considering this myself:

**Investigating a Mac80211 Symbol**

Okay, so `drv_sta_state` is a non-static, visible function in `mac80211`. That immediately flags something to look at – it's exposed outside the module. Now, I'm wondering if there's a corresponding function used for inserting the driver state information, a "cousin" so to speak. Maybe something like `sta_info_insert_rcu` or, ideally, a function explicitly handling the driver state insertion, like `sta_info_insert_drv_state`? That name feels like it would be the most relevant.

Right, time to check the callsites of `sta_info_insert_drv_state` within `net/mac80211/sta_info.c`. Gotta understand how that symbol is used within the module itself before I can assess its broader impact. Let's see what the code's doing!



42/2 2026/10/03 16:10 tool grepper
0m Args:
{
  "Expression": "sta_info_insert_drv_state",
  "PathPrefix": "net/mac80211"
}

Results:
{
  "Output": "net/mac80211/sta_info.c=818=static int sta_info_insert_check(struct sta_info *sta)\n--\nnet/mac80211/sta_info.c-856-\nnet/mac80211/sta_info.c:857:static int sta_info_insert_drv_state(struct ieee80211_local *local,\nnet/mac80211/sta_info.c-858-\t\t\t\t     struct ieee80211_sub_if_data *sdata,\n--\nnet/mac80211/sta_info.c=925=static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)\n--\nnet/mac80211/sta_info.c-977-\t/* notify driver */\nnet/mac80211/sta_info.c:978:\terr = sta_info_insert_drv_state(local, sdata, sta);\nnet/mac80211/sta_info.c-979-\tif (err)\n"
}

43/2 2026/10/03 16:10 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 42639
							output: 35
							thoughts: 15
						

Thoughts:
Here's a breakdown of what I'm thinking, based on the prompt:

**Analyzing the `sta_info_insert_finish` Call**

Okay, so the prompt wants me to analyze `sta_info_insert_finish`. My first thought is: *What exactly is this function doing? What's the context?* Without more information about the codebase, it's hard to make a definitive analysis, but I can make educated guesses.

I'm assuming this is related to something like station information. Given the naming conventions used in well-engineered wireless stacks, the prefix "sta" likely refers to "station," probably a client device associated with an access point. The "info" suggests that it deals with data about the client, and "insert_finish" clearly implies the completion of an insertion process.

My immediate thought process involves some questions I'd be trying to answer:

*   **Data Structures:** What data structures are involved? There's likely a `struct sta_info` (or similar) that holds station-specific data. I'd want to know if this function is responsible for the final steps of populating this struct, or maybe adding the filled struct to a linked list.
*   **Synchronization:** Where is this function called from? Is it called from an interrupt context, a tasklet, or a regular process context? If it's a critical section, how is it protected against concurrent access? Locking schemes are important to consider to prevent race conditions.
*   **Error Handling:** Does it check for errors? Is there a return value or other mechanism to signal success or failure? Does it have any implications for graceful degradation or system recovery?
*   **Memory Management:** How is the memory for the `sta_info` allocated and deallocated? Is there any risk of memory leaks or buffer overflows?
*   **Context:** Does the function have any implications for connection or disconnection processes? Is it the last step of the authentication sequence?

To really dig into this, I'd need to trace the call, look at the callers, and the callee. Is the call within a larger context of other calls. Ultimately I would try to reverse engineer the code and draw inferences from the codebase.



44/2 2026/10/03 16:10 tool grepper
0m Args:
{
  "Expression": "sta_info_insert_finish",
  "PathPrefix": "net/mac80211"
}

Results:
{
  "Output": "net/mac80211/sta_info.c=900=ieee80211_recalc_p2p_go_ps_allowed(struct ieee80211_sub_if_data *sdata)\n--\nnet/mac80211/sta_info.c-924-\nnet/mac80211/sta_info.c:925:static int sta_info_insert_finish(struct sta_info *sta) __acquires(RCU)\nnet/mac80211/sta_info.c-926-{\n--\nnet/mac80211/sta_info.c=1040=int sta_info_insert_rcu(struct sta_info *sta) __acquires(RCU)\n--\nnet/mac80211/sta_info.c-1054-\nnet/mac80211/sta_info.c:1055:\treturn sta_info_insert_finish(sta);\nnet/mac80211/sta_info.c-1056-}\n"
}

45/2 2026/10/03 16:10 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 43437
							output: 51
							thoughts: 134
						

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

**Investigating the Reach of `sta_info_insert_rcu`**

Okay, so `sta_info_insert_rcu` isn't static. That immediately opens up the possibility of external calls. I need to understand its broader usage, specifically within the context of the mac80211 framework. Let's see... the `net/mac80211/cfg.c` file seems like a logical place to start digging, given it deals with configuration.

I need to quickly identify the functions that call `sta_apply_parameters`, since `sta_info_insert_rcu` is ultimately part of the station configuration process. A quick scan of `cfg.c` reveals two key functions: line 2724, which calls `ieee80211_add_station`, and line 2917, which calls `ieee80211_change_station`.

Now, the critical question is the calling context of those functions. Where are `ieee80211_add_station` and `ieee80211_change_station` themselves referenced within `cfg.c`? Knowing where *they* are called from will show me the points of insertion and modification of station information which ultimately call `sta_info_insert_rcu`.



46/2 2026/10/03 16:10 tool grepper
0m Args:
{
  "Expression": "ieee80211_add_station|ieee80211_change_station",
  "PathPrefix": "net/mac80211"
}

Results:
{
  "Output": "net/mac80211/cfg.c=2479=static int sta_apply_parameters(struct ieee80211_local *local,\n--\nnet/mac80211/cfg.c-2592-\t * Some of the following updates would be racy if called on an\nnet/mac80211/cfg.c:2593:\t * existing station, via ieee80211_change_station(). However,\nnet/mac80211/cfg.c-2594-\t * all such changes are rejected by cfg80211 except for updates\n--\nnet/mac80211/cfg.c-2669-\nnet/mac80211/cfg.c:2670:static int ieee80211_add_station(struct wiphy *wiphy, struct wireless_dev *wdev,\nnet/mac80211/cfg.c-2671-\t\t\t\t const u8 *mac,\n--\nnet/mac80211/cfg.c=2764=static int ieee80211_set_sta_4addr(struct ieee80211_local *local,\n--\nnet/mac80211/cfg.c-2822-\nnet/mac80211/cfg.c:2823:static int ieee80211_change_station(struct wiphy *wiphy,\nnet/mac80211/cfg.c-2824-\t\t\t\t    struct wireless_dev *wdev, const u8 *mac,\n--\nnet/mac80211/cfg.c=6031=const struct cfg80211_ops mac80211_config_ops = {\n--\nnet/mac80211/cfg.c-6045-\t.stop_ap = ieee80211_stop_ap,\nnet/mac80211/cfg.c:6046:\t.add_station = ieee80211_add_station,\nnet/mac80211/cfg.c-6047-\t.del_station = ieee80211_del_station,\nnet/mac80211/cfg.c:6048:\t.change_station = ieee80211_change_station,\nnet/mac80211/cfg.c-6049-\t.get_station = ieee80211_get_station,\n"
}

47/2 2026/10/03 16:10 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 44556
							output: 41
							thoughts: 1655
						

Thoughts:
**Focusing on Target Symbols and Configurations for mac80211 Airtime Weight Changes**

Okay, so I'm digging into these static functions, `ieee80211_add_station` and `ieee80211_change_station`, within `net/mac80211/cfg.c`. While they are static, I know those symbols will still exist in vmlinux unless completely inlined. My initial thought is to figure out the relevant symbols for mac80211 that are related to this change.

I was considering including: `drv_sta_state`, `sta_info_insert_rcu`, `sta_apply_parameters`, `ieee80211_add_station`, and `ieee80211_change_station`.

Now, the question becomes: do I need to include symbols from `ath11k` as well? I have to remember, syzkaller will only hit `ath11k` functions in QEMU if the hardware is emulated. However, mac80211 functions are reachable in QEMU with mac80211_hwsim! So I'm thinking, listing unreachable symbols won't help. I'm going to follow the instructions more closely here, and that means listing the functions that *specifically* implement the changed logic or are the entrypoints to the feature.

Let's see. The airtime weight feature has touched:

*   `drv_sta_state`
*   `sta_apply_parameters`
*   `ieee80211_add_station`
*   `ieee80211_change_station`
*   `sta_info_insert_drv_state` (or `sta_info_insert_rcu`)

Now, I'm remembering `drv_sta_set_airtime_weight` is a static inline function in `net/mac80211/driver-ops.h`. So I need to identify non-static callers that exercise it. The callers are: `drv_sta_state`, `sta_apply_parameters` (called by `ieee80211_add_station` and `ieee80211_change_station`), and `sta_info_insert_drv_state` (or `sta_info_insert_rcu`).

So, `drv_sta_state` is non-static and in `net/mac80211/driver-ops.c`. Similarly, `sta_info_insert_rcu` is non-static in `net/mac80211/sta_info.c`. I need to remember: `ieee80211_add_station` and `ieee80211_change_station` are static in `net/mac80211/cfg.c`. Also, `sta_apply_parameters` is static.

Then, there's the `ath11k` question. I see functions like `ath11k_mac_op_sta_set_airtime_weight`. But, "List functions that specifically implement the logic being added or altered, or direct API entrypoints for the subsystem feature under review." Only the mac80211 functions do this.

So, I think I'll include:

*   `drv_sta_state`
*   `sta_info_insert_rcu`
*   `ieee80211_change_station`
*   `ieee80211_add_station`
*   `sta_apply_parameters`

These directly exercise the changes.

Now, let's nail down the configs. What's needed for mac80211 and the virtual driver? Checking Kconfig, I see: `MAC80211` and `CFG80211`. `MAC80211` depends on `CFG80211`. Also, `MAC80211_HWSIM` depends on `MAC80211`.

What about `ATH11K`? Should it be included? Well, I checked, and `ATH11K`, `ATH11K_PCI`, and `ATH11K_AHB` compile. But do I want to include it? No. Following the prompt, I'll identify the configs that are needed to compile *and* reach the modified code.

So, here's the final list:

*   `MAC80211`
*   `CFG80211`
*   `MAC8021


48/2 2026/10/03 16:10 tool read-file
0m Args:
{
  "File": "drivers/net/wireless/ath/ath11k/Kconfig",
  "FirstLine": 1,
  "LineCount": 40
}

Results:
{
  "Contents": "   1:\t# SPDX-License-Identifier: BSD-3-Clause-Clear\n   2:\tconfig ATH11K\n   3:\t\ttristate \"Qualcomm 802.11ax chipset support\"\n   4:\t\tdepends on MAC80211 \u0026\u0026 HAS_DMA\n   5:\t\tselect ATH_COMMON\n   6:\t\tselect QCOM_QMI_HELPERS\n   7:\t\thelp\n   8:\t\t  This module adds support for Qualcomm Technologies 802.11ax family of\n   9:\t\t  chipsets.\n  10:\t\n  11:\t\t  If you choose to build a module, it'll be called ath11k.\n  12:\t\n  13:\tconfig ATH11K_AHB\n  14:\t\ttristate \"Atheros ath11k AHB support\"\n  15:\t\tdepends on ATH11K\n  16:\t\tdepends on REMOTEPROC\n  17:\t\tselect RPMSG\n  18:\t\tselect QRTR\n  19:\t\tselect QRTR_SMD\n  20:\t\thelp\n  21:\t\t  This module adds support for AHB bus\n  22:\t\n  23:\tconfig ATH11K_PCI\n  24:\t\ttristate \"Atheros ath11k PCI support\"\n  25:\t\tdepends on ATH11K \u0026\u0026 PCI \u0026\u0026 PCIEASPM\n  26:\t\tselect MHI_BUS\n  27:\t\tselect QRTR\n  28:\t\tselect QRTR_MHI\n  29:\t\tselect PCI_PWRCTRL_PWRSEQ if HAVE_PWRCTRL\n  30:\t\thelp\n  31:\t\t  This module adds support for PCIE bus\n  32:\t\n  33:\tconfig ATH11K_DEBUG\n  34:\t\tbool \"QCA ath11k debugging\"\n  35:\t\tdepends on ATH11K\n  36:\t\thelp\n  37:\t\t  Enables debug support\n  38:\t\n  39:\t\t  If unsure, say Y to make it easier to debug problems.\n  40:\t\n"
}

49/2 2026/10/03 16:10 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 47793
							output: 36
							thoughts: 235
						

Thoughts:
**Navigating the MAC80211 Dependency Labyrinth**

Okay, so I'm digging into this `ATH11K` module, and immediately I see it's linked to `MAC80211` and, crucially, requires `HAS_DMA`. Makes sense, they often go hand-in-hand. Then I see `MAC80211` itself is contingent on `CFG80211`. Standard stuff for modern wireless stacks. I'm also noticing `MAC80211_HWSIM` – that's the hardware simulator – depends on `MAC80211`. That part seems straightforward, but a red flag just went up.

Now I have to stop and think... is `MAC80211_HWSIM` actually *required* here? Without it, or maybe a software device driver like `VIRT_WIFI`, won't I run into issues? I'm thinking about QEMU, and my mind's screaming, "No registered device or wiphy!" Without something to emulate a wireless interface, the whole thing falls apart.

Ah, I remember! Syzkaller uses `MAC80211_HWSIM` to build these simulated wifi devices for testing `mac80211` and `nl80211`. So it's essential for that environment. Then I have to think about what components will compile if `MAC80211` is enabled. Since enabling `MAC80211` compiles the all-important modified files in `net/mac80211/`, it means the `mac80211` directory is involved.

Okay, I need to know which configs are responsible for enabling `net/mac80211` in the first place. That's what I'll do... I'll dive into the `net/mac80211/Makefile` and see what's what.



50/2 2026/10/03 16:10 tool read-file
0m Args:
{
  "File": "net/mac80211/Makefile",
  "FirstLine": 1,
  "LineCount": 40
}

Results:
{
  "Contents": "   1:\t# SPDX-License-Identifier: GPL-2.0\n   2:\tobj-$(CONFIG_MAC80211) += mac80211.o\n   3:\t\n   4:\t# mac80211 objects\n   5:\tmac80211-y := \\\n   6:\t\tmain.o status.o \\\n   7:\t\tdriver-ops.o \\\n   8:\t\tsta_info.o \\\n   9:\t\twep.o \\\n  10:\t\taead_api.o \\\n  11:\t\twpa.o \\\n  12:\t\tscan.o offchannel.o \\\n  13:\t\tht.o agg-tx.o agg-rx.o \\\n  14:\t\tvht.o \\\n  15:\t\the.o \\\n  16:\t\ts1g.o \\\n  17:\t\tibss.o \\\n  18:\t\tiface.o \\\n  19:\t\tlink.o \\\n  20:\t\trate.o \\\n  21:\t\ttkip.o \\\n  22:\t\taes_cmac.o \\\n  23:\t\taes_gmac.o \\\n  24:\t\tfils_aead.o \\\n  25:\t\tcfg.o \\\n  26:\t\tethtool.o \\\n  27:\t\trx.o \\\n  28:\t\tspectmgmt.o \\\n  29:\t\ttx.o \\\n  30:\t\tkey.o \\\n  31:\t\tutil.o parse.o \\\n  32:\t\twme.o \\\n  33:\t\tchan.o ap.o \\\n  34:\t\ttrace.o mlme.o \\\n  35:\t\ttdls.o \\\n  36:\t\tocb.o \\\n  37:\t\tairtime.o \\\n  38:\t\teht.o uhr.o nan.o\n  39:\t\n  40:\tmac80211-$(CONFIG_MAC80211_LEDS) += led.o\n"
}

51/2 2026/10/03 16:10 llm patch-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 49006
							output: 283
							thoughts: 1443
						

Thoughts:
**Focusing on Reachable mac80211 Code for Effective Fuzzing**

Alright, let's break this down. My main concern here is maximizing the effectiveness of fuzzing. We're dealing with modifications that touch both the `ath11k` vendor driver and, crucially, the core `mac80211` networking stack.

The key is reachability. While `ath11k` is hardware-dependent and not directly emulated in standard environments, the changes we're making to `mac80211` are executable and reachable within a virtual QEMU environment, specifically through the `mac80211_hwsim` module and netlink commands. This is confirmed by the build process, where `mac80211.o` compiles critical modules and it depends on `CONFIG_CFG80211`. We're using `MAC80211_HWSIM` to simulate the virtual radio. And of course, `ATH11K` checks for build breakage.

So, the game plan is to focus our fuzzing efforts on these accessible parts of `mac80211`. That means we need to identify the right symbols. The initial list includes `drv_sta_state`, `sta_apply_parameters`, `ieee80211_add_station`, `ieee80211_change_station`, and `sta_info_insert_rcu`. After checking them, it's pretty clear that these are specific to station management and, crucially, not ubiquitous hot-paths that would waste fuzzing resources.

Crucially, `ath11k_mac_op_sta_set_airtime_weight` is a callback that could be reachable if someone has the hardware or mocked it. But it may not be reachable in the base QEMU/GCE configuration.

To ensure reachability, we must avoid listing symbols that cannot be reached in a standard, virtualized environment. However, we also need to avoid listing generic, ubiquitous functions. We must instead target specific feature logic and entry points.

Given that `sta_apply_parameters` and `drv_sta_state` are entry points to mac80211 with a symbol, this should be perfect. These are direct operations, which cannot be inlined, ensuring they will be fuzzed by the Syzkaller tool.

The configurations to be listed are:
*   `CFG80211`
*   `MAC80211`
*   `MAC80211_HWSIM`
*   `ATH11K`

The logic is sound. We have a patch that modifies both the vendor driver and the core networking stack. While the vendor driver is hardware-bound, the `mac80211` changes are executable and reachable via `mac80211_hwsim` and `nl80211` netlink commands. The modified code introduces assertions and alters critical state handling. Thus, this is indeed worth fuzzing, and we can now confidently call set-results.



52/2 2026/10/03 16:10 tool set-results
0m Args:
{
  "EnableConfigs": [
    "CFG80211",
    "MAC80211",
    "MAC80211_HWSIM",
    "ATH11K"
  ],
  "FocusSymbols": [
    "drv_sta_state",
    "sta_apply_parameters",
    "ieee80211_add_station",
    "ieee80211_change_station",
    "sta_info_insert_rcu"
  ],
  "Reasoning": "The patch introduces driver callbacks and core mac80211 support for configuring station airtime weights, alongside ath11k driver support. Although ath11k requires physical hardware, the modifications to the mac80211 core networking subsystem (in net/mac80211/cfg.c, driver-ops.c, driver-ops.h, and sta_info.c) are executable in standard virtualized environments via mac80211_hwsim and nl80211 netlink commands. The new helper drv_sta_set_airtime_weight introduces runtime checks (might_sleep() and lockdep_assert_wiphy()) and is triggered upon station insertion and parameter modification, making it worth fuzzing.",
  "WorthFuzzing": true
}

Results:
{
  "EnableConfigs": [
    "CFG80211",
    "MAC80211",
    "MAC80211_HWSIM",
    "ATH11K"
  ],
  "FocusSymbols": [
    "drv_sta_state",
    "sta_apply_parameters",
    "ieee80211_add_station",
    "ieee80211_change_station",
    "sta_info_insert_rcu"
  ],
  "Reasoning": "The patch introduces driver callbacks and core mac80211 support for configuring station airtime weights, alongside ath11k driver support. Although ath11k requires physical hardware, the modifications to the mac80211 core networking subsystem (in net/mac80211/cfg.c, driver-ops.c, driver-ops.h, and sta_info.c) are executable in standard virtualized environments via mac80211_hwsim and nl80211 netlink commands. The new helper drv_sta_set_airtime_weight introduces runtime checks (might_sleep() and lockdep_assert_wiphy()) and is triggered upon station insertion and parameter modification, making it worth fuzzing.",
  "WorthFuzzing": true
}

53/1 2026/10/03 16:10 action If
2m Args:
{
  "WorthFuzzing": true
}

Results:
null

54/2 2026/10/03 16:10 agent kmsan-evaluator
2m Model:
core

Args:
null

Results:
{
  "KMSANReasoning": "The patch adds beacon protection and airtime fairness (ATF) support to the ath11k driver and mac80211 subsystem, expands supported cipher suites and key table indices, and exposes WMI services via debugfs.\n\nThere are no uninitialized memory risks or kernel-to-user info-leak vectors introduced:\n- All new struct fields (`beacon_prot` in `struct ath11k_vif`, `airtime_weight` in `struct ath11k_sta`, and the expanded `keys` array in `struct ath11k_peer`) are part of structures allocated via `kzalloc` (or explicitly cleared via `memset` in `ath11k_mac_op_sta_state`) and set to well-defined default constants (`IEEE80211_DEFAULT_AIRTIME_WEIGHT`).\n- In `ath11k_mac_atf_update()`, local structs use designated initializers (zeroing remaining fields) and buffers are allocated using `kcalloc`.\n- WMI command skbs are allocated using `ath11k_wmi_alloc_skb()`, which explicitly zeroes the buffer (`memset(skb-\u003edata, 0, round_len)`).\n- The debugfs attribute `ath11k_wmi_services_show()` iterates over `ab-\u003ewmi_ab.svc_map` (part of kzalloc'd `ath11k_base`) using `for_each_set_bit()` up to `WMI_MAX_EXT2_SERVICE` and prints bit indices; it does not read uninitialized data.\n- Beacon parsing in `ath11k_mac_bcn_prot_enabled()` parses IE buffers; any potential indexing issues or bounds errors would be out-of-bounds reads covered by KASAN.\n\nBecause the changes do not expose uninitialized memory reads or information leaks to userspace, a dedicated KMSAN fuzzing run is not justified; standard KASAN fuzzing is sufficient.",
  "NeedsKMSAN": false
}

Instruction:
You are an expert Linux kernel security engineer specializing in kernel memory
error detectors (KASAN and KMSAN). Your job is to review the provided patch series and
determine if the code changes justify spawning a dedicated KMSAN (KernelMemorySanitizer)
fuzzing session in addition to standard KASAN fuzzing.

CRITICAL DISTINCTION BETWEEN KASAN AND KMSAN:
- Standard KASAN kernel builds (upstream-apparmor-kasan.config) already enable
  a comprehensive suite of debugging tools and sanitizers, including KASAN
  (out-of-bounds accesses, use-after-free, double free, invalid free), LOCKDEP
  (locking bugs and deadlocks), UB-sanitizers, and memory corruption checks.
- KMSAN (KernelMemorySanitizer) detects reads of UNINITIALIZED memory (stack, heap,
  or page allocations) and kernel-to-user memory info-leaks.

Rule: THERE IS NO SENSE IN RUNNING A KMSAN SESSION IF A BUG CAN BE CAUGHT BY KASAN,
LOCKDEP, OR OTHER STANDARD BUG DETECTORS.
A dedicated KMSAN fuzzing session incurs significant resource costs. You must ONLY
set NeedsKMSAN=true if the code changes introduce or expose UNINITIALIZED MEMORY risks
that are detected ONLY by KMSAN.

Look holistically at the patch series and surrounding code. Even if no direct
uninitialized field accesses or new buffer allocations are added in the diff itself,
a patch may alter control flow, bounds checking, or data length calculations in ways
that change how the rest of the code operates on existing buffers (e.g. allowing
uninitialized stack/heap memory to be read, copied to user space, or used in control
flow). Do not hesitate to use your code access tools to inspect the surrounding code,
called functions, and callers.

Set NeedsKMSAN=true ONLY IF the patch introduces or modifies:
1. Kernel structures sent to user space (via copy_to_user, put_user, netlink skb
   attributes, ioctl output arguments, socket options, or BPF buffers) where fields
   or structure padding might not be fully initialized/zeroed.
2. Conditional logic or branching that depends on potentially uninitialized variables
   or struct fields.
3. Allocation or initialization of complex data structures where uninitialized fields
   could be read later in reachable code paths.
4. Bounds checks, lengths, or logic in a way that allows surrounding code to access
   uninitialized bytes of existing buffers.

Set NeedsKMSAN=false IF:
- The code changes primarily risk out-of-bounds access, array overflows, NULL pointer
  dereferences, locking deadlocks, or use-after-free bugs (these are already caught
  by KASAN, LOCKDEP, or standard bug detectors).
- All stack/heap structures touched or introduced by the patch are fully zeroed
  or initialized (e.g. using = {0}, memset, kzalloc) before being read or copied.
- The patch does not introduce any risk of uninitialized memory usage or info-leaks.

Use your code access tools to inspect the surrounding code if necessary, then provide
detailed KMSANReasoning contrasting KASAN vs KMSAN applicability for this patch.
Prefer calling several tools at the same time to save round-trips.


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

Prompt:
Target architecture: amd64

For your convenience, here is the diff of the changes:
commit 8ccba6d098a12ba25e898d574a025ed50ab6c191
Author: syz-cluster <triage@syzkaller.com>
Date:   Sat Oct 3 16:08:28 2026 +0000

    syz-cluster: applied patch under review

diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index a0d725923ef24..bb5f730c88202 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -408,6 +408,7 @@ struct ath11k_vif {
 	int txpower;
 	bool rsnie_present;
 	bool wpaie_present;
+	bool beacon_prot;
 	bool bcca_zero_sent;
 	bool do_not_send_tmpl;
 	struct ath11k_arp_ns_offload arp_ns_offload;
@@ -541,6 +542,7 @@ struct ath11k_per_peer_cfr_capture {
 
 struct ath11k_sta {
 	struct ath11k_vif *arvif;
+	u16 airtime_weight;
 
 	/* the following are protected by ar->data_lock */
 	u32 changed; /* IEEE80211_RC_* */
diff --git a/drivers/net/wireless/ath/ath11k/debugfs.c b/drivers/net/wireless/ath/ath11k/debugfs.c
index 70922612d3fb9..75d2e81c77743 100644
--- a/drivers/net/wireless/ath/ath11k/debugfs.c
+++ b/drivers/net/wireless/ath/ath11k/debugfs.c
@@ -851,6 +851,18 @@ static const struct file_operations fops_sram_dump = {
 	.llseek = default_llseek,
 };
 
+static int ath11k_wmi_services_show(struct seq_file *m, void *v)
+{
+	struct ath11k_base *ab = m->private;
+	unsigned int i;
+
+	for_each_set_bit(i, ab->wmi_ab.svc_map, WMI_MAX_EXT2_SERVICE)
+		seq_printf(m, "%u\n", i);
+
+	return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(ath11k_wmi_services);
+
 int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
 {
 	if (test_bit(ATH11K_FLAG_REGISTERED, &ab->dev_flags))
@@ -862,6 +874,9 @@ int ath11k_debugfs_pdev_create(struct ath11k_base *ab)
 	debugfs_create_file("soc_dp_stats", 0400, ab->debugfs_soc, ab,
 			    &fops_soc_dp_stats);
 
+	debugfs_create_file("wmi_services", 0400, ab->debugfs_soc, ab,
+			    &ath11k_wmi_services_fops);
+
 	if (ab->hw_params.sram_dump.start != 0)
 		debugfs_create_file("sram", 0400, ab->debugfs_soc, ab,
 				    &fops_sram_dump);
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index c1fa42edd3630..7a03c12d2ebd4 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -1495,6 +1495,44 @@ static int ath11k_mac_remove_vendor_ie(struct sk_buff *skb, unsigned int oui,
 	return 0;
 }
 
+static bool ath11k_mac_ext_capa_bcn_prot(const struct element *ext_capa)
+{
+	return ext_capa && ext_capa->datalen >= 11 &&
+	       (ext_capa->data[10] & WLAN_EXT_CAPA11_BCN_PROTECT);
+}
+
+/* Beacon protection covers the whole beacon, so enable it when the
+ * transmitted BSS or any nontransmitted profile in it advertises it.
+ */
+static bool ath11k_mac_bcn_prot_enabled(struct sk_buff *bcn)
+{
+	struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)bcn->data;
+	const u8 *ies = mgmt->u.beacon.variable;
+	int ies_len = skb_tail_pointer(bcn) - ies;
+	const struct element *elem, *profile;
+
+	if (ath11k_mac_ext_capa_bcn_prot(cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY,
+							    ies, ies_len)))
+		return true;
+
+	for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, ies, ies_len) {
+		if (elem->datalen < 1)
+			continue;
+
+		for_each_element(profile, elem->data + 1, elem->datalen - 1) {
+			if (profile->id != 0)
+				continue;
+
+			if (ath11k_mac_ext_capa_bcn_prot(cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY,
+									    profile->data,
+									    profile->datalen)))
+				return true;
+		}
+	}
+
+	return false;
+}
+
 static int ath11k_mac_set_vif_params(struct ath11k_vif *arvif,
 				     struct sk_buff *bcn)
 {
@@ -1598,6 +1636,7 @@ static int ath11k_mac_setup_bcn_tmpl_ema(struct ath11k_vif *arvif,
 		params |= ((!i ? 1 : 0) << WMI_EMA_FIRST_TMPL_SHIFT);
 		params |= ((i + 1 == beacons->cnt ? 1 : 0) << WMI_EMA_LAST_TMPL_SHIFT);
 
+		tx_arvif->beacon_prot = ath11k_mac_bcn_prot_enabled(beacons->bcn[i].skb);
 		ret = ath11k_wmi_bcn_tmpl(tx_arvif->ar, tx_arvif->vdev_id,
 					  &beacons->bcn[i].offs,
 					  beacons->bcn[i].skb, params);
@@ -1651,6 +1690,7 @@ static int ath11k_mac_setup_bcn_tmpl_mbssid(struct ath11k_vif *arvif,
 		goto free;
 	}
 
+	arvif->beacon_prot = ath11k_mac_bcn_prot_enabled(bcn);
 	ret = ath11k_wmi_bcn_tmpl(ar, arvif->vdev_id, &offs, bcn, 0);
 	if (ret)
 		ath11k_warn(ab, "failed to submit beacon template command: %d\n",
@@ -4412,6 +4452,14 @@ static int ath11k_install_key(struct ath11k_vif *arvif,
 		arg.key_cipher = WMI_CIPHER_AES_GCM;
 		key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
 		break;
+	case WLAN_CIPHER_SUITE_AES_CMAC:
+	case WLAN_CIPHER_SUITE_BIP_CMAC_256:
+		arg.key_cipher = WMI_CIPHER_AES_CMAC;
+		break;
+	case WLAN_CIPHER_SUITE_BIP_GMAC_128:
+	case WLAN_CIPHER_SUITE_BIP_GMAC_256:
+		arg.key_cipher = WMI_CIPHER_AES_GMAC;
+		break;
 	default:
 		ath11k_warn(ar->ab, "cipher %d is not supported\n", key->cipher);
 		return -EOPNOTSUPP;
@@ -4523,11 +4571,10 @@ static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
 	int ret = 0;
 	u32 flags = 0;
 
-	/* BIP needs to be done in software */
-	if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC ||
-	    key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 ||
-	    key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 ||
-	    key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256)
+	/* The IGTK protects management frames, which are done in software;
+	 * only the BIGTK (index 6/7) goes to the firmware, which signs beacons.
+	 */
+	if (key->keyidx == 4 || key->keyidx == 5)
 		return 1;
 
 	if (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, &ar->ab->dev_flags))
@@ -6685,6 +6732,16 @@ static int ath11k_mac_op_start(struct ieee80211_hw *hw)
 		goto err;
 	}
 
+	if (test_bit(WMI_TLV_SERVICE_ATF, ab->wmi_ab.svc_map)) {
+		ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_ATF_DYNAMIC_ENABLE,
+						1, pdev->pdev_id);
+		if (ret) {
+			ath11k_err(ab, "failed to enable airtime fairness: %d\n",
+				   ret);
+			goto err;
+		}
+	}
+
 	ret = ath11k_wmi_send_dfs_phyerr_offload_enable_cmd(ar, pdev->pdev_id);
 	if (ret) {
 		ath11k_err(ab, "failed to offload radar detection: %d\n",
@@ -9938,6 +9995,90 @@ static int ath11k_mac_station_remove(struct ath11k *ar,
 	return ret;
 }
 
+#define ATH11K_ATF_PEERS_PER_CMD 32
+
+struct ath11k_mac_atf_iter {
+	struct ath11k_wmi_atf_peer_arg *peers;
+	u16 *weights;
+	u32 num, max, total;
+};
+
+static void ath11k_mac_atf_iter(void *data, struct ieee80211_sta *sta)
+{
+	struct ath11k_mac_atf_iter *it = data;
+	struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
+
+	if (it->num == it->max || !arsta->arvif ||
+	    arsta->arvif->vdev_type != WMI_VDEV_TYPE_AP)
+		return;
+
+	ether_addr_copy(it->peers[it->num].addr, sta->addr);
+	it->peers[it->num].vdev_id = arsta->arvif->vdev_id;
+	it->weights[it->num] = arsta->airtime_weight;
+	it->total += arsta->airtime_weight;
+	it->num++;
+}
+
+/* Firmware airtime fairness: give every station of the radio its share of
+ * the airtime, in proportion to its airtime weight. The firmware schedules
+ * a station only by the share of its group, so group 0 (every station's)
+ * gets the whole radio first.
+ */
+static int ath11k_mac_atf_update(struct ath11k *ar)
+{
+	struct ath11k_mac_atf_iter it = { .max = ar->max_num_stations };
+	u32 i, n;
+	int ret = 0;
+
+	lockdep_assert_held(&ar->conf_mutex);
+
+	if (!test_bit(WMI_TLV_SERVICE_ATF, ar->ab->wmi_ab.svc_map))
+		return 0;
+
+	it.peers = kcalloc(it.max, sizeof(*it.peers), GFP_KERNEL);
+	it.weights = kcalloc(it.max, sizeof(*it.weights), GFP_KERNEL);
+	if (!it.peers || !it.weights) {
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ieee80211_iterate_stations_atomic(ar->hw, ath11k_mac_atf_iter, &it);
+
+	for (i = 0; i < it.num; i++)
+		it.peers[i].units = max_t(u32, 1, div_u64((u64)WMI_ATF_DENOMINATION *
+							  it.weights[i], it.total));
+
+	ret = ath11k_wmi_send_atf_group(ar, 0, WMI_ATF_DENOMINATION);
+	if (ret)
+		goto out;
+
+	for (i = 0; i < it.num; i += n) {
+		n = min_t(u32, it.num - i, ATH11K_ATF_PEERS_PER_CMD);
+		ret = ath11k_wmi_send_peer_atf_request(ar, &it.peers[i], n,
+						       i + n < it.num);
+		if (ret)
+			break;
+	}
+
+out:
+	kfree(it.weights);
+	kfree(it.peers);
+	return ret;
+}
+
+static void ath11k_mac_op_sta_set_airtime_weight(struct ieee80211_hw *hw,
+						 struct ieee80211_vif *vif,
+						 struct ieee80211_sta *sta, u16 weight)
+{
+	struct ath11k_sta *arsta = ath11k_sta_to_arsta(sta);
+	struct ath11k *ar = hw->priv;
+
+	mutex_lock(&ar->conf_mutex);
+	arsta->airtime_weight = weight;
+	ath11k_mac_atf_update(ar);
+	mutex_unlock(&ar->conf_mutex);
+}
+
 static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
 				   struct ieee80211_vif *vif,
 				   struct ieee80211_sta *sta,
@@ -9965,6 +10106,7 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
 	    new_state == IEEE80211_STA_NONE) {
 		memset(arsta, 0, sizeof(*arsta));
 		arsta->arvif = arvif;
+		arsta->airtime_weight = IEEE80211_DEFAULT_AIRTIME_WEIGHT;
 		arsta->peer_ps_state = WMI_PEER_PS_STATE_DISABLED;
 		INIT_WORK(&arsta->update_wk, ath11k_sta_rc_update_wk);
 		INIT_WORK(&arsta->set_4addr_wk, ath11k_sta_set_4addr_wk);
@@ -9996,6 +10138,9 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
 		mutex_unlock(&ar->ab->tbl_mtx_lock);
 
 		ath11k_cfr_decrement_peer_count(ar, arsta);
+
+		if (vif->type == NL80211_IFTYPE_AP)
+			ath11k_mac_atf_update(ar);
 	} else if (old_state == IEEE80211_STA_AUTH &&
 		   new_state == IEEE80211_STA_ASSOC &&
 		   (vif->type == NL80211_IFTYPE_AP ||
@@ -10005,6 +10150,8 @@ static int ath11k_mac_op_sta_state(struct ieee80211_hw *hw,
 		if (ret)
 			ath11k_warn(ar->ab, "Failed to associate station: %pM\n",
 				    sta->addr);
+		else if (vif->type == NL80211_IFTYPE_AP)
+			ath11k_mac_atf_update(ar);
 
 		spin_lock_bh(&ar->data_lock);
 		/* Set arsta bw and prev bw */
@@ -10096,6 +10243,7 @@ static const struct ieee80211_ops ath11k_ops = {
 	.sta_state                      = ath11k_mac_op_sta_state,
 	.sta_set_4addr                  = ath11k_mac_op_sta_set_4addr,
 	.sta_set_txpwr			= ath11k_mac_op_sta_set_txpwr,
+	.sta_set_airtime_weight		= ath11k_mac_op_sta_set_airtime_weight,
 	.link_sta_rc_update		= ath11k_mac_op_sta_rc_update,
 	.conf_tx                        = ath11k_mac_op_conf_tx,
 	.set_antenna			= ath11k_mac_op_set_antenna,
@@ -10633,6 +10781,14 @@ static int __ath11k_mac_register(struct ath11k *ar)
 		wiphy_ext_feature_set(ar->hw->wiphy,
 				      NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER);
 
+	if (test_bit(WMI_TLV_SERVICE_BEACON_PROTECTION_SUPPORT, ar->ab->wmi_ab.svc_map))
+		wiphy_ext_feature_set(ar->hw->wiphy,
+				      NL80211_EXT_FEATURE_BEACON_PROTECTION);
+
+	if (test_bit(WMI_TLV_SERVICE_ATF, ar->ab->wmi_ab.svc_map))
+		wiphy_ext_feature_set(ar->hw->wiphy,
+				      NL80211_EXT_FEATURE_AIRTIME_FAIRNESS);
+
 	ar->hw->wiphy->mbssid_max_interfaces = TARGET_NUM_VDEVS(ab);
 	ar->hw->wiphy->ema_max_profile_periodicity = TARGET_EMA_MAX_PROFILE_PERIOD;
 
diff --git a/drivers/net/wireless/ath/ath11k/wmi.c b/drivers/net/wireless/ath/ath11k/wmi.c
index 08fd6795ed9e7..28f5d606ae039 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.c
+++ b/drivers/net/wireless/ath/ath11k/wmi.c
@@ -1811,6 +1811,8 @@ int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,
 	cmd->buf_len = bcn->len;
 	cmd->mbssid_ie_offset = offs->mbssid_off;
 	cmd->ema_params = ema_params;
+	if (arvif->beacon_prot)
+		cmd->feature_enable_bitmap |= WMI_BCN_TMPL_BEACON_PROTECTION_EN;
 
 	ptr = skb->data + sizeof(*cmd);
 
@@ -4466,6 +4468,100 @@ int ath11k_wmi_set_hw_mode(struct ath11k_base *ab,
 	return 0;
 }
 
+int ath11k_wmi_send_atf_group(struct ath11k *ar, u32 group_id, u32 units)
+{
+	struct ath11k_pdev_wmi *wmi = ar->wmi;
+	struct wmi_atf_ssid_grp_request_cmd *cmd;
+	struct wmi_atf_group_info *grp;
+	struct wmi_tlv *tlv;
+	struct sk_buff *skb;
+	int ret;
+
+	skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, sizeof(*cmd) + TLV_HDR_SIZE + sizeof(*grp));
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_atf_ssid_grp_request_cmd *)skb->data;
+	cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ATF_SSID_GRP_REQUEST) |
+			  FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
+	cmd->pdev_id = ar->pdev->pdev_id;
+
+	tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd));
+	tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) |
+		      FIELD_PREP(WMI_TLV_LEN, sizeof(*grp));
+	grp = (struct wmi_atf_group_info *)tlv->value;
+	grp->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ATF_GROUP_INFO) |
+			  FIELD_PREP(WMI_TLV_LEN, sizeof(*grp) - TLV_HDR_SIZE);
+	grp->atf_group_id = group_id;
+	grp->atf_group_units = units;
+	grp->atf_group_flags = WMI_ATF_GROUP_POLICY_FAIR;
+
+	ret = ath11k_wmi_cmd_send(wmi, skb, WMI_ATF_SSID_GROUPING_REQUEST_CMDID);
+	if (ret) {
+		ath11k_warn(ar->ab, "failed to send atf group request: %d\n", ret);
+		dev_kfree_skb(skb);
+		return ret;
+	}
+
+	ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd atf group %u units %u\n", group_id, units);
+
+	return 0;
+}
+
+int ath11k_wmi_send_peer_atf_request(struct ath11k *ar,
+				     const struct ath11k_wmi_atf_peer_arg *peers,
+				     u32 num_peers, bool more)
+{
+	struct ath11k_pdev_wmi *wmi = ar->wmi;
+	struct wmi_peer_atf_request_cmd *cmd;
+	struct wmi_atf_peer_info *info;
+	struct wmi_tlv *tlv;
+	struct sk_buff *skb;
+	u32 i, pdev_id = ar->pdev->pdev_id;
+	int ret, len;
+
+	len = sizeof(*cmd) + TLV_HDR_SIZE + num_peers * sizeof(*info);
+	skb = ath11k_wmi_alloc_skb(wmi->wmi_ab, len);
+	if (!skb)
+		return -ENOMEM;
+
+	cmd = (struct wmi_peer_atf_request_cmd *)skb->data;
+	cmd->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_PEER_ATF_REQUEST) |
+			  FIELD_PREP(WMI_TLV_LEN, sizeof(*cmd) - TLV_HDR_SIZE);
+	cmd->num_peers = num_peers;
+	cmd->pdev_id = pdev_id;
+	cmd->atf_flags = WMI_PEER_ATF_REQ_FLAG_FULL_UPDATE |
+			 WMI_PEER_ATF_REQ_FLAG_PDEV_ID_VALID;
+	if (more)
+		cmd->atf_flags |= WMI_PEER_ATF_REQ_FLAG_PENDING_CMDS;
+
+	tlv = (struct wmi_tlv *)(skb->data + sizeof(*cmd));
+	tlv->header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ARRAY_STRUCT) |
+		      FIELD_PREP(WMI_TLV_LEN, num_peers * sizeof(*info));
+	info = (struct wmi_atf_peer_info *)tlv->value;
+
+	for (i = 0; i < num_peers; i++, info++) {
+		info->tlv_header = FIELD_PREP(WMI_TLV_TAG, WMI_TAG_ATF_PEER_INFO) |
+				   FIELD_PREP(WMI_TLV_LEN, sizeof(*info) - TLV_HDR_SIZE);
+		ether_addr_copy(info->peer_macaddr.addr, peers[i].addr);
+		info->atf_units = peers[i].units;
+		info->vdev_id = peers[i].vdev_id;
+		info->pdev_id = pdev_id;
+	}
+
+	ret = ath11k_wmi_cmd_send(wmi, skb, WMI_PEER_ATF_REQUEST_CMDID);
+	if (ret) {
+		ath11k_warn(ar->ab, "failed to send peer atf request: %d\n", ret);
+		dev_kfree_skb(skb);
+		return ret;
+	}
+
+	ath11k_dbg(ar->ab, ATH11K_DBG_WMI, "cmd peer atf request pdev %u peers %u%s\n",
+		   pdev_id, num_peers, more ? " (more)" : "");
+
+	return 0;
+}
+
 int ath11k_wmi_cmd_init(struct ath11k_base *ab)
 {
 	struct ath11k_wmi_base *wmi_ab = &ab->wmi_ab;
@@ -4481,6 +4577,9 @@ int ath11k_wmi_cmd_init(struct ath11k_base *ab)
 		     ab->wmi_ab.svc_map))
 		config.is_reg_cc_ext_event_supported = 1;
 
+	if (test_bit(WMI_TLV_SERVICE_ATF, ab->wmi_ab.svc_map))
+		config.flag1 |= WMI_RSRC_CFG_FLAG1_ATF_CONFIG_ENABLE;
+
 	memcpy(&wmi_ab->wlan_resource_config, &config, sizeof(config));
 
 	init_param.res_cfg = &wmi_ab->wlan_resource_config;
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index b2dade0516ac7..53cce7fd7dff3 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -212,6 +212,7 @@ enum wmi_cmd_group {
 	WMI_GRP_TWT            = 0x3e,
 	WMI_GRP_MOTION_DET     = 0x3f,
 	WMI_GRP_SPATIAL_REUSE  = 0x40,
+	WMI_GRP_ATM            = 0x45,
 };
 
 #define WMI_CMD_GRP(grp_id) (((grp_id) << 12) | 0x1)
@@ -2128,6 +2129,7 @@ enum wmi_tlv_service {
 	WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET = 213,
 	WMI_TLV_SERVICE_FREQINFO_IN_METADATA = 219,
 	WMI_TLV_SERVICE_EXT2_MSG = 220,
+	WMI_TLV_SERVICE_BEACON_PROTECTION_SUPPORT = 244,
 	WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT = 246,
 	WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT = 249,
 	WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT = 253,
@@ -2353,6 +2355,7 @@ struct wmi_init_cmd {
 } __packed;
 
 #define WMI_RSRC_CFG_FLAG1_BSS_CHANNEL_INFO_64 BIT(5)
+#define WMI_RSRC_CFG_FLAG1_ATF_CONFIG_ENABLE BIT(6)
 #define WMI_RSRC_CFG_FLAG2_CALC_NEXT_DTIM_COUNT_SET BIT(9)
 #define WMI_RSRC_CFG_FLAG1_ACK_RSSI BIT(18)
 
@@ -3628,6 +3631,55 @@ struct ath11k_wmi_p2p_noa_info {
 #define WMI_EMA_FIRST_TMPL_SHIFT          16
 #define WMI_EMA_LAST_TMPL_SHIFT           24
 
+#define WMI_BCN_TMPL_BEACON_PROTECTION_EN BIT(0)
+
+/* Airtime fairness: a share is in parts per thousand of the radio's airtime */
+#define WMI_ATF_DENOMINATION			1000
+#define WMI_PEER_ATF_REQ_FLAG_FULL_UPDATE	BIT(0)
+#define WMI_PEER_ATF_REQ_FLAG_PENDING_CMDS	BIT(1)
+#define WMI_PEER_ATF_REQ_FLAG_PDEV_ID_VALID	BIT(2)
+#define WMI_ATF_GROUP_POLICY_FAIR		0
+
+#define WMI_ATF_SSID_GROUPING_REQUEST_CMDID	WMI_TLV_CMD(WMI_GRP_ATM)
+/* Outside enum wmi_tlv_tag: its WMI_TAG_MAX sizes the TLV policy table. */
+#define WMI_TAG_ATF_SSID_GRP_REQUEST		0x346
+#define WMI_TAG_ATF_GROUP_INFO			0x347
+
+struct wmi_atf_ssid_grp_request_cmd {
+	u32 tlv_header;
+	u32 pdev_id;
+} __packed;
+
+struct wmi_atf_group_info {
+	u32 tlv_header;
+	u32 atf_group_id;
+	u32 atf_group_units;
+	u32 atf_group_flags;
+} __packed;
+
+struct wmi_peer_atf_request_cmd {
+	u32 tlv_header;
+	u32 num_peers;
+	u32 pdev_id;
+	u32 atf_flags;
+} __packed;
+
+struct wmi_atf_peer_info {
+	u32 tlv_header;
+	struct wmi_mac_addr peer_macaddr;
+	u32 atf_units;
+	u32 atf_groupid;
+	u32 atf_units_reserved;
+	u32 vdev_id;
+	u32 pdev_id;
+} __packed;
+
+struct ath11k_wmi_atf_peer_arg {
+	u8 addr[ETH_ALEN];
+	u32 vdev_id;
+	u32 units;
+};
+
 struct wmi_bcn_tmpl_cmd {
 	u32 tlv_header;
 	u32 vdev_id;
@@ -5237,7 +5289,7 @@ enum wmi_ap_ps_peer_param {
 
 #define DISABLE_SIFS_RESPONSE_TRIGGER 0
 
-#define WMI_MAX_KEY_INDEX   3
+#define WMI_MAX_KEY_INDEX   7
 #define WMI_MAX_KEY_LEN     32
 
 #define WMI_KEY_PAIRWISE 0x00
@@ -6450,6 +6502,10 @@ int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,
 			  bool restart);
 int ath11k_wmi_set_peer_param(struct ath11k *ar, const u8 *peer_addr,
 			      u32 vdev_id, u32 param_id, u32 param_val);
+int ath11k_wmi_send_atf_group(struct ath11k *ar, u32 group_id, u32 units);
+int ath11k_wmi_send_peer_atf_request(struct ath11k *ar,
+				     const struct ath11k_wmi_atf_peer_arg *peers,
+				     u32 num_peers, bool more);
 int ath11k_wmi_pdev_set_param(struct ath11k *ar, u32 param_id,
 			      u32 param_value, u8 pdev_id);
 int ath11k_wmi_pdev_set_ps_mode(struct ath11k *ar, int vdev_id,
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index cb9f8e14b3b62..aab98d92ee5e1 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -4694,6 +4694,8 @@ struct ieee80211_prep_tx_info {
  * @set_sar_specs: Update the SAR (TX power) settings.
  * @sta_set_decap_offload: Called to notify the driver when a station is allowed
  *	to use rx decapsulation offload
+ * @sta_set_airtime_weight: Called to notify the driver of a change to a
+ *	station's airtime fairness weight, so it can be programmed in hardware.
  * @add_twt_setup: Update hw with TWT agreement parameters received from the peer.
  *	This callback allows the hw to check if requested parameters
  *	are supported and if there is enough room for a new agreement.
@@ -5108,6 +5110,9 @@ struct ieee80211_ops {
 	void (*sta_set_decap_offload)(struct ieee80211_hw *hw,
 				      struct ieee80211_vif *vif,
 				      struct ieee80211_sta *sta, bool enabled);
+	void (*sta_set_airtime_weight)(struct ieee80211_hw *hw,
+				       struct ieee80211_vif *vif,
+				       struct ieee80211_sta *sta, u16 weight);
 	void (*add_twt_setup)(struct ieee80211_hw *hw,
 			      struct ieee80211_sta *sta,
 			      struct ieee80211_twt_setup *twt);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index bd1a857c812d4..28f99a8f8acce 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2616,8 +2616,12 @@ static int sta_apply_parameters(struct ieee80211_local *local,
 	if (ieee80211_vif_is_mesh(&sdata->vif))
 		sta_apply_mesh_params(local, sta, params);
 
-	if (params->airtime_weight)
+	if (params->airtime_weight) {
 		sta->airtime_weight = params->airtime_weight;
+		if (sta->uploaded)
+			drv_sta_set_airtime_weight(local, sdata, &sta->sta,
+						   sta->airtime_weight);
+	}
 
 	if (params->nmi_mac) {
 		struct ieee80211_sub_if_data *nmi =
diff --git a/net/mac80211/driver-ops.c b/net/mac80211/driver-ops.c
index 49753b73aba26..083c2651754fd 100644
--- a/net/mac80211/driver-ops.c
+++ b/net/mac80211/driver-ops.c
@@ -157,6 +157,10 @@ int drv_sta_state(struct ieee80211_local *local,
 			sta->uploaded = true;
 			if (rcu_access_pointer(sta->sta.rates))
 				drv_sta_rate_tbl_update(local, sdata, &sta->sta);
+			if (sta->airtime_weight != IEEE80211_DEFAULT_AIRTIME_WEIGHT)
+				drv_sta_set_airtime_weight(local, sdata,
+							   &sta->sta,
+							   sta->airtime_weight);
 		}
 	} else if (old_state == IEEE80211_STA_ASSOC &&
 		   new_state == IEEE80211_STA_AUTH) {
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index f1c0b87fddd5f..bd5c9d1edcf57 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -1633,6 +1633,25 @@ static inline void drv_sta_set_decap_offload(struct ieee80211_local *local,
 	trace_drv_return_void(local);
 }
 
+static inline void drv_sta_set_airtime_weight(struct ieee80211_local *local,
+					      struct ieee80211_sub_if_data *sdata,
+					      struct ieee80211_sta *sta,
+					      u16 weight)
+{
+	sdata = get_bss_sdata(sdata);
+
+	might_sleep();
+	lockdep_assert_wiphy(local->hw.wiphy);
+	if (!check_sdata_in_driver(sdata))
+		return;
+
+	trace_drv_sta_set_airtime_weight(local, sdata, sta, weight);
+	if (local->ops->sta_set_airtime_weight)
+		local->ops->sta_set_airtime_weight(&local->hw, &sdata->vif, sta,
+						   weight);
+	trace_drv_return_void(local);
+}
+
 static inline void drv_add_twt_setup(struct ieee80211_local *local,
 				     struct ieee80211_sub_if_data *sdata,
 				     struct ieee80211_sta *sta,
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index e81cd155197b9..2ce3ef905f15c 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -872,8 +872,13 @@ static int sta_info_insert_drv_state(struct ieee80211_local *local,
 		 * Drivers using legacy sta_add/sta_remove callbacks only
 		 * get uploaded set to true after sta_add is called.
 		 */
-		if (!local->ops->sta_add)
+		if (!local->ops->sta_add) {
 			sta->uploaded = true;
+			if (sta->airtime_weight != IEEE80211_DEFAULT_AIRTIME_WEIGHT)
+				drv_sta_set_airtime_weight(local, sdata,
+							   &sta->sta,
+							   sta->airtime_weight);
+		}
 		return 0;
 	}
 
diff --git a/net/mac80211/trace.h b/net/mac80211/trace.h
index 562a4964afa3a..3ae7e78de715c 100644
--- a/net/mac80211/trace.h
+++ b/net/mac80211/trace.h
@@ -2462,6 +2462,33 @@ DEFINE_EVENT(sta_flag_evt, drv_sta_set_decap_offload,
 	TP_ARGS(local, sdata, sta, enabled)
 );
 
+TRACE_EVENT(drv_sta_set_airtime_weight,
+	TP_PROTO(struct ieee80211_local *local,
+		 struct ieee80211_sub_if_data *sdata,
+		 struct ieee80211_sta *sta, u16 weight),
+
+	TP_ARGS(local, sdata, sta, weight),
+
+	TP_STRUCT__entry(
+		LOCAL_ENTRY
+		VIF_ENTRY
+		STA_ENTRY
+		__field(u16, weight)
+	),
+
+	TP_fast_assign(
+		LOCAL_ASSIGN;
+		VIF_ASSIGN;
+		STA_ASSIGN;
+		__entry->weight = weight;
+	),
+
+	TP_printk(
+		LOCAL_PR_FMT  VIF_PR_FMT  STA_PR_FMT " weight:%u",
+		LOCAL_PR_ARG, VIF_PR_ARG, STA_PR_ARG, __entry->weight
+	)
+);
+
 TRACE_EVENT(drv_add_twt_setup,
 	TP_PROTO(struct ieee80211_local *local,
 		 struct ieee80211_sta *sta,

55/3 2026/10/03 16:10 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 13161
							output: 26
							thoughts: 1864
						

Thoughts:
**Analyzing the ath11k and mac80211 Patch for Potential Issues**

Okay, so this patch appears to be focused on adding Beacon protection and Airtime Fairness (ATF) features to the ath11k driver and its interaction with mac80211. My initial assessment suggests several code modifications are happening across core header files, debugfs, the mac layer, and the WMI interface. Specifically, I'm noting the addition of `beacon_prot` and `airtime_weight` fields within the `ath11k_vif` and `ath11k_sta` structures, respectively. Debugfs is also being extended to show service maps, which is useful for debugging. The mac layer changes are pretty extensive, handling beacon protection, cipher suites, and adding the ATF framework with functions for iteration, updates, and setting airtime weights. The WMI layer seems to be coordinating these features at a lower level with ATF structures and new commands, also increasing the key index limit. Finally, mac80211 is seeing the addition of the airtime weight setting callback which is interesting.

My primary concern, given my expertise, is potential vulnerabilities related to uninitialized memory access, particularly in this new ATF functionality. I'm leveraging KMSAN to detect read of uninitialized memory. So, I need to thoroughly audit the changes for any instances where uninitialized variables might be used in a way that could cause problems, like in branching conditions, copying data to userspace, or sending data over netlink, and potentially leaking info.

Specifically, I'm focusing on `ath11k_mac_atf_update` and `ath11k_mac_atf_iter` because they deal with airtime weights and iterating over station data. My initial thoughts are that, even though some fields are initialized in the `it` structure, they are allocated with `kcalloc` and therefore are initialized to zero. After reviewing the code, it looks like `it.peers` and `it.weights` are indeed allocated with zeroed memory. However, I'm now realizing a potential *divide-by-zero* issue. If the total airtime weight (`it.total`) is zero and we have valid stations, the `div_u64` call becomes problematic and leads to a crash, but not an uninitialized memory read!

Given that's unlikely to trigger a KMSAN, I need to re-assess the changes to see if they are uninitialized values being read, instead of arithmetic exceptions. My next steps involve a comprehensive review of memory allocation with `ath11k_wmi_alloc_skb`. I'll employ `grepper` to explore this function's uses, to see if there are other potential KMSAN/KASAN issues.



56/3 2026/10/03 16:10 tool grepper
0m Args:
{
  "Expression": "ath11k_wmi_alloc_skb"
}

Results:
{
  "Output": "\nFull output is too long, showing 200 out of 574 lines.\nUse more precise expression if possible.\n\ndrivers/net/wireless/ath/ath11k/testmode.c=300=static int ath11k_tm_cmd_wmi(struct ath11k *ar, struct nlattr *tb[],\n--\ndrivers/net/wireless/ath/ath11k/testmode.c-366-\ndrivers/net/wireless/ath/ath11k/testmode.c:367:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, buf_len);\ndrivers/net/wireless/ath/ath11k/testmode.c-368-\tif (!skb) {\n--\ndrivers/net/wireless/ath/ath11k/testmode.c=390=static int ath11k_tm_cmd_wmi_ftm(struct ath11k *ar, struct nlattr *tb[])\n--\ndrivers/net/wireless/ath/ath11k/testmode.c-435-\ndrivers/net/wireless/ath/ath11k/testmode.c:436:\t\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, (chunk_len +\ndrivers/net/wireless/ath/ath11k/testmode.c-437-\t\t\t\t\t   sizeof(struct wmi_ftm_cmd)));\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=610=static int ath11k_service_ready_event(struct ath11k_base *ab, struct sk_buff *skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-627-\ndrivers/net/wireless/ath/ath11k/wmi.c:628:struct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_ab, u32 len)\ndrivers/net/wireless/ath/ath11k/wmi.c-629-{\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=662=int ath11k_wmi_mgmt_send(struct ath11k *ar, u32 vdev_id, u32 buf_id,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-680-\ndrivers/net/wireless/ath/ath11k/wmi.c:681:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, len);\ndrivers/net/wireless/ath/ath11k/wmi.c-682-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=726=int ath11k_wmi_vdev_create(struct ath11k *ar, u8 *macaddr,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-743-\ndrivers/net/wireless/ath/ath11k/wmi.c:744:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, len);\ndrivers/net/wireless/ath/ath11k/wmi.c-745-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=806=int ath11k_wmi_vdev_delete(struct ath11k *ar, u8 vdev_id)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-812-\ndrivers/net/wireless/ath/ath11k/wmi.c:813:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-814-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=833=int ath11k_wmi_vdev_stop(struct ath11k *ar, u8 vdev_id)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-839-\ndrivers/net/wireless/ath/ath11k/wmi.c:840:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-841-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=861=int ath11k_wmi_vdev_down(struct ath11k *ar, u8 vdev_id)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-867-\ndrivers/net/wireless/ath/ath11k/wmi.c:868:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-869-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=943=int ath11k_wmi_vdev_start(struct ath11k *ar, struct wmi_vdev_start_req_arg *arg,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-958-\ndrivers/net/wireless/ath/ath11k/wmi.c:959:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, len);\ndrivers/net/wireless/ath/ath11k/wmi.c-960-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1034=int ath11k_wmi_vdev_up(struct ath11k *ar, u32 vdev_id, u32 aid, const u8 *bssid,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1045-\ndrivers/net/wireless/ath/ath11k/wmi.c:1046:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1047-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1088=int ath11k_wmi_send_peer_create_cmd(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1095-\ndrivers/net/wireless/ath/ath11k/wmi.c:1096:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1097-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1121=int ath11k_wmi_send_peer_delete_cmd(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1128-\ndrivers/net/wireless/ath/ath11k/wmi.c:1129:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1130-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1153=int ath11k_wmi_send_pdev_set_regdomain(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1160-\ndrivers/net/wireless/ath/ath11k/wmi.c:1161:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1162-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1193=int ath11k_wmi_set_peer_param(struct ath11k *ar, const u8 *peer_addr,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1200-\ndrivers/net/wireless/ath/ath11k/wmi.c:1201:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1202-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1226=int ath11k_wmi_send_peer_flush_tids_cmd(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1234-\ndrivers/net/wireless/ath/ath11k/wmi.c:1235:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1236-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1261=int ath11k_wmi_peer_rx_reorder_queue_setup(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1270-\ndrivers/net/wireless/ath/ath11k/wmi.c:1271:\tskb = ath11k_wmi_alloc_skb(ar-\u003ewmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1272-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1305=ath11k_wmi_rx_reord_queue_remove(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1312-\ndrivers/net/wireless/ath/ath11k/wmi.c:1313:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1314-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1341=int ath11k_wmi_pdev_set_param(struct ath11k *ar, u32 param_id,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1348-\ndrivers/net/wireless/ath/ath11k/wmi.c:1349:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1350-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1373=int ath11k_wmi_pdev_set_ps_mode(struct ath11k *ar, int vdev_id,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1380-\ndrivers/net/wireless/ath/ath11k/wmi.c:1381:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1382-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1404=int ath11k_wmi_pdev_suspend(struct ath11k *ar, u32 suspend_opt,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1411-\ndrivers/net/wireless/ath/ath11k/wmi.c:1412:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1413-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1436=int ath11k_wmi_pdev_resume(struct ath11k *ar, u32 pdev_id)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1442-\ndrivers/net/wireless/ath/ath11k/wmi.c:1443:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1444-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1469=int ath11k_wmi_pdev_bss_chan_info_request(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1476-\ndrivers/net/wireless/ath/ath11k/wmi.c:1477:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1478-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1503=int ath11k_wmi_send_set_ap_ps_param_cmd(struct ath11k *ar, u8 *peer_addr,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1510-\ndrivers/net/wireless/ath/ath11k/wmi.c:1511:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1512-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1538=int ath11k_wmi_set_sta_ps_param(struct ath11k *ar, u32 vdev_id,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1545-\ndrivers/net/wireless/ath/ath11k/wmi.c:1546:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1547-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1572=int ath11k_wmi_force_fw_hang_cmd(struct ath11k *ar, u32 type, u32 delay_time_ms)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1580-\ndrivers/net/wireless/ath/ath11k/wmi.c:1581:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, len);\ndrivers/net/wireless/ath/ath11k/wmi.c-1582-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1604=int ath11k_wmi_vdev_set_param_cmd(struct ath11k *ar, u32 vdev_id,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1611-\ndrivers/net/wireless/ath/ath11k/wmi.c:1612:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1613-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1638=int ath11k_wmi_send_stats_request_cmd(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1645-\ndrivers/net/wireless/ath/ath11k/wmi.c:1646:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1647-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1671=int ath11k_wmi_send_pdev_temperature_cmd(struct ath11k *ar)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1677-\ndrivers/net/wireless/ath/ath11k/wmi.c:1678:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1679-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1699=int ath11k_wmi_send_bcn_offload_control_cmd(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1706-\ndrivers/net/wireless/ath/ath11k/wmi.c:1707:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, sizeof(*cmd));\ndrivers/net/wireless/ath/ath11k/wmi.c-1708-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1733=int ath11k_wmi_p2p_go_bcn_ie(struct ath11k *ar, u32 vdev_id,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1747-\ndrivers/net/wireless/ath/ath11k/wmi.c:1748:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, len);\ndrivers/net/wireless/ath/ath11k/wmi.c-1749-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1772=int ath11k_wmi_bcn_tmpl(struct ath11k *ar, u32 vdev_id,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1795-\ndrivers/net/wireless/ath/ath11k/wmi.c:1796:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, len);\ndrivers/net/wireless/ath/ath11k/wmi.c-1797-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1845=int ath11k_wmi_vdev_install_key(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-1856-\ndrivers/net/wireless/ath/ath11k/wmi.c:1857:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, len);\ndrivers/net/wireless/ath/ath11k/wmi.c-1858-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=1981=int ath11k_wmi_send_peer_assoc_cmd(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-2005-\ndrivers/net/wireless/ath/ath11k/wmi.c:2006:\tskb = ath11k_wmi_alloc_skb(wmi-\u003ewmi_ab, len);\ndrivers/net/wireless/ath/ath11k/wmi.c-2007-\tif (!skb)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=2266=int ath11k_wmi_send_scan_start_cmd(struct ath11k *ar,\n--\n\n"
}

57/3 2026/10/03 16:10 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 21147
							output: 45
							thoughts: 39
						

Thoughts:
Here's a summary of my thought process:

**Diving into the `ath11k_wmi_alloc_skb` Function**

Okay, let's get down to brass tacks. I need to understand how the allocation of Socket Buffers (SKBs) is handled within the ath11k wireless driver, specifically within the WMI (Wireless Management Interface) context. My first step is to zero in on the `ath11k_wmi_alloc_skb` function definition. I know it resides within the `drivers/net/wireless/ath/ath11k/wmi.c` file. Time to crack open the source code and see how the memory is being requested and what considerations are in place, because, let's face it, efficient SKB allocation is *critical* for good throughput and low latency in any wireless system.



58/3 2026/10/03 16:10 tool read-file
0m Args:
{
  "File": "drivers/net/wireless/ath/ath11k/wmi.c",
  "FirstLine": 625,
  "LineCount": 25
}

Results:
{
  "Contents": " 625:\t\treturn 0;\n 626:\t}\n 627:\t\n 628:\tstruct sk_buff *ath11k_wmi_alloc_skb(struct ath11k_wmi_base *wmi_ab, u32 len)\n 629:\t{\n 630:\t\tstruct sk_buff *skb;\n 631:\t\tstruct ath11k_base *ab = wmi_ab-\u003eab;\n 632:\t\tu32 round_len = roundup(len, 4);\n 633:\t\n 634:\t\tskb = ath11k_htc_alloc_skb(ab, WMI_SKB_HEADROOM + round_len);\n 635:\t\tif (!skb)\n 636:\t\t\treturn NULL;\n 637:\t\n 638:\t\tskb_reserve(skb, WMI_SKB_HEADROOM);\n 639:\t\tif (!IS_ALIGNED((unsigned long)skb-\u003edata, 4))\n 640:\t\t\tath11k_warn(ab, \"unaligned WMI skb data\\n\");\n 641:\t\n 642:\t\tskb_put(skb, round_len);\n 643:\t\tmemset(skb-\u003edata, 0, round_len);\n 644:\t\n 645:\t\treturn skb;\n 646:\t}\n 647:\t\n 648:\tstatic u32 ath11k_wmi_mgmt_get_freq(struct ath11k *ar,\n 649:\t\t\t\t\t    struct ieee80211_tx_info *info)\n"
}

59/3 2026/10/03 16:10 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 21856
							output: 36
							thoughts: 324
						

Thoughts:
**Analyzing Potential Uninitialized Data in the ath11k Driver**

Okay, so I'm looking at this `ath11k` driver code, specifically at how command buffers are handled. My initial observation is that `ath11k_wmi_alloc_skb` uses `memset` to zero out the allocated memory (`skb->data`). This is good; it means any `skb` allocated through this function, and subsequently used as a command buffer, should start in a known, initialized state (all zeros). This observation holds true for both `ath11k_wmi_send_atf_group` and `ath11k_wmi_send_peer_atf_request`, as they both rely on `ath11k_wmi_alloc_skb` for allocation. This implies that any command buffers created by either of these two functions should also be safely initialized.

However, I've got a nagging feeling, and that's usually a good sign to dig deeper. I'm now examining `ath11k_wmi_services_show`, and specifically the use of `ab->wmi_ab.svc_map`. The function iterates through the `svc_map` using `for_each_set_bit`. Now, the key question is: does this read uninitialized data? I need to know where `ab->wmi_ab.svc_map` is initialized to ensure that the bits being iterated over have a defined state. This is critical for preventing potential security vulnerabilities or unexpected behavior due to uninitialized memory reads. I'm going to have to find the initialization point for `svc_map` and verify its behavior to ensure that the code is correctly handling the map's contents.



60/3 2026/10/03 16:10 tool grepper
0m Args:
{
  "Expression": "svc_map",
  "PathPrefix": "drivers/net/wireless/ath/ath11k/"
}

Results:
{
  "Output": "\nFull output is too long, showing 200 out of 279 lines.\nUse more precise expression if possible.\n\ndrivers/net/wireless/ath/ath11k/cfr.c=923=void ath11k_cfr_deinit(struct ath11k_base *ab)\n--\ndrivers/net/wireless/ath/ath11k/cfr.c-928-\ndrivers/net/wireless/ath/ath11k/cfr.c:929:\tif (!test_bit(WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT, ab-\u003ewmi_ab.svc_map) ||\ndrivers/net/wireless/ath/ath11k/cfr.c-930-\t    !ab-\u003ehw_params.cfr_support)\n--\ndrivers/net/wireless/ath/ath11k/cfr.c=951=int ath11k_cfr_init(struct ath11k_base *ab)\n--\ndrivers/net/wireless/ath/ath11k/cfr.c-958-\ndrivers/net/wireless/ath/ath11k/cfr.c:959:\tif (!test_bit(WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT, ab-\u003ewmi_ab.svc_map) ||\ndrivers/net/wireless/ath/ath11k/cfr.c-960-\t    !ab-\u003ehw_params.cfr_support)\n--\ndrivers/net/wireless/ath/ath11k/debugfs.c=854=static int ath11k_wmi_services_show(struct seq_file *m, void *v)\n--\ndrivers/net/wireless/ath/ath11k/debugfs.c-858-\ndrivers/net/wireless/ath/ath11k/debugfs.c:859:\tfor_each_set_bit(i, ab-\u003ewmi_ab.svc_map, WMI_MAX_EXT2_SERVICE)\ndrivers/net/wireless/ath/ath11k/debugfs.c-860-\t\tseq_printf(m, \"%u\\n\", i);\n--\ndrivers/net/wireless/ath/ath11k/debugfs.c=1484=int ath11k_debugfs_register(struct ath11k *ar)\n--\ndrivers/net/wireless/ath/ath11k/debugfs.c-1533-\tif (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,\ndrivers/net/wireless/ath/ath11k/debugfs.c:1534:\t\t     ar-\u003eab-\u003ewmi_ab.svc_map)) {\ndrivers/net/wireless/ath/ath11k/debugfs.c-1535-\t\tdebugfs_create_file(\"ps_timekeeper_enable\", 0600,\n--\ndrivers/net/wireless/ath/ath11k/debugfs.c=1789=void ath11k_debugfs_op_vif_add(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/ath/ath11k/debugfs.c-1797-\t    !(arvif-\u003evif-\u003etype == NL80211_IFTYPE_STATION \u0026\u0026\ndrivers/net/wireless/ath/ath11k/debugfs.c:1798:\t      test_bit(WMI_TLV_SERVICE_STA_TWT, ab-\u003ewmi_ab.svc_map)))\ndrivers/net/wireless/ath/ath11k/debugfs.c-1799-\t\treturn;\n--\ndrivers/net/wireless/ath/ath11k/debugfs_sta.c=985=void ath11k_debugfs_sta_op_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif,\n--\ndrivers/net/wireless/ath/ath11k/debugfs_sta.c-1008-\tif (test_bit(WMI_TLV_SERVICE_PER_PEER_HTT_STATS_RESET,\ndrivers/net/wireless/ath/ath11k/debugfs_sta.c:1009:\t\t     ar-\u003eab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/debugfs_sta.c-1010-\t\tdebugfs_create_file(\"htt_peer_stats_reset\", 0600, dir, sta,\n--\ndrivers/net/wireless/ath/ath11k/debugfs_sta.c-1014-\tif (test_bit(WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT,\ndrivers/net/wireless/ath/ath11k/debugfs_sta.c:1015:\t\t     ar-\u003eab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/debugfs_sta.c-1016-\t\tdebugfs_create_file(\"cfr_capture\", 0600, dir, sta,\n--\ndrivers/net/wireless/ath/ath11k/debugfs_sta.c-1023-\tif (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,\ndrivers/net/wireless/ath/ath11k/debugfs_sta.c:1024:\t\t     ar-\u003eab-\u003ewmi_ab.svc_map)) {\ndrivers/net/wireless/ath/ath11k/debugfs_sta.c-1025-\t\tdebugfs_create_file(\"current_ps_duration\", 0440, dir, sta,\n--\ndrivers/net/wireless/ath/ath11k/dp_tx.c=316=ath11k_dp_tx_htt_tx_complete_buf(struct ath11k_base *ab,\n--\ndrivers/net/wireless/ath/ath11k/dp_tx.c-359-\t\t\tif (!test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,\ndrivers/net/wireless/ath/ath11k/dp_tx.c:360:\t\t\t\t      ab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/dp_tx.c-361-\t\t\t\tinfo-\u003estatus.ack_signal += ATH11K_DEFAULT_NOISE_FLOOR;\n--\ndrivers/net/wireless/ath/ath11k/dp_tx.c=551=static void ath11k_dp_tx_complete_msdu(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/dp_tx.c-594-\t\tif (!test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,\ndrivers/net/wireless/ath/ath11k/dp_tx.c:595:\t\t\t      ab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/dp_tx.c-596-\t\t\tinfo-\u003estatus.ack_signal += ATH11K_DEFAULT_NOISE_FLOOR;\n--\ndrivers/net/wireless/ath/ath11k/hal_rx.c=875=ath11k_hal_rx_parse_mon_status_tlv(struct ath11k_base *ab,\n--\ndrivers/net/wireless/ath/ath11k/hal_rx.c-1445-\t\tbool db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,\ndrivers/net/wireless/ath/ath11k/hal_rx.c:1446:\t\t\t\t       ab-\u003ewmi_ab.svc_map);\ndrivers/net/wireless/ath/ath11k/hal_rx.c-1447-\t\tstruct hal_rx_phyrx_rssi_legacy_info *rssi =\n--\ndrivers/net/wireless/ath/ath11k/mac.c=3405=static int ath11k_mac_config_obss_pd(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-3450-\tif (test_bit(WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT,\ndrivers/net/wireless/ath/ath11k/mac.c:3451:\t\t     ar-\u003eab-\u003ewmi_ab.svc_map)) {\ndrivers/net/wireless/ath/ath11k/mac.c-3452-\t\tparam_val |= ATH11K_OBSS_PD_THRESHOLD_IN_DBM;\n--\ndrivers/net/wireless/ath/ath11k/mac.c-3492-\tif (!test_bit(WMI_TLV_SERVICE_SRG_SRP_SPATIAL_REUSE_SUPPORT,\ndrivers/net/wireless/ath/ath11k/mac.c:3493:\t\t      ar-\u003eab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/mac.c-3494-\t\treturn 0;\n--\ndrivers/net/wireless/ath/ath11k/mac.c=3557=static bool ath11k_mac_supports_station_tpc(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-3561-\treturn ath11k_wmi_supports_6ghz_cc_ext(ar) \u0026\u0026\ndrivers/net/wireless/ath/ath11k/mac.c:3562:\t\ttest_bit(WMI_TLV_SERVICE_EXT_TPC_REG_SUPPORT, ar-\u003eab-\u003ewmi_ab.svc_map) \u0026\u0026\ndrivers/net/wireless/ath/ath11k/mac.c-3563-\t\tarvif-\u003evdev_type == WMI_VDEV_TYPE_STA \u0026\u0026\n--\ndrivers/net/wireless/ath/ath11k/mac.c=3569=static void ath11k_mac_op_bss_info_changed(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-3890-\t    arvif-\u003eftm_responder != info-\u003eftm_responder \u0026\u0026\ndrivers/net/wireless/ath/ath11k/mac.c:3891:\t    test_bit(WMI_TLV_SERVICE_RTT, ar-\u003eab-\u003ewmi_ab.svc_map) \u0026\u0026\ndrivers/net/wireless/ath/ath11k/mac.c-3892-\t    (vif-\u003etype == NL80211_IFTYPE_AP ||\n--\ndrivers/net/wireless/ath/ath11k/mac.c=4051=static int ath11k_start_scan(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-4065-\ndrivers/net/wireless/ath/ath11k/mac.c:4066:\tif (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar-\u003eab-\u003ewmi_ab.svc_map)) {\ndrivers/net/wireless/ath/ath11k/mac.c-4067-\t\ttimeout = 5 * HZ;\n--\ndrivers/net/wireless/ath/ath11k/mac.c=4240=static int ath11k_mac_op_hw_scan(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-4260-\t    test_bit(WMI_TLV_SERVICE_SUPPORT_11D_FOR_HOST_SCAN,\ndrivers/net/wireless/ath/ath11k/mac.c:4261:\t\t     ar-\u003eab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/mac.c-4262-\t\tath11k_mac_11d_scan_start(ar, arvif-\u003evdev_id);\n--\ndrivers/net/wireless/ath/ath11k/mac.c-4323-\t\tif (test_bit(WMI_TLV_SERVICE_SCAN_CONFIG_PER_CHANNEL,\ndrivers/net/wireless/ath/ath11k/mac.c:4324:\t\t\t     ar-\u003eab-\u003ewmi_ab.svc_map)) {\ndrivers/net/wireless/ath/ath11k/mac.c-4325-\t\t\targ-\u003echan_list[i] =\n--\ndrivers/net/wireless/ath/ath11k/mac.c=6672=static int ath11k_mac_op_start(struct ieee80211_hw *hw)\n--\ndrivers/net/wireless/ath/ath11k/mac.c-6718-\ndrivers/net/wireless/ath/ath11k/mac.c:6719:\tif (test_bit(WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT, ar-\u003ewmi-\u003ewmi_ab-\u003esvc_map)) {\ndrivers/net/wireless/ath/ath11k/mac.c-6720-\t\tret = ath11k_wmi_scan_prob_req_oui(ar, ar-\u003emac_addr);\n--\ndrivers/net/wireless/ath/ath11k/mac.c-6734-\ndrivers/net/wireless/ath/ath11k/mac.c:6735:\tif (test_bit(WMI_TLV_SERVICE_ATF, ab-\u003ewmi_ab.svc_map)) {\ndrivers/net/wireless/ath/ath11k/mac.c-6736-\t\tret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_ATF_DYNAMIC_ENABLE,\n--\ndrivers/net/wireless/ath/ath11k/mac.c=6899=static int ath11k_mac_setup_vdev_create_params(struct ath11k_vif *arvif,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-6913-\tif (!test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT,\ndrivers/net/wireless/ath/ath11k/mac.c:6914:\t\t      ar-\u003eab-\u003ewmi_ab.svc_map)) {\ndrivers/net/wireless/ath/ath11k/mac.c-6915-\t\tret = ath11k_mac_setup_vdev_params_mbssid(arvif,\n--\ndrivers/net/wireless/ath/ath11k/mac.c=7004=void ath11k_mac_11d_scan_start(struct ath11k *ar, u32 vdev_id)\n--\ndrivers/net/wireless/ath/ath11k/mac.c-7019-\ndrivers/net/wireless/ath/ath11k/mac.c:7020:\tif (!test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar-\u003eab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/mac.c-7021-\t\tgoto fin;\n--\ndrivers/net/wireless/ath/ath11k/mac.c=7051=void ath11k_mac_11d_scan_stop(struct ath11k *ar)\n--\ndrivers/net/wireless/ath/ath11k/mac.c-7055-\ndrivers/net/wireless/ath/ath11k/mac.c:7056:\tif (!test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ar-\u003eab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/mac.c-7057-\t\treturn;\n--\ndrivers/net/wireless/ath/ath11k/mac.c=7148=static int ath11k_mac_op_add_interface(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-7337-\ndrivers/net/wireless/ath/ath11k/mac.c:7338:\t\tif (test_bit(WMI_TLV_SERVICE_11D_OFFLOAD, ab-\u003ewmi_ab.svc_map)) {\ndrivers/net/wireless/ath/ath11k/mac.c-7339-\t\t\treinit_completion(\u0026ar-\u003ecompleted_11d_scan);\n--\ndrivers/net/wireless/ath/ath11k/mac.c=7628=ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-7663-\tif (test_bit(WMI_TLV_SERVICE_MBSS_PARAM_IN_VDEV_START_SUPPORT,\ndrivers/net/wireless/ath/ath11k/mac.c:7664:\t\t     ar-\u003eab-\u003ewmi_ab.svc_map)) {\ndrivers/net/wireless/ath/ath11k/mac.c-7665-\t\tret = ath11k_mac_setup_vdev_params_mbssid(arvif,\n--\ndrivers/net/wireless/ath/ath11k/mac.c=9366=ath11k_mac_update_bss_chan_survey(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-9373-\ndrivers/net/wireless/ath/ath11k/mac.c:9374:\tif (!test_bit(WMI_TLV_SERVICE_BSS_CHANNEL_INFO_64, ar-\u003eab-\u003ewmi_ab.svc_map) ||\ndrivers/net/wireless/ath/ath11k/mac.c-9375-\t    ar-\u003erx_channel != channel)\n--\ndrivers/net/wireless/ath/ath11k/mac.c=9477=static void ath11k_mac_op_sta_statistics(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-9485-\tbool db2dbm = test_bit(WMI_TLV_SERVICE_HW_DB2DBM_CONVERSION_SUPPORT,\ndrivers/net/wireless/ath/ath11k/mac.c:9486:\t\t\t       ar-\u003eab-\u003ewmi_ab.svc_map);\ndrivers/net/wireless/ath/ath11k/mac.c-9487-\n--\ndrivers/net/wireless/ath/ath11k/mac.c=9681=static int ath11k_mac_op_set_bios_sar_specs(struct ieee80211_hw *hw,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-9695-\ndrivers/net/wireless/ath/ath11k/mac.c:9696:\tif (!test_bit(WMI_TLV_SERVICE_BIOS_SAR_SUPPORT, ar-\u003eab-\u003ewmi_ab.svc_map) ||\ndrivers/net/wireless/ath/ath11k/mac.c-9697-\t    !ar-\u003eab-\u003ehw_params.bios_sar_capa) {\n--\ndrivers/net/wireless/ath/ath11k/mac.c=10027=static int ath11k_mac_atf_update(struct ath11k *ar)\n--\ndrivers/net/wireless/ath/ath11k/mac.c-10034-\ndrivers/net/wireless/ath/ath11k/mac.c:10035:\tif (!test_bit(WMI_TLV_SERVICE_ATF, ar-\u003eab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/mac.c-10036-\t\treturn 0;\n--\ndrivers/net/wireless/ath/ath11k/mac.c=10602=static int __ath11k_mac_register(struct ath11k *ar)\n--\ndrivers/net/wireless/ath/ath11k/mac.c-10717-\ndrivers/net/wireless/ath/ath11k/mac.c:10718:\tif (test_bit(WMI_TLV_SERVICE_SPOOF_MAC_SUPPORT, ar-\u003ewmi-\u003ewmi_ab-\u003esvc_map)) {\ndrivers/net/wireless/ath/ath11k/mac.c-10719-\t\tar-\u003ehw-\u003ewiphy-\u003efeatures |=\n--\ndrivers/net/wireless/ath/ath11k/mac.c-10722-\ndrivers/net/wireless/ath/ath11k/mac.c:10723:\tif (test_bit(WMI_TLV_SERVICE_NLO, ar-\u003ewmi-\u003ewmi_ab-\u003esvc_map)) {\ndrivers/net/wireless/ath/ath11k/mac.c-10724-\t\tar-\u003ehw-\u003ewiphy-\u003emax_sched_scan_ssids = WMI_PNO_MAX_SUPP_NETWORKS;\n--\ndrivers/net/wireless/ath/ath11k/mac.c-10741-\tif (test_bit(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,\ndrivers/net/wireless/ath/ath11k/mac.c:10742:\t\t     ar-\u003eab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/mac.c-10743-\t\twiphy_ext_feature_set(ar-\u003ehw-\u003ewiphy,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-10756-\tif (test_bit(WMI_TLV_SERVICE_BSS_COLOR_OFFLOAD,\ndrivers/net/wireless/ath/ath11k/mac.c:10757:\t\t     ar-\u003eab-\u003ewmi_ab.svc_map)) {\ndrivers/net/wireless/ath/ath11k/mac.c-10758-\t\twiphy_ext_feature_set(ar-\u003ehw-\u003ewiphy,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-10779-\ndrivers/net/wireless/ath/ath11k/mac.c:10780:\tif (test_bit(WMI_TLV_SERVICE_RTT, ar-\u003eab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/mac.c-10781-\t\twiphy_ext_feature_set(ar-\u003ehw-\u003ewiphy,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-10783-\ndrivers/net/wireless/ath/ath11k/mac.c:10784:\tif (test_bit(WMI_TLV_SERVICE_BEACON_PROTECTION_SUPPORT, ar-\u003eab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/mac.c-10785-\t\twiphy_ext_feature_set(ar-\u003ehw-\u003ewiphy,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-10787-\ndrivers/net/wireless/ath/ath11k/mac.c:10788:\tif (test_bit(WMI_TLV_SERVICE_ATF, ar-\u003eab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/mac.c-10789-\t\twiphy_ext_feature_set(ar-\u003ehw-\u003ewiphy,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-10802-\ndrivers/net/wireless/ath/ath11k/mac.c:10803:\tif (test_bit(WMI_TLV_SERVICE_BIOS_SAR_SUPPORT, ar-\u003eab-\u003ewmi_ab.svc_map) \u0026\u0026\ndrivers/net/wireless/ath/ath11k/mac.c-10804-\t    ab-\u003ehw_params.bios_sar_capa)\n--\ndrivers/net/wireless/ath/ath11k/mac.c=11017=int ath11k_mac_vif_set_keepalive(struct ath11k_vif *arvif,\n--\n\n"
}

61/3 2026/10/03 16:10 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 28693
							output: 40
							thoughts: 30
						

Thoughts:
Okay, here's my thought process laid out, as if I were thinking it:

**Tracing the Initialization of `svc_map`**

Alright, I need to understand where this `svc_map` variable gets initialized. It's a key structure, so understanding its initial state is crucial. My first instinct is to dig into the `wmi.c` file. Given the context, it's a pretty good bet that the definition and initialization are in there somewhere. Let's fire up a `grep` and search for `svc_map` within that file. That should give me a concise list of locations where it's defined, initialized, or modified. Then I can examine the relevant parts of the code more closely.



62/3 2026/10/03 16:11 tool grepper
0m Args:
{
  "Expression": "svc_map",
  "PathPrefix": "drivers/net/wireless/ath/ath11k/wmi.c"
}

Results:
{
  "Output": "drivers/net/wireless/ath/ath11k/wmi.c=563=static void ath11k_wmi_service_bitmap_copy(struct ath11k_pdev_wmi *wmi,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-570-\t\t\tif (wmi_svc_bm[i] \u0026 BIT(j % WMI_SERVICE_BITS_IN_SIZE32))\ndrivers/net/wireless/ath/ath11k/wmi.c:571:\t\t\t\tset_bit(j, wmi-\u003ewmi_ab-\u003esvc_map);\ndrivers/net/wireless/ath/ath11k/wmi.c-572-\t\t} while (++j % WMI_SERVICE_BITS_IN_SIZE32);\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=2148=void ath11k_wmi_start_scan_init(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-2176-\tif (test_bit(WMI_TLV_SERVICE_PASSIVE_SCAN_START_TIME_ENHANCE,\ndrivers/net/wireless/ath/ath11k/wmi.c:2177:\t\t     ar-\u003eab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/wmi.c-2178-\t\targ-\u003escan_ctrl_flags_ext |=\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=4565=int ath11k_wmi_cmd_init(struct ath11k_base *ab)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-4576-\tif (test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT,\ndrivers/net/wireless/ath/ath11k/wmi.c:4577:\t\t     ab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/wmi.c-4578-\t\tconfig.is_reg_cc_ext_event_supported = 1;\ndrivers/net/wireless/ath/ath11k/wmi.c-4579-\ndrivers/net/wireless/ath/ath11k/wmi.c:4580:\tif (test_bit(WMI_TLV_SERVICE_ATF, ab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/wmi.c-4581-\t\tconfig.flag1 |= WMI_RSRC_CFG_FLAG1_ATF_CONFIG_ENABLE;\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=5214=static int ath11k_service_ready_ext_event(struct ath11k_base *ab,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-5229-\ndrivers/net/wireless/ath/ath11k/wmi.c:5230:\tif (!test_bit(WMI_TLV_SERVICE_EXT2_MSG, ab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/wmi.c-5231-\t\tcomplete(\u0026ab-\u003ewmi_ab.service_ready);\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=6122=static int wmi_process_mgmt_tx_comp(struct ath11k *ar,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-6153-\t\tif (test_bit(WMI_TLV_SERVICE_TX_DATA_MGMT_ACK_RSSI,\ndrivers/net/wireless/ath/ath11k/wmi.c:6154:\t\t\t     ar-\u003eab-\u003ewmi_ab.svc_map))\ndrivers/net/wireless/ath/ath11k/wmi.c-6155-\t\t\tinfo-\u003estatus.ack_signal = tx_compl_param-\u003eack_rssi;\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=7600=static void ath11k_wmi_event_peer_sta_ps_state_chg(struct ath11k_base *ab,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-7672-\tif (test_bit(WMI_TLV_SERVICE_PEER_POWER_SAVE_DURATION_SUPPORT,\ndrivers/net/wireless/ath/ath11k/wmi.c:7673:\t\t     ar-\u003eab-\u003ewmi_ab.svc_map)) {\ndrivers/net/wireless/ath/ath11k/wmi.c-7674-\t\tif (!(ev-\u003eps_supported_bitmap \u0026 WMI_PEER_PS_VALID) ||\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=8254=static int  ath11k_wmi_tlv_services_parser(struct ath11k_base *ab,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-8270-\t\t\t\t    BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32))\ndrivers/net/wireless/ath/ath11k/wmi.c:8271:\t\t\t\t\tset_bit(j, ab-\u003ewmi_ab.svc_map);\ndrivers/net/wireless/ath/ath11k/wmi.c-8272-\t\t\t} while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32);\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-8289-\t\t\t\t    BIT(j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32))\ndrivers/net/wireless/ath/ath11k/wmi.c:8290:\t\t\t\t\tset_bit(j, ab-\u003ewmi_ab.svc_map);\ndrivers/net/wireless/ath/ath11k/wmi.c-8291-\t\t\t} while (++j % WMI_AVAIL_SERVICE_BITS_IN_SIZE32);\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=10275=bool ath11k_wmi_supports_6ghz_cc_ext(struct ath11k *ar)\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-10277-\treturn test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT,\ndrivers/net/wireless/ath/ath11k/wmi.c:10278:\t\t\tar-\u003eab-\u003ewmi_ab.svc_map) \u0026\u0026 ar-\u003esupports_6ghz;\ndrivers/net/wireless/ath/ath11k/wmi.c-10279-}\n"
}

63/3 2026/10/03 16:11 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 30650
							output: 42
							thoughts: 82
						

Thoughts:
Okay, here's my take on those thoughts, framed as an expert's internal monologue:

**Investigating the Initialization of `svc_map` in ath11k**

Alright, so `ab` gets allocated through `ath11k_core_alloc`, which is essentially a `kzalloc`. That means `svc_map` is initialized to all zeros right off the bat, as expected. But I need to confirm something. `WMI_MAX_EXT2_SERVICE` – that's the key here. It defines the size, specifically the number of bits, within that `svc_map` data structure. I need to refresh my memory on that constant's precise definition. Time to crack open `wmi.h` and make sure my understanding is spot-on. I'll double-check it's what I think it is, and then the picture should be clear.



64/3 2026/10/03 16:11 tool grepper
0m Args:
{
  "Expression": "WMI_MAX_EXT2_SERVICE",
  "PathPrefix": "drivers/net/wireless/ath/ath11k/"
}

Results:
{
  "Output": "drivers/net/wireless/ath/ath11k/debugfs.c=854=static int ath11k_wmi_services_show(struct seq_file *m, void *v)\n--\ndrivers/net/wireless/ath/ath11k/debugfs.c-858-\ndrivers/net/wireless/ath/ath11k/debugfs.c:859:\tfor_each_set_bit(i, ab-\u003ewmi_ab.svc_map, WMI_MAX_EXT2_SERVICE)\ndrivers/net/wireless/ath/ath11k/debugfs.c-860-\t\tseq_printf(m, \"%u\\n\", i);\n--\ndrivers/net/wireless/ath/ath11k/wmi.c=8254=static int  ath11k_wmi_tlv_services_parser(struct ath11k_base *ab,\n--\ndrivers/net/wireless/ath/ath11k/wmi.c-8284-\t\tfor (i = 0, j = WMI_MAX_EXT_SERVICE;\ndrivers/net/wireless/ath/ath11k/wmi.c:8285:\t\t\ti \u003c WMI_SERVICE_SEGMENT_BM_SIZE32 \u0026\u0026 j \u003c WMI_MAX_EXT2_SERVICE;\ndrivers/net/wireless/ath/ath11k/wmi.c-8286-\t\t\ti++) {\n--\ndrivers/net/wireless/ath/ath11k/wmi.h=1911=enum wmi_tlv_service {\n--\ndrivers/net/wireless/ath/ath11k/wmi.h-2146-\t/* The third 128 bits */\ndrivers/net/wireless/ath/ath11k/wmi.h:2147:\tWMI_MAX_EXT2_SERVICE = 384\ndrivers/net/wireless/ath/ath11k/wmi.h-2148-};\n--\ndrivers/net/wireless/ath/ath11k/wmi.h=5904=struct ath11k_wmi_base {\n--\ndrivers/net/wireless/ath/ath11k/wmi.h-5911-\tstruct completion unified_ready;\ndrivers/net/wireless/ath/ath11k/wmi.h:5912:\tDECLARE_BITMAP(svc_map, WMI_MAX_EXT2_SERVICE);\ndrivers/net/wireless/ath/ath11k/wmi.h-5913-\twait_queue_head_t tx_credits_wq;\n"
}

65/3 2026/10/03 16:11 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 31608
							output: 42
							thoughts: 693
						

Thoughts:
**Analyzing Beacon Protection in ath11k**

Okay, so I'm looking at this `ath11k_mac_bcn_prot_enabled` function, and the first thing I notice is how it iterates over the `svc_map` bitmap. The `for_each_set_bit` macro looks safe, operating within the defined bounds. Good.

Now, let's dive into the beacon protection parsing. The core of this seems to be the `ath11k_mac_ext_capa_bcn_prot` helper function. It checks for a specific bit within the extended capabilities element. Seems straightforward. The main function searches the beacon frame for the extended capability element.

However, I've got a nagging concern. Looking at the `ath11k_mac_bcn_prot_enabled` function, I'm starting to worry about potential buffer overruns or underflows. Specifically, the line that calculates `ies_len`: `skb_tail_pointer(bcn) - ies`. Is it possible that the `bcn->data` or `bcn->len` values could be smaller than `mgmt->u.beacon.variable`? If that happens, then `ies_len` could become negative which I *suspect* is the root cause of the bug report I'm looking at.

And if `ies_len` is negative, what does `cfg80211_find_elem` do with it? Does it interpret the negative length as a large positive number, or does it correctly handle the negative value? I need to check the function signature for `cfg80211_find_elem`. I need to figure out how it handles negative length arguments. Let's look at the source for that function.



66/3 2026/10/03 16:11 tool grepper
0m Args:
{
  "Expression": "cfg80211_find_elem",
  "PathPrefix": "include/net/cfg80211.h"
}

Results:
{
  "Output": "include/net/cfg80211.h=7835=unsigned int cfg80211_classify8021d(struct sk_buff *skb,\n--\ninclude/net/cfg80211.h-7838-/**\ninclude/net/cfg80211.h:7839: * cfg80211_find_elem_match - match information element and byte array in data\ninclude/net/cfg80211.h-7840- *\n--\ninclude/net/cfg80211.h=7860=const struct element *\ninclude/net/cfg80211.h:7861:cfg80211_find_elem_match(u8 eid, const u8 *ies, unsigned int len,\ninclude/net/cfg80211.h-7862-\t\t\t const u8 *match, unsigned int match_len,\n--\ninclude/net/cfg80211.h=7890=cfg80211_find_ie_match(u8 eid, const u8 *ies, unsigned int len,\n--\ninclude/net/cfg80211.h-7900-\ninclude/net/cfg80211.h:7901:\treturn (const void *)cfg80211_find_elem_match(eid, ies, len,\ninclude/net/cfg80211.h-7902-\t\t\t\t\t\t      match, match_len,\n--\ninclude/net/cfg80211.h-7907-/**\ninclude/net/cfg80211.h:7908: * cfg80211_find_elem - find information element in data\ninclude/net/cfg80211.h-7909- *\n--\ninclude/net/cfg80211.h=7922=static inline const struct element *\ninclude/net/cfg80211.h:7923:cfg80211_find_elem(u8 eid, const u8 *ies, int len)\ninclude/net/cfg80211.h-7924-{\ninclude/net/cfg80211.h:7925:\treturn cfg80211_find_elem_match(eid, ies, len, NULL, 0, 0);\ninclude/net/cfg80211.h-7926-}\n--\ninclude/net/cfg80211.h=7964=cfg80211_find_ext_elem(u8 ext_eid, const u8 *ies, int len)\ninclude/net/cfg80211.h-7965-{\ninclude/net/cfg80211.h:7966:\treturn cfg80211_find_elem_match(WLAN_EID_EXTENSION, ies, len,\ninclude/net/cfg80211.h-7967-\t\t\t\t\t\u0026ext_eid, 1, 0);\n"
}

67/3 2026/10/03 16:11 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 33482
							output: 36
							thoughts: 35
						

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

**Investigating `cfg80211_find_elem_match`**

Okay, so I need to track down how this matching is actually implemented. I'm going to start by going straight to the source. Let's see... the name `cfg80211_find_elem_match` suggests it's a core function within the cfg80211 wireless subsystem. My gut tells me it's likely defined within the `net/wireless/` directory, specifically in a utility file. I'll need to check `util.c` within that directory, or potentially in a header file if it's declared separately. Essentially, I need to understand the exact implementation details of this matching function in the wireless stack. Let's get to the code.



68/3 2026/10/03 16:11 tool grepper
0m Args:
{
  "Expression": "cfg80211_find_elem_match",
  "PathPrefix": "net/wireless/"
}

Results:
{
  "Output": "net/wireless/scan.c=269=cfg80211_gen_new_ie(const u8 *ie, size_t ielen,\n--\nnet/wireless/scan.c-310-\t\t/* Find first occurrence in subie */\nnet/wireless/scan.c:311:\t\tsub = cfg80211_find_elem_match(id, subie, subie_len,\nnet/wireless/scan.c-312-\t\t\t\t\t       \u0026ext_id, match_len, 0);\n--\nnet/wireless/scan.c-347-\t\t/* Already copied if an earlier element had the same type */\nnet/wireless/scan.c:348:\t\tif (cfg80211_find_elem_match(id, ie, (u8 *)parent - ie,\nnet/wireless/scan.c-349-\t\t\t\t\t     \u0026ext_id, match_len, 0))\n--\nnet/wireless/scan.c-359-\nnet/wireless/scan.c:360:\t\t\tsub = cfg80211_find_elem_match(id,\nnet/wireless/scan.c-361-\t\t\t\t\t\t       sub-\u003edata + sub-\u003edatalen,\n--\nnet/wireless/scan.c-395-\t\t/* Processed if one was included in the parent */\nnet/wireless/scan.c:396:\t\tif (cfg80211_find_elem_match(id, ie, ielen,\nnet/wireless/scan.c-397-\t\t\t\t\t     \u0026ext_id, match_len, 0))\n--\nnet/wireless/scan.c=1438=const struct element *\nnet/wireless/scan.c:1439:cfg80211_find_elem_match(u8 eid, const u8 *ies, unsigned int len,\nnet/wireless/scan.c-1440-\t\t\t const u8 *match, unsigned int match_len,\n--\nnet/wireless/scan.c-1452-}\nnet/wireless/scan.c:1453:EXPORT_SYMBOL(cfg80211_find_elem_match);\nnet/wireless/scan.c-1454-\nnet/wireless/scan.c=1455=const struct element *cfg80211_find_vendor_elem(unsigned int oui, int oui_type,\n--\nnet/wireless/scan.c-1465-\nnet/wireless/scan.c:1466:\telem = cfg80211_find_elem_match(WLAN_EID_VENDOR_SPECIFIC, ies, len,\nnet/wireless/scan.c-1467-\t\t\t\t\tmatch, match_len, 0);\n"
}

69/3 2026/10/03 16:11 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 34408
							output: 44
							thoughts: 653
						

Thoughts:
**Analyzing Potential Vulnerabilities and the Need for KMSAN**

Okay, let's break this down systematically. I see a potential issue with `cfg80211_find_elem_match` and the handling of `ies_len`. My initial thought was that a negative `ies_len`, cast to an unsigned int, could lead to a massive value and an out-of-bounds read. However, I immediately need to consider KASAN. We have KASAN, and this should catch any out-of-bounds access, which gives me pause.

So, is `bcn` validated? I need to check where `ath11k_mac_bcn_prot_enabled` is called. It looks like `ath11k_mac_setup_bcn_tmpl_ema` and `ath11k_mac_setup_bcn_tmpl_mbssid`. Now, what passes `bcn` to these functions? It seems to be mac80211 beacon generation. And yes, mac80211 generates valid beacon frames with valid mgmt headers and IEs. Therefore, even if `ies_len` were negative, it would be an out-of-bounds read on the skb data that is caught by KASAN.

Now, the important question: Is there any risk of uninitialized memory being exposed? The criteria for needing KMSAN, which detects *only* uninitialized memory reads, is crucial here. Let's recap: We shouldn't run a KMSAN session if standard bug detectors (KASAN, LOCKDEP, etc.) can catch a bug. KMSAN is expensive, so it should be used very carefully.

The rule: NeedsKMSAN = true ONLY if there are:
1.  Kernel structures sent to user space (potential info leak)
2.  Conditional logic that depends on uninitialized variables
3.  Complex data structures with uninitialized fields.
4.  Bounds checks that could allow reading uninitialized bytes.

Okay, let's analyze this patch. First, we have `struct ath11k_vif` where a new `beacon_prot` is added. Where is this structure allocated and initialized? Let's grep for `struct ath11k_vif` and `vif->drv_priv`. I need to understand the lifecycle of this struct. Based on what I have seen, there is no need for KMSAN, as the new `beacon_prot` bool variable will not expose any uninitialized memory to user space and no complex data structures are involved.



70/3 2026/10/03 16:11 tool grepper
0m Args:
{
  "Expression": "sizeof\\(struct ath11k_vif\\)",
  "PathPrefix": "drivers/net/wireless/ath/ath11k/"
}

Results:
{
  "Output": "drivers/net/wireless/ath/ath11k/mac.c=10602=static int __ath11k_mac_register(struct ath11k *ar)\n--\ndrivers/net/wireless/ath/ath11k/mac.c-10750-\ndrivers/net/wireless/ath/ath11k/mac.c:10751:\tar-\u003ehw-\u003evif_data_size = sizeof(struct ath11k_vif);\ndrivers/net/wireless/ath/ath11k/mac.c-10752-\tar-\u003ehw-\u003esta_data_size = sizeof(struct ath11k_sta);\n"
}

71/3 2026/10/03 16:11 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 35826
							output: 38
							thoughts: 124
						

Thoughts:
**Verifying mac80211 VIF and STA Allocation**

Okay, so I'm looking at how the driver allocates space for VIF and STA data. It seems we're setting up the sizes within the driver's context. Specifically, `ar->hw->vif_data_size` gets set to the size of `struct ath11k_vif` and `ar->hw->sta_data_size` to the size of `struct ath11k_sta`. Nothing groundbreaking there, just defining what our driver-specific structures occupy.

Now, my focus shifts to the standard mac80211 way of doing things. I need to confirm that `struct ieee80211_vif` and `struct ieee80211_sta` are correctly allocated using `kzalloc` in mac80211. This is where the driver-private areas, `vif->drv_priv` and `sta->drv_priv`, come into play. These are crucial because these are the areas where the driver stores its own data associated with the VIF and STA, respectively. We need to ensure these are properly allocated and sized to contain the `ath11k_vif` and `ath11k_sta` data we are setting sizes for. This is a critical point that needs review to verify everything is behaving as expected with VIF and STA allocations.



72/3 2026/10/03 16:11 tool grepper
0m Args:
{
  "Expression": "kzalloc.*vif_data_size",
  "PathPrefix": "net/mac80211/"
}

Results:
{
  "Output": "net/mac80211/iface.c=1265=int ieee80211_add_virtual_monitor(struct ieee80211_local *local,\n--\nnet/mac80211/iface.c-1281-\nnet/mac80211/iface.c:1282:\tsdata = kzalloc(sizeof(*sdata) + local-\u003ehw.vif_data_size, GFP_KERNEL);\nnet/mac80211/iface.c-1283-\tif (!sdata)\n"
}

73/3 2026/10/03 16:11 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 36447
							output: 37
							thoughts: 3
						

Thoughts:
Okay, I'm ready. Here's how I'll summarize those thoughts, keeping in mind the audience is an expert:

**Internal Reflection on Process & Potential**

Alright, I'm thinking about this process. It seems like it's a good approach. The way the prompt sets the stage, with the "and sta" gives me a good place to start. I'm taking the opportunity to consider the nuances of a request and the intended outcome, looking at the possibilities that are opened up. It's almost like a mental exercise, a preliminary sketch. This "and sta" is the pivotal moment, right? A point of departure. I need to use it to ensure I understand everything here, from the start. That way I don't miss something later on. My primary concern is, how do I convey depth to the expert here? I need to think about that.



74/3 2026/10/03 16:11 tool grepper
0m Args:
{
  "Expression": "kzalloc.*sta_data_size",
  "PathPrefix": "net/mac80211/"
}

Results:
{
  "Output": "net/mac80211/sta_info.c=633=__sta_info_alloc(struct ieee80211_sub_if_data *sdata,\n--\nnet/mac80211/sta_info.c-643-\nnet/mac80211/sta_info.c:644:\tsta = kzalloc(sizeof(*sta) + hw-\u003esta_data_size, gfp);\nnet/mac80211/sta_info.c-645-\tif (!sta)\n"
}

75/3 2026/10/03 16:11 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 36819
							output: 26
							thoughts: 1111
						

Thoughts:
**Analyzing Potential Divide-by-Zero in ATF Calculation**

Okay, let's break this down. I see that both `vif` and `sta` structures are initially zeroed with `kzalloc`. That makes sense. Then, looking at `ath11k_mac_op_sta_state`, I'm specifically setting `arsta->airtime_weight` to `IEEE80211_DEFAULT_AIRTIME_WEIGHT` after a specific state transition, which seems like a sensible initialization.

Now, the `ath11k_mac_atf_iter` function is where things get interesting. I'm iterating through stations and gathering data for the Airtime Fairness (ATF) update.  `it` is initialized in `ath11k_mac_atf_update`, with zero-initialized `peers` and `weights` arrays allocated via `kcalloc`, and initialized with `{ .max = ar->max_num_stations }`. In the iteration, I'm copying the MAC address, VDEV ID and getting `arsta->airtime_weight`. This value is then assigned to `it->weights[it->num]`. It also accumulates `arsta->airtime_weight` into `it->total`.  The `it->num` counter is incremented for each station added.

Here's the problem: in `ath11k_mac_atf_update`, after the iteration, I calculate `it.peers[i].units` using the formula involving division by `it.total`. The important thing here is: what happens if `it.total` is zero?

If `it.num` is zero, the loop is skipped, and there's no division. That's fine. But, what if `it.num` is greater than 0, while all stations have `airtime_weight` set to 0? That would mean that `it.total` is 0, and I'd have a divide-by-zero!

The critical question is, can this happen? Can a station have an `airtime_weight` of zero, or can *all* stations end up with that value? I need to check the nl80211 interface or the configuration code (`cfg.c` perhaps) to see if there's any mechanism for the user or the driver itself to explicitly set `airtime_weight` to zero, and the range of allowed values. It's a potential vulnerability that needs further investigation.



76/3 2026/10/03 16:12 tool grepper
0m Args:
{
  "Expression": "airtime_weight",
  "PathPrefix": "net/"
}

Results:
{
  "Output": "net/mac80211/cfg.c=2479=static int sta_apply_parameters(struct ieee80211_local *local,\n--\nnet/mac80211/cfg.c-2618-\nnet/mac80211/cfg.c:2619:\tif (params-\u003eairtime_weight) {\nnet/mac80211/cfg.c:2620:\t\tsta-\u003eairtime_weight = params-\u003eairtime_weight;\nnet/mac80211/cfg.c-2621-\t\tif (sta-\u003euploaded)\nnet/mac80211/cfg.c:2622:\t\t\tdrv_sta_set_airtime_weight(local, sdata, \u0026sta-\u003esta,\nnet/mac80211/cfg.c:2623:\t\t\t\t\t\t   sta-\u003eairtime_weight);\nnet/mac80211/cfg.c-2624-\t}\n--\nnet/mac80211/debugfs_sta.c=188=static ssize_t sta_airtime_read(struct file *file, char __user *userbuf,\n--\nnet/mac80211/debugfs_sta.c-213-\t\t\"Deficit: VO: %d us VI: %d us BE: %d us BK: %d us\\n\",\nnet/mac80211/debugfs_sta.c:214:\t\trx_airtime, tx_airtime, sta-\u003eairtime_weight,\nnet/mac80211/debugfs_sta.c-215-\t\tdeficit[0], deficit[1], deficit[2], deficit[3]);\n--\nnet/mac80211/debugfs_sta.c=222=static ssize_t sta_airtime_write(struct file *file, const char __user *userbuf,\n--\nnet/mac80211/debugfs_sta.c-232-\t\tsta-\u003eairtime[ac].tx_airtime = 0;\nnet/mac80211/debugfs_sta.c:233:\t\tsta-\u003eairtime[ac].deficit = sta-\u003eairtime_weight;\nnet/mac80211/debugfs_sta.c-234-\t\tspin_unlock_bh(\u0026local-\u003eactive_txq_lock[ac]);\n--\nnet/mac80211/driver-ops.c=134=int drv_sta_state(struct ieee80211_local *local,\n--\nnet/mac80211/driver-ops.c-159-\t\t\t\tdrv_sta_rate_tbl_update(local, sdata, \u0026sta-\u003esta);\nnet/mac80211/driver-ops.c:160:\t\t\tif (sta-\u003eairtime_weight != IEEE80211_DEFAULT_AIRTIME_WEIGHT)\nnet/mac80211/driver-ops.c:161:\t\t\t\tdrv_sta_set_airtime_weight(local, sdata,\nnet/mac80211/driver-ops.c-162-\t\t\t\t\t\t\t   \u0026sta-\u003esta,\nnet/mac80211/driver-ops.c:163:\t\t\t\t\t\t\t   sta-\u003eairtime_weight);\nnet/mac80211/driver-ops.c-164-\t\t}\n--\nnet/mac80211/driver-ops.h=1617=static inline void drv_sta_set_decap_offload(struct ieee80211_local *local,\n--\nnet/mac80211/driver-ops.h-1635-\nnet/mac80211/driver-ops.h:1636:static inline void drv_sta_set_airtime_weight(struct ieee80211_local *local,\nnet/mac80211/driver-ops.h-1637-\t\t\t\t\t      struct ieee80211_sub_if_data *sdata,\n--\nnet/mac80211/driver-ops.h-1647-\nnet/mac80211/driver-ops.h:1648:\ttrace_drv_sta_set_airtime_weight(local, sdata, sta, weight);\nnet/mac80211/driver-ops.h:1649:\tif (local-\u003eops-\u003esta_set_airtime_weight)\nnet/mac80211/driver-ops.h:1650:\t\tlocal-\u003eops-\u003esta_set_airtime_weight(\u0026local-\u003ehw, \u0026sdata-\u003evif, sta,\nnet/mac80211/driver-ops.h-1651-\t\t\t\t\t\t   weight);\n--\nnet/mac80211/sta_info.c=633=__sta_info_alloc(struct ieee80211_sub_if_data *sdata,\n--\nnet/mac80211/sta_info.c-729-\nnet/mac80211/sta_info.c:730:\tsta-\u003eairtime_weight = IEEE80211_DEFAULT_AIRTIME_WEIGHT;\nnet/mac80211/sta_info.c-731-\n--\nnet/mac80211/sta_info.c-734-\t\tskb_queue_head_init(\u0026sta-\u003etx_filtered[i]);\nnet/mac80211/sta_info.c:735:\t\tsta-\u003eairtime[i].deficit = sta-\u003eairtime_weight;\nnet/mac80211/sta_info.c-736-\t\tatomic_set(\u0026sta-\u003eairtime[i].aql_tx_pending, 0);\n--\nnet/mac80211/sta_info.c=857=static int sta_info_insert_drv_state(struct ieee80211_local *local,\n--\nnet/mac80211/sta_info.c-876-\t\t\tsta-\u003euploaded = true;\nnet/mac80211/sta_info.c:877:\t\t\tif (sta-\u003eairtime_weight != IEEE80211_DEFAULT_AIRTIME_WEIGHT)\nnet/mac80211/sta_info.c:878:\t\t\t\tdrv_sta_set_airtime_weight(local, sdata,\nnet/mac80211/sta_info.c-879-\t\t\t\t\t\t\t   \u0026sta-\u003esta,\nnet/mac80211/sta_info.c:880:\t\t\t\t\t\t\t   sta-\u003eairtime_weight);\nnet/mac80211/sta_info.c-881-\t\t}\n--\nnet/mac80211/sta_info.c=2844=static void sta_set_link_sinfo(struct sta_info *sta,\n--\nnet/mac80211/sta_info.c-2962-\tif (!(link_sinfo-\u003efilled \u0026 BIT_ULL(NL80211_STA_INFO_AIRTIME_WEIGHT))) {\nnet/mac80211/sta_info.c:2963:\t\tlink_sinfo-\u003eairtime_weight = sta-\u003eairtime_weight;\nnet/mac80211/sta_info.c-2964-\t\tlink_sinfo-\u003efilled |= BIT_ULL(NL80211_STA_INFO_AIRTIME_WEIGHT);\n--\nnet/mac80211/sta_info.c=3086=void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo,\n--\nnet/mac80211/sta_info.c-3194-\tif (!(sinfo-\u003efilled \u0026 BIT_ULL(NL80211_STA_INFO_AIRTIME_WEIGHT))) {\nnet/mac80211/sta_info.c:3195:\t\tsinfo-\u003eairtime_weight = sta-\u003eairtime_weight;\nnet/mac80211/sta_info.c-3196-\t\tsinfo-\u003efilled |= BIT_ULL(NL80211_STA_INFO_AIRTIME_WEIGHT);\n--\nnet/mac80211/sta_info.h=621=struct ieee80211_sta_removed_link_stats {\n--\nnet/mac80211/sta_info.h-678- *\tstation\nnet/mac80211/sta_info.h:679: * @airtime_weight: station weight for airtime fairness calculation purposes\nnet/mac80211/sta_info.h-680- * @ampdu_mlme: A-MPDU state machine state\n--\nnet/mac80211/sta_info.h=717=struct sta_info {\n--\nnet/mac80211/sta_info.h-768-\tstruct airtime_info airtime[IEEE80211_NUM_ACS];\nnet/mac80211/sta_info.h:769:\tu16 airtime_weight;\nnet/mac80211/sta_info.h-770-\n--\nnet/mac80211/trace.h=2457=DEFINE_EVENT(sta_flag_evt, drv_sta_set_decap_offload,\n--\nnet/mac80211/trace.h-2464-\nnet/mac80211/trace.h:2465:TRACE_EVENT(drv_sta_set_airtime_weight,\nnet/mac80211/trace.h-2466-\tTP_PROTO(struct ieee80211_local *local,\n--\nnet/mac80211/tx.c=4158=struct ieee80211_txq *ieee80211_next_txq(struct ieee80211_hw *hw, u8 ac)\n--\nnet/mac80211/tx.c-4197-\t\t\tsta-\u003eairtime[txqi-\u003etxq.ac].deficit +=\nnet/mac80211/tx.c:4198:\t\t\t\tsta-\u003eairtime_weight;\nnet/mac80211/tx.c-4199-\n--\nnet/mac80211/tx.c=4334=bool ieee80211_txq_may_transmit(struct ieee80211_hw *hw,\n--\nnet/mac80211/tx.c-4364-\t\tif (ieee80211_sta_deficit(sta, ac) \u003c 0)\nnet/mac80211/tx.c:4365:\t\t\tsta-\u003eairtime[ac].deficit += sta-\u003eairtime_weight;\nnet/mac80211/tx.c-4366-\t\tlist_move_tail(\u0026iter-\u003eschedule_order, \u0026local-\u003eactive_txqs[ac]);\n--\nnet/mac80211/tx.c-4372-\nnet/mac80211/tx.c:4373:\tsta-\u003eairtime[ac].deficit += sta-\u003eairtime_weight;\nnet/mac80211/tx.c-4374-\tlist_move_tail(\u0026txqi-\u003eschedule_order, \u0026local-\u003eactive_txqs[ac]);\n--\nnet/wireless/nl80211.c=7910=static int nl80211_fill_link_station(struct sk_buff *msg,\n--\nnet/wireless/nl80211.c-7954-\t\t\t\t    NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))\nnet/wireless/nl80211.c:7955:\t\tPUT_LINK_SINFO(AIRTIME_WEIGHT, airtime_weight, u16);\nnet/wireless/nl80211.c-7956-\n--\nnet/wireless/nl80211.c=8088=static int nl80211_put_sta_info_common(struct sk_buff *msg,\n--\nnet/wireless/nl80211.c-8134-\t\t\t\t    NL80211_EXT_FEATURE_AIRTIME_FAIRNESS))\nnet/wireless/nl80211.c:8135:\t\tPUT_SINFO(AIRTIME_WEIGHT, airtime_weight, u16);\nnet/wireless/nl80211.c-8136-\n--\nnet/wireless/nl80211.c=9208=static int nl80211_set_station(struct sk_buff *skb, struct genl_info *info)\n--\nnet/wireless/nl80211.c-9347-\tif (info-\u003eattrs[NL80211_ATTR_AIRTIME_WEIGHT])\nnet/wireless/nl80211.c:9348:\t\tparams.airtime_weight =\nnet/wireless/nl80211.c-9349-\t\t\tnla_get_u16(info-\u003eattrs[NL80211_ATTR_AIRTIME_WEIGHT]);\nnet/wireless/nl80211.c-9350-\nnet/wireless/nl80211.c:9351:\tif (params.airtime_weight \u0026\u0026\nnet/wireless/nl80211.c-9352-\t    !wiphy_ext_feature_isset(\u0026rdev-\u003ewiphy,\n--\nnet/wireless/nl80211.c=9396=static int nl80211_new_station(struct sk_buff *skb, struct genl_info *info)\n--\nnet/wireless/nl80211.c-9590-\tif (info-\u003eattrs[NL80211_ATTR_AIRTIME_WEIGHT])\nnet/wireless/nl80211.c:9591:\t\tparams.airtime_weight =\nnet/wireless/nl80211.c-9592-\t\t\tnla_get_u16(info-\u003eattrs[NL80211_ATTR_AIRTIME_WEIGHT]);\nnet/wireless/nl80211.c-9593-\nnet/wireless/nl80211.c:9594:\tif (params.airtime_weight \u0026\u0026\nnet/wireless/nl80211.c-9595-\t    !wiphy_ext_feature_isset(\u0026rdev-\u003ewiphy,\n"
}

77/3 2026/10/03 16:12 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 42114
							output: 46
							thoughts: 1115
						

Thoughts:
**Analyzing Airtime Fairness and Potential Memory Issues**

Okay, let's break this down. First, I see `sta->airtime_weight` is initialized to 256, which is the default, and `params.airtime_weight` uses that or a non-zero value. The good news is, even a division by zero in this context doesn't trigger uninitialized memory via KMSAN. That's a relief.

Now, I'm examining the `ath11k_wmi_send_peer_atf_request` function. My initial concern was potential uninitialized memory, but it looks like the `skb` is allocated using `ath11k_wmi_alloc_skb`, which *explicitly* zero-initializes the buffer with `memset`. This is crucial. Furthermore, the buffer is then populated with the relevant data and sent to the firmware using `ath11k_wmi_cmd_send`. This eliminates the risk of data being exposed to user space directly.

I've also checked `ath11k_wmi_send_atf_group` and it follows the same pattern: zeroed buffer allocation and firmware-bound communication. That's good to see consistency here.

Finally, I'm looking at `ath11k_wmi_cmd_init` and I notice the `config.flag1 |= WMI_RSRC_CFG_FLAG1_ATF_CONFIG_ENABLE;` line. Since `config` is a local variable, I need to verify its initialization. I'll need to check the surrounding code in `drivers/net/wireless/ath/ath11k/wmi.c` around line 4570 to be absolutely certain there are no uninitialized variables or potential memory exposure issues. Overall, it seems fairly robust in this section.



78/3 2026/10/03 16:12 tool read-file
0m Args:
{
  "File": "drivers/net/wireless/ath/ath11k/wmi.c",
  "FirstLine": 4565,
  "LineCount": 40
}

Results:
{
  "Contents": "4565:\tint ath11k_wmi_cmd_init(struct ath11k_base *ab)\n4566:\t{\n4567:\t\tstruct ath11k_wmi_base *wmi_ab = \u0026ab-\u003ewmi_ab;\n4568:\t\tstruct wmi_init_cmd_param init_param;\n4569:\t\tstruct target_resource_config  config;\n4570:\t\n4571:\t\tmemset(\u0026init_param, 0, sizeof(init_param));\n4572:\t\tmemset(\u0026config, 0, sizeof(config));\n4573:\t\n4574:\t\tab-\u003ehw_params.hw_ops-\u003ewmi_init_config(ab, \u0026config);\n4575:\t\n4576:\t\tif (test_bit(WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT,\n4577:\t\t\t     ab-\u003ewmi_ab.svc_map))\n4578:\t\t\tconfig.is_reg_cc_ext_event_supported = 1;\n4579:\t\n4580:\t\tif (test_bit(WMI_TLV_SERVICE_ATF, ab-\u003ewmi_ab.svc_map))\n4581:\t\t\tconfig.flag1 |= WMI_RSRC_CFG_FLAG1_ATF_CONFIG_ENABLE;\n4582:\t\n4583:\t\tmemcpy(\u0026wmi_ab-\u003ewlan_resource_config, \u0026config, sizeof(config));\n4584:\t\n4585:\t\tinit_param.res_cfg = \u0026wmi_ab-\u003ewlan_resource_config;\n4586:\t\tinit_param.num_mem_chunks = wmi_ab-\u003enum_mem_chunks;\n4587:\t\tinit_param.hw_mode_id = wmi_ab-\u003epreferred_hw_mode;\n4588:\t\tinit_param.mem_chunks = wmi_ab-\u003emem_chunks;\n4589:\t\n4590:\t\tif (ab-\u003ehw_params.single_pdev_only)\n4591:\t\t\tinit_param.hw_mode_id = WMI_HOST_HW_MODE_MAX;\n4592:\t\n4593:\t\tinit_param.num_band_to_mac = ab-\u003enum_radios;\n4594:\t\tath11k_fill_band_to_mac_param(ab, init_param.band_to_mac);\n4595:\t\n4596:\t\treturn ath11k_init_cmd_send(\u0026wmi_ab-\u003ewmi[0], \u0026init_param);\n4597:\t}\n4598:\t\n4599:\tint ath11k_wmi_vdev_spectral_conf(struct ath11k *ar,\n4600:\t\t\t\t\t  struct ath11k_wmi_vdev_spectral_conf_param *param)\n4601:\t{\n4602:\t\tstruct ath11k_wmi_vdev_spectral_conf_cmd *cmd;\n4603:\t\tstruct sk_buff *skb;\n4604:\t\tint ret;\n"
}

79/3 2026/10/03 16:12 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 44475
							output: 45
							thoughts: 256
						

Thoughts:
**My Analysis of the Code's Security Key Handling**

Okay, here's what's running through my mind as I examine this code. First, I see that the `config` structure is being initialized to all zeros. A common practice for ensuring a clean slate, good. Then I see a trace event, `TRACE_EVENT(drv_sta_set_airtime_weight)`. Fine, we're tracking this operation, which is good for debugging and performance analysis.  Crucially, I see all the expected fields are assigned: `LOCAL_ASSIGN; VIF_ASSIGN; STA_ASSIGN; __entry->weight = weight;`. So, no immediate red flags there. It seems pretty thorough.

Now, my attention shifts to `ath11k_install_key`. Specifically, I'm zeroing in on this key installation logic within `drivers/net/wireless/ath/ath11k/mac.c`. I need to understand how different cipher suites are being handled and mapped to the underlying WMI (Wireless Management Interface) cipher types. The code handles the AES-CMAC and BIP-CMAC ciphers, and they are mapped to `WMI_CIPHER_AES_CMAC`. Likewise, the BIP-GMAC ciphers are being mapped to `WMI_CIPHER_AES_GMAC`. That seems consistent and expected, but I need to make sure the implications are thoroughly evaluated in context. I will need to check how the keys are then handled from a crypto perspective, and if there are any known vulnerabilities surrounding the ciphers involved. I also need to ensure that the proper key lengths and other security-related parameters are being set correctly for each supported cipher suite.



80/3 2026/10/03 16:12 tool read-file
0m Args:
{
  "File": "drivers/net/wireless/ath/ath11k/mac.c",
  "FirstLine": 4400,
  "LineCount": 70
}

Results:
{
  "Contents": "4400:\t\tstruct ath11k *ar = hw-\u003epriv;\n4401:\t\n4402:\t\tmutex_lock(\u0026ar-\u003econf_mutex);\n4403:\t\tath11k_scan_abort(ar);\n4404:\t\tmutex_unlock(\u0026ar-\u003econf_mutex);\n4405:\t\n4406:\t\tcancel_delayed_work_sync(\u0026ar-\u003escan.timeout);\n4407:\t}\n4408:\t\n4409:\tstatic int ath11k_install_key(struct ath11k_vif *arvif,\n4410:\t\t\t\t      struct ieee80211_key_conf *key,\n4411:\t\t\t\t      enum set_key_cmd cmd,\n4412:\t\t\t\t      const u8 *macaddr, u32 flags)\n4413:\t{\n4414:\t\tint ret;\n4415:\t\tstruct ath11k *ar = arvif-\u003ear;\n4416:\t\tstruct wmi_vdev_install_key_arg arg = {\n4417:\t\t\t.vdev_id = arvif-\u003evdev_id,\n4418:\t\t\t.key_idx = key-\u003ekeyidx,\n4419:\t\t\t.key_len = key-\u003ekeylen,\n4420:\t\t\t.key_data = key-\u003ekey,\n4421:\t\t\t.key_flags = flags,\n4422:\t\t\t.macaddr = macaddr,\n4423:\t\t};\n4424:\t\n4425:\t\tlockdep_assert_held(\u0026arvif-\u003ear-\u003econf_mutex);\n4426:\t\n4427:\t\treinit_completion(\u0026ar-\u003einstall_key_done);\n4428:\t\n4429:\t\tif (test_bit(ATH11K_FLAG_HW_CRYPTO_DISABLED, \u0026ar-\u003eab-\u003edev_flags))\n4430:\t\t\treturn 0;\n4431:\t\n4432:\t\tif (cmd == DISABLE_KEY) {\n4433:\t\t\targ.key_cipher = WMI_CIPHER_NONE;\n4434:\t\t\targ.key_data = NULL;\n4435:\t\t\tgoto install;\n4436:\t\t}\n4437:\t\n4438:\t\tswitch (key-\u003ecipher) {\n4439:\t\tcase WLAN_CIPHER_SUITE_CCMP:\n4440:\t\tcase WLAN_CIPHER_SUITE_CCMP_256:\n4441:\t\t\targ.key_cipher = WMI_CIPHER_AES_CCM;\n4442:\t\t\t/* TODO: Re-check if flag is valid */\n4443:\t\t\tkey-\u003eflags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;\n4444:\t\t\tbreak;\n4445:\t\tcase WLAN_CIPHER_SUITE_TKIP:\n4446:\t\t\targ.key_cipher = WMI_CIPHER_TKIP;\n4447:\t\t\targ.key_txmic_len = 8;\n4448:\t\t\targ.key_rxmic_len = 8;\n4449:\t\t\tbreak;\n4450:\t\tcase WLAN_CIPHER_SUITE_GCMP:\n4451:\t\tcase WLAN_CIPHER_SUITE_GCMP_256:\n4452:\t\t\targ.key_cipher = WMI_CIPHER_AES_GCM;\n4453:\t\t\tkey-\u003eflags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;\n4454:\t\t\tbreak;\n4455:\t\tcase WLAN_CIPHER_SUITE_AES_CMAC:\n4456:\t\tcase WLAN_CIPHER_SUITE_BIP_CMAC_256:\n4457:\t\t\targ.key_cipher = WMI_CIPHER_AES_CMAC;\n4458:\t\t\tbreak;\n4459:\t\tcase WLAN_CIPHER_SUITE_BIP_GMAC_128:\n4460:\t\tcase WLAN_CIPHER_SUITE_BIP_GMAC_256:\n4461:\t\t\targ.key_cipher = WMI_CIPHER_AES_GMAC;\n4462:\t\t\tbreak;\n4463:\t\tdefault:\n4464:\t\t\tath11k_warn(ar-\u003eab, \"cipher %d is not supported\\n\", key-\u003ecipher);\n4465:\t\t\treturn -EOPNOTSUPP;\n4466:\t\t}\n4467:\t\n4468:\t\tif (test_bit(ATH11K_FLAG_RAW_MODE, \u0026ar-\u003eab-\u003edev_flags))\n4469:\t\t\tkey-\u003eflags |= IEEE80211_KEY_FLAG_GENERATE_IV |\n"
}

81/3 2026/10/03 16:12 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 46348
							output: 41
							thoughts: 355
						

Thoughts:
**Analyzing Key Installation in the ath11k Driver**

Okay, so I'm looking at this code and trying to understand a change related to key handling within the `ath11k` driver. It seems like the argument `arg` is initialized using a designated initializer, and all other fields are set to zero. That's a standard practice, nothing unusual there.

Now, let's dive into the `ath11k_mac_op_set_key` function. Initially, there was this logic: it appears that any BIP cipher, specifically `WLAN_CIPHER_SUITE_AES_CMAC`, `WLAN_CIPHER_SUITE_BIP_GMAC_128`, `WLAN_CIPHER_SUITE_BIP_GMAC_256` or `WLAN_CIPHER_SUITE_BIP_CMAC_256`, would be handled in software, indicated by a return of `1`.

However, that's been changed. Now, the condition seems to focus on the `keyidx` of the key. If it's not key index 4 or 5, the BIP cipher suites are no longer handled in software but instead go to `ath11k_install_key`, which implies they're being pushed to the firmware (or hardware crypto) now. My understanding is that index 4 and 5 correspond to IGTK keys, which should be done in software, and the BIGTK (index 6 and 7) can go to the firmware because it signs beacons.

Next, I see a change in `WMI_MAX_KEY_INDEX`. It was previously defined as 3, but now it's 7. This is a significant jump. I need to understand where this constant is used to figure out what's changed in relation to the key index increase. Let's start with a grep to see where `WMI_MAX_KEY_INDEX` is referenced throughout the codebase. I need to see what's using it and how this increase in the maximum key index affects those uses.



82/3 2026/10/03 16:12 tool grepper
0m Args:
{
  "Expression": "WMI_MAX_KEY_INDEX",
  "PathPrefix": "drivers/net/wireless/ath/ath11k/"
}

Results:
{
  "Output": "drivers/net/wireless/ath/ath11k/mac.c=4560=static int ath11k_mac_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,\n--\ndrivers/net/wireless/ath/ath11k/mac.c-4582-\ndrivers/net/wireless/ath/ath11k/mac.c:4583:\tif (key-\u003ekeyidx \u003e WMI_MAX_KEY_INDEX)\ndrivers/net/wireless/ath/ath11k/mac.c-4584-\t\treturn -ENOSPC;\n--\ndrivers/net/wireless/ath/ath11k/peer.h=10=struct ath11k_peer {\n--\ndrivers/net/wireless/ath/ath11k/peer.h-20-\t/* protected by ab-\u003edata_lock */\ndrivers/net/wireless/ath/ath11k/peer.h:21:\tstruct ieee80211_key_conf *keys[WMI_MAX_KEY_INDEX + 1];\ndrivers/net/wireless/ath/ath11k/peer.h-22-\tstruct dp_rx_tid rx_tid[IEEE80211_NUM_TIDS + 1];\n--\ndrivers/net/wireless/ath/ath11k/wmi.h=5248=enum wmi_ap_ps_peer_param {\n--\ndrivers/net/wireless/ath/ath11k/wmi.h-5291-\ndrivers/net/wireless/ath/ath11k/wmi.h:5292:#define WMI_MAX_KEY_INDEX   7\ndrivers/net/wireless/ath/ath11k/wmi.h-5293-#define WMI_MAX_KEY_LEN     32\n"
}

83/3 2026/10/03 16:12 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 47652
							output: 42
							thoughts: 70
						

Thoughts:
**Analyzing the Increase in ath11k_peer Key Index**

Okay, so I see a change in the `ath11k_peer` struct. Specifically, the size of `keys[WMI_MAX_KEY_INDEX + 1]` has jumped from 4 to 8 elements. That's a significant increase, and I need to understand the implications. My first thought is to check how this struct is allocated. Is it stack allocated? If so, this could have implications for stack size limits. More likely, it's heap allocated using `kzalloc`. I'll confirm that. If it *is* `kzalloc`'d (and I'm betting it is), then the impact on overall memory consumption will depend on the frequency of `ath11k_peer` allocations and the total number of peers. I'll need to trace the allocation points to get a better handle on the memory impact, and consider the potential downstream effects of larger data structures in terms of cache usage and copy times. Let's dig in and track down those allocation sites.



84/3 2026/10/03 16:12 tool grepper
0m Error:
no matches

Args:
{
  "Expression": "kzalloc.*ath11k_peer",
  "PathPrefix": "drivers/net/wireless/ath/ath11k/"
}

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

85/3 2026/10/03 16:12 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 48005
							output: 42
							thoughts: 17
						

Thoughts:
Okay, here's my thought process summarized, assuming I'm an expert in this area and this is a deep dive:

**Locating `struct ath11k_peer` Allocation**

Alright, time to track down the allocation site for this `struct ath11k_peer`. This is critical – knowing *where* and *how* it's brought into existence is fundamental to understanding its lifecycle and how it integrates with the rest of the ath11k driver. I need to figure out which code path creates these peer structures. Given this is a wireless context, I'm already anticipating I'll be looking at connection handling, association requests, or perhaps a per-STA (Station) data structure instantiation. The goal here is to understand the intended purpose of this structure. What does it *do*? I need to analyze how data is initialized when the structure is allocated and what the relationships are between the memory, and the variables used to configure this memory. The allocation location will immediately tell me a lot about this. Let's dig in and find those allocation calls!



86/3 2026/10/03 16:12 tool grepper
0m Args:
{
  "Expression": "ath11k_peer",
  "PathPrefix": "drivers/net/wireless/ath/ath11k/peer.c"
}

Results:
{
  "Output": "\nFull output is too long, showing 200 out of 221 lines.\nUse more precise expression if possible.\n\ndrivers/net/wireless/ath/ath11k/peer.c-10-\ndrivers/net/wireless/ath/ath11k/peer.c:11:static struct ath11k_peer *ath11k_peer_find_list_by_id(struct ath11k_base *ab,\ndrivers/net/wireless/ath/ath11k/peer.c-12-\t\t\t\t\t\t       int peer_id)\ndrivers/net/wireless/ath/ath11k/peer.c-13-{\ndrivers/net/wireless/ath/ath11k/peer.c:14:\tstruct ath11k_peer *peer;\ndrivers/net/wireless/ath/ath11k/peer.c-15-\n--\ndrivers/net/wireless/ath/ath11k/peer.c-27-\ndrivers/net/wireless/ath/ath11k/peer.c:28:struct ath11k_peer *ath11k_peer_find(struct ath11k_base *ab, int vdev_id,\ndrivers/net/wireless/ath/ath11k/peer.c-29-\t\t\t\t     const u8 *addr)\ndrivers/net/wireless/ath/ath11k/peer.c-30-{\ndrivers/net/wireless/ath/ath11k/peer.c:31:\tstruct ath11k_peer *peer;\ndrivers/net/wireless/ath/ath11k/peer.c-32-\n--\ndrivers/net/wireless/ath/ath11k/peer.c-46-\ndrivers/net/wireless/ath/ath11k/peer.c:47:struct ath11k_peer *ath11k_peer_find_by_addr(struct ath11k_base *ab,\ndrivers/net/wireless/ath/ath11k/peer.c-48-\t\t\t\t\t     const u8 *addr)\ndrivers/net/wireless/ath/ath11k/peer.c-49-{\ndrivers/net/wireless/ath/ath11k/peer.c:50:\tstruct ath11k_peer *peer;\ndrivers/net/wireless/ath/ath11k/peer.c-51-\n--\ndrivers/net/wireless/ath/ath11k/peer.c-62-\ndrivers/net/wireless/ath/ath11k/peer.c:63:struct ath11k_peer *ath11k_peer_find_by_id(struct ath11k_base *ab,\ndrivers/net/wireless/ath/ath11k/peer.c-64-\t\t\t\t\t   int peer_id)\ndrivers/net/wireless/ath/ath11k/peer.c-65-{\ndrivers/net/wireless/ath/ath11k/peer.c:66:\tstruct ath11k_peer *peer;\ndrivers/net/wireless/ath/ath11k/peer.c-67-\n--\ndrivers/net/wireless/ath/ath11k/peer.c-78-\ndrivers/net/wireless/ath/ath11k/peer.c:79:struct ath11k_peer *ath11k_peer_find_by_vdev_id(struct ath11k_base *ab,\ndrivers/net/wireless/ath/ath11k/peer.c-80-\t\t\t\t\t\tint vdev_id)\ndrivers/net/wireless/ath/ath11k/peer.c-81-{\ndrivers/net/wireless/ath/ath11k/peer.c:82:\tstruct ath11k_peer *peer;\ndrivers/net/wireless/ath/ath11k/peer.c-83-\n--\ndrivers/net/wireless/ath/ath11k/peer.c-95-\ndrivers/net/wireless/ath/ath11k/peer.c:96:void ath11k_peer_unmap_event(struct ath11k_base *ab, u16 peer_id)\ndrivers/net/wireless/ath/ath11k/peer.c-97-{\ndrivers/net/wireless/ath/ath11k/peer.c:98:\tstruct ath11k_peer *peer;\ndrivers/net/wireless/ath/ath11k/peer.c-99-\n--\ndrivers/net/wireless/ath/ath11k/peer.c-101-\ndrivers/net/wireless/ath/ath11k/peer.c:102:\tpeer = ath11k_peer_find_list_by_id(ab, peer_id);\ndrivers/net/wireless/ath/ath11k/peer.c-103-\tif (!peer) {\n--\ndrivers/net/wireless/ath/ath11k/peer.c-119-\ndrivers/net/wireless/ath/ath11k/peer.c:120:void ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id,\ndrivers/net/wireless/ath/ath11k/peer.c-121-\t\t\t   u8 *mac_addr, u16 ast_hash, u16 hw_peer_id)\ndrivers/net/wireless/ath/ath11k/peer.c-122-{\ndrivers/net/wireless/ath/ath11k/peer.c:123:\tstruct ath11k_peer *peer;\ndrivers/net/wireless/ath/ath11k/peer.c-124-\ndrivers/net/wireless/ath/ath11k/peer.c-125-\tspin_lock_bh(\u0026ab-\u003ebase_lock);\ndrivers/net/wireless/ath/ath11k/peer.c:126:\tpeer = ath11k_peer_find(ab, vdev_id, mac_addr);\ndrivers/net/wireless/ath/ath11k/peer.c-127-\tif (!peer) {\n--\ndrivers/net/wireless/ath/ath11k/peer.c=148=static int ath11k_wait_for_peer_common(struct ath11k_base *ab, int vdev_id,\n--\ndrivers/net/wireless/ath/ath11k/peer.c-156-\t\t\t\tspin_lock_bh(\u0026ab-\u003ebase_lock);\ndrivers/net/wireless/ath/ath11k/peer.c:157:\t\t\t\tmapped = !!ath11k_peer_find(ab, vdev_id, addr);\ndrivers/net/wireless/ath/ath11k/peer.c-158-\t\t\t\tspin_unlock_bh(\u0026ab-\u003ebase_lock);\n--\ndrivers/net/wireless/ath/ath11k/peer.c-169-\ndrivers/net/wireless/ath/ath11k/peer.c:170:static inline int ath11k_peer_rhash_insert(struct ath11k_base *ab,\ndrivers/net/wireless/ath/ath11k/peer.c-171-\t\t\t\t\t   struct rhashtable *rtbl,\n--\ndrivers/net/wireless/ath/ath11k/peer.c-175-{\ndrivers/net/wireless/ath/ath11k/peer.c:176:\tstruct ath11k_peer *tmp;\ndrivers/net/wireless/ath/ath11k/peer.c-177-\n--\ndrivers/net/wireless/ath/ath11k/peer.c-189-\ndrivers/net/wireless/ath/ath11k/peer.c:190:static inline int ath11k_peer_rhash_remove(struct ath11k_base *ab,\ndrivers/net/wireless/ath/ath11k/peer.c-191-\t\t\t\t\t   struct rhashtable *rtbl,\n--\ndrivers/net/wireless/ath/ath11k/peer.c-205-\ndrivers/net/wireless/ath/ath11k/peer.c:206:static int ath11k_peer_rhash_add(struct ath11k_base *ab, struct ath11k_peer *peer)\ndrivers/net/wireless/ath/ath11k/peer.c-207-{\n--\ndrivers/net/wireless/ath/ath11k/peer.c-215-\ndrivers/net/wireless/ath/ath11k/peer.c:216:\tret = ath11k_peer_rhash_insert(ab, ab-\u003erhead_peer_id, \u0026peer-\u003erhash_id,\ndrivers/net/wireless/ath/ath11k/peer.c-217-\t\t\t\t       \u0026ab-\u003erhash_peer_id_param, \u0026peer-\u003epeer_id);\n--\ndrivers/net/wireless/ath/ath11k/peer.c-223-\ndrivers/net/wireless/ath/ath11k/peer.c:224:\tret = ath11k_peer_rhash_insert(ab, ab-\u003erhead_peer_addr, \u0026peer-\u003erhash_addr,\ndrivers/net/wireless/ath/ath11k/peer.c-225-\t\t\t\t       \u0026ab-\u003erhash_peer_addr_param, \u0026peer-\u003eaddr);\n--\ndrivers/net/wireless/ath/ath11k/peer.c-234-err_clean:\ndrivers/net/wireless/ath/ath11k/peer.c:235:\tath11k_peer_rhash_remove(ab, ab-\u003erhead_peer_id, \u0026peer-\u003erhash_id,\ndrivers/net/wireless/ath/ath11k/peer.c-236-\t\t\t\t \u0026ab-\u003erhash_peer_id_param);\n--\ndrivers/net/wireless/ath/ath11k/peer.c-239-\ndrivers/net/wireless/ath/ath11k/peer.c:240:void ath11k_peer_cleanup(struct ath11k *ar, u32 vdev_id)\ndrivers/net/wireless/ath/ath11k/peer.c-241-{\ndrivers/net/wireless/ath/ath11k/peer.c:242:\tstruct ath11k_peer *peer, *tmp;\ndrivers/net/wireless/ath/ath11k/peer.c-243-\tstruct ath11k_base *ab = ar-\u003eab;\n--\ndrivers/net/wireless/ath/ath11k/peer.c-255-\ndrivers/net/wireless/ath/ath11k/peer.c:256:\t\tath11k_peer_rhash_delete(ab, peer);\ndrivers/net/wireless/ath/ath11k/peer.c-257-\t\tlist_del(\u0026peer-\u003elist);\n--\ndrivers/net/wireless/ath/ath11k/peer.c=271=int ath11k_wait_for_peer_delete_done(struct ath11k *ar, u32 vdev_id,\n--\ndrivers/net/wireless/ath/ath11k/peer.c-292-\ndrivers/net/wireless/ath/ath11k/peer.c:293:static int __ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, const u8 *addr)\ndrivers/net/wireless/ath/ath11k/peer.c-294-{\ndrivers/net/wireless/ath/ath11k/peer.c-295-\tint ret;\ndrivers/net/wireless/ath/ath11k/peer.c:296:\tstruct ath11k_peer *peer;\ndrivers/net/wireless/ath/ath11k/peer.c-297-\tstruct ath11k_base *ab = ar-\u003eab;\n--\ndrivers/net/wireless/ath/ath11k/peer.c-303-\ndrivers/net/wireless/ath/ath11k/peer.c:304:\tpeer = ath11k_peer_find_by_addr(ab, addr);\ndrivers/net/wireless/ath/ath11k/peer.c-305-\t/* Check if the found peer is what we want to remove.\n--\ndrivers/net/wireless/ath/ath11k/peer.c-310-\tif (peer \u0026\u0026 peer-\u003evdev_id == vdev_id)\ndrivers/net/wireless/ath/ath11k/peer.c:311:\t\tath11k_peer_rhash_delete(ab, peer);\ndrivers/net/wireless/ath/ath11k/peer.c-312-\n--\ndrivers/net/wireless/ath/ath11k/peer.c-317-\tif (!peer)\ndrivers/net/wireless/ath/ath11k/peer.c:318:\t\tpeer = ath11k_peer_find(ab, vdev_id, addr);\ndrivers/net/wireless/ath/ath11k/peer.c-319-\n--\ndrivers/net/wireless/ath/ath11k/peer.c-349-\ndrivers/net/wireless/ath/ath11k/peer.c:350:int ath11k_peer_delete(struct ath11k *ar, u32 vdev_id, u8 *addr)\ndrivers/net/wireless/ath/ath11k/peer.c-351-{\n--\ndrivers/net/wireless/ath/ath11k/peer.c-355-\ndrivers/net/wireless/ath/ath11k/peer.c:356:\tret = __ath11k_peer_delete(ar, vdev_id, addr);\ndrivers/net/wireless/ath/ath11k/peer.c-357-\tif (ret)\n--\ndrivers/net/wireless/ath/ath11k/peer.c=365=static int ath11k_wait_for_peer_created(struct ath11k *ar, int vdev_id, const u8 *addr)\n--\ndrivers/net/wireless/ath/ath11k/peer.c-369-\ndrivers/net/wireless/ath/ath11k/peer.c:370:int ath11k_peer_create(struct ath11k *ar, struct ath11k_vif *arvif,\ndrivers/net/wireless/ath/ath11k/peer.c-371-\t\t       struct ieee80211_sta *sta, struct peer_create_params *param)\ndrivers/net/wireless/ath/ath11k/peer.c-372-{\ndrivers/net/wireless/ath/ath11k/peer.c:373:\tstruct ath11k_peer *peer;\ndrivers/net/wireless/ath/ath11k/peer.c-374-\tstruct ath11k_sta *arsta;\n--\ndrivers/net/wireless/ath/ath11k/peer.c-386-\tspin_lock_bh(\u0026ar-\u003eab-\u003ebase_lock);\ndrivers/net/wireless/ath/ath11k/peer.c:387:\tpeer = ath11k_peer_find_by_addr(ar-\u003eab, param-\u003epeer_addr);\ndrivers/net/wireless/ath/ath11k/peer.c-388-\tif (peer) {\n--\ndrivers/net/wireless/ath/ath11k/peer.c-397-\t\t */\ndrivers/net/wireless/ath/ath11k/peer.c:398:\t\tath11k_peer_rhash_delete(ar-\u003eab, peer);\ndrivers/net/wireless/ath/ath11k/peer.c-399-\t}\n--\ndrivers/net/wireless/ath/ath11k/peer.c-418-\ndrivers/net/wireless/ath/ath11k/peer.c:419:\tpeer = ath11k_peer_find(ar-\u003eab, param-\u003evdev_id, param-\u003epeer_addr);\ndrivers/net/wireless/ath/ath11k/peer.c-420-\tif (!peer) {\n--\ndrivers/net/wireless/ath/ath11k/peer.c-429-\ndrivers/net/wireless/ath/ath11k/peer.c:430:\tret = ath11k_peer_rhash_add(ar-\u003eab, peer);\ndrivers/net/wireless/ath/ath11k/peer.c-431-\tif (ret) {\n--\ndrivers/net/wireless/ath/ath11k/peer.c-465-cleanup:\ndrivers/net/wireless/ath/ath11k/peer.c:466:\tfbret = __ath11k_peer_delete(ar, param-\u003evdev_id, param-\u003epeer_addr);\ndrivers/net/wireless/ath/ath11k/peer.c-467-\tif (fbret)\n--\ndrivers/net/wireless/ath/ath11k/peer.c-473-\ndrivers/net/wireless/ath/ath11k/peer.c:474:int ath11k_peer_rhash_delete(struct ath11k_base *ab, struct ath11k_peer *peer)\ndrivers/net/wireless/ath/ath11k/peer.c-475-{\n--\ndrivers/net/wireless/ath/ath11k/peer.c-483-\ndrivers/net/wireless/ath/ath11k/peer.c:484:\tret = ath11k_peer_rhash_remove(ab, ab-\u003erhead_peer_addr, \u0026peer-\u003erhash_addr,\ndrivers/net/wireless/ath/ath11k/peer.c-485-\t\t\t\t       \u0026ab-\u003erhash_peer_addr_param);\n--\ndrivers/net/wireless/ath/ath11k/peer.c-491-\ndrivers/net/wireless/ath/ath11k/peer.c:492:\tret = ath11k_peer_rhash_remove(ab, ab-\u003erhead_peer_id, \u0026peer-\u003erhash_id,\ndrivers/net/wireless/ath/ath11k/peer.c-493-\t\t\t\t       \u0026ab-\u003erhash_peer_id_param);\n--\ndrivers/net/wireless/ath/ath11k/peer.c-502-\ndrivers/net/wireless/ath/ath11k/peer.c:503:static int ath11k_peer_rhash_id_tbl_init(struct ath11k_base *ab)\ndrivers/net/wireless/ath/ath11k/peer.c-504-{\n--\ndrivers/net/wireless/ath/ath11k/peer.c-524-\ndrivers/net/wireless/ath/ath11k/peer.c:525:\tparam-\u003ekey_offset = offsetof(struct ath11k_peer, peer_id);\ndrivers/net/wireless/ath/ath11k/peer.c:526:\tparam-\u003ehead_offset = offsetof(struct ath11k_peer, rhash_id);\ndrivers/net/wireless/ath/ath11k/peer.c:527:\tparam-\u003ekey_len = sizeof_field(struct ath11k_peer, peer_id);\ndrivers/net/wireless/ath/ath11k/peer.c-528-\tparam-\u003eautomatic_shrinking = true;\n--\ndrivers/net/wireless/ath/ath11k/peer.c-557-\ndrivers/net/wireless/ath/ath11k/peer.c:558:static int ath11k_peer_rhash_addr_tbl_init(struct ath11k_base *ab)\ndrivers/net/wireless/ath/ath11k/peer.c-559-{\n--\ndrivers/net/wireless/ath/ath11k/peer.c-579-\ndrivers/net/wireless/ath/ath11k/peer.c:580:\tparam-\u003ekey_offset = offsetof(struct ath11k_peer, addr);\ndrivers/net/wireless/ath/ath11k/peer.c:581:\tparam-\u003ehead_offset = offsetof(struct ath11k_peer, rhash_addr);\ndrivers/net/wireless/ath/ath11k/peer.c:582:\tparam-\u003ekey_len = sizeof_field(struct ath11k_peer, addr);\ndrivers/net/wireless/ath/ath11k/peer.c-583-\tparam-\u003eautomatic_shrinking = true;\n--\ndrivers/net/wireless/ath/ath11k/peer.c-612-\ndrivers/net/wireless/ath/ath11k/peer.c:613:static inline void ath11k_peer_rhash_id_tbl_destroy(struct ath11k_base *ab)\ndrivers/net/wireless/ath/ath11k/peer.c-614-{\n--\ndrivers/net/wireless/ath/ath11k/peer.c-624-\ndrivers/net/wireless/ath/ath11k/peer.c:625:static inline void ath11k_peer_rhash_addr_tbl_destroy(struct ath11k_base *ab)\ndrivers/net/wireless/ath/ath11k/peer.c-626-{\n--\ndrivers/net/wireless/ath/ath11k/peer.c-636-\ndrivers/net/wireless/ath/ath11k/peer.c:637:int ath11k_peer_rhash_tbl_init(struct ath11k_base *ab)\ndrivers/net/wireless/ath/ath11k/peer.c-638-{\n\n"
}

87/3 2026/10/03 16:12 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 53680
							output: 44
							thoughts: 52
						

Thoughts:
Okay, let's dive into this.

**Tracing Peer Allocation in ath11k**

Alright, I need to understand how the `peer` structure is being allocated within the `ath11k` driver, specifically within the context of peer creation. Let's start with `ath11k_peer_create` and related functions. I know that's where the magic happens, so I'm focusing my attention there. Specifically, I need to check lines 380-420 of `drivers/net/wireless/ath/ath11k/peer.c`. That should give me the core logic around the allocation itself. I'm looking for where and how the memory is grabbed, any initialization performed, and any potential allocation failures that might be handled. Knowing the exact allocation mechanism will be crucial for understanding potential memory management issues or potential race conditions down the line, given the critical importance of proper peer handling in this driver. I expect to find a `kmalloc` or similar call in that region; if it's more complex than that, I will be expecting some interesting details.



88/3 2026/10/03 16:12 tool read-file
0m Args:
{
  "File": "drivers/net/wireless/ath/ath11k/peer.c",
  "FirstLine": 375,
  "LineCount": 45
}

Results:
{
  "Contents": " 375:\t\tint ret, fbret;\n 376:\t\n 377:\t\tlockdep_assert_held(\u0026ar-\u003econf_mutex);\n 378:\t\n 379:\t\tif (ar-\u003enum_peers \u003e (ar-\u003emax_num_peers - 1)) {\n 380:\t\t\tath11k_warn(ar-\u003eab,\n 381:\t\t\t\t    \"failed to create peer due to insufficient peer entry resource in firmware\\n\");\n 382:\t\t\treturn -ENOBUFS;\n 383:\t\t}\n 384:\t\n 385:\t\tmutex_lock(\u0026ar-\u003eab-\u003etbl_mtx_lock);\n 386:\t\tspin_lock_bh(\u0026ar-\u003eab-\u003ebase_lock);\n 387:\t\tpeer = ath11k_peer_find_by_addr(ar-\u003eab, param-\u003epeer_addr);\n 388:\t\tif (peer) {\n 389:\t\t\tif (peer-\u003evdev_id == param-\u003evdev_id) {\n 390:\t\t\t\tspin_unlock_bh(\u0026ar-\u003eab-\u003ebase_lock);\n 391:\t\t\t\tmutex_unlock(\u0026ar-\u003eab-\u003etbl_mtx_lock);\n 392:\t\t\t\treturn -EINVAL;\n 393:\t\t\t}\n 394:\t\n 395:\t\t\t/* Assume sta is transitioning to another band.\n 396:\t\t\t * Remove here the peer from rhash.\n 397:\t\t\t */\n 398:\t\t\tath11k_peer_rhash_delete(ar-\u003eab, peer);\n 399:\t\t}\n 400:\t\tspin_unlock_bh(\u0026ar-\u003eab-\u003ebase_lock);\n 401:\t\tmutex_unlock(\u0026ar-\u003eab-\u003etbl_mtx_lock);\n 402:\t\n 403:\t\tret = ath11k_wmi_send_peer_create_cmd(ar, param);\n 404:\t\tif (ret) {\n 405:\t\t\tath11k_warn(ar-\u003eab,\n 406:\t\t\t\t    \"failed to send peer create vdev_id %d ret %d\\n\",\n 407:\t\t\t\t    param-\u003evdev_id, ret);\n 408:\t\t\treturn ret;\n 409:\t\t}\n 410:\t\n 411:\t\tret = ath11k_wait_for_peer_created(ar, param-\u003evdev_id,\n 412:\t\t\t\t\t\t   param-\u003epeer_addr);\n 413:\t\tif (ret)\n 414:\t\t\treturn ret;\n 415:\t\n 416:\t\tmutex_lock(\u0026ar-\u003eab-\u003etbl_mtx_lock);\n 417:\t\tspin_lock_bh(\u0026ar-\u003eab-\u003ebase_lock);\n 418:\t\n 419:\t\tpeer = ath11k_peer_find(ar-\u003eab, param-\u003evdev_id, param-\u003epeer_addr);\n"
}

89/3 2026/10/03 16:12 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 54757
							output: 44
							thoughts: 22
						

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

**Investigating Peer Allocation**

Okay, so I'm trying to trace down where this `peer` is actually allocated in the ath11k driver. My instinct is to zero in on the relevant event, and for this, I'm thinking the `ath11k_peer_map_event` function seems like a likely candidate. It’s the place to start drilling down. This function is likely responsible for mapping and handling peer related events.



90/3 2026/10/03 16:12 tool read-file
0m Args:
{
  "File": "drivers/net/wireless/ath/ath11k/peer.c",
  "FirstLine": 115,
  "LineCount": 40
}

Results:
{
  "Contents": " 115:\t\n 116:\texit:\n 117:\t\tspin_unlock_bh(\u0026ab-\u003ebase_lock);\n 118:\t}\n 119:\t\n 120:\tvoid ath11k_peer_map_event(struct ath11k_base *ab, u8 vdev_id, u16 peer_id,\n 121:\t\t\t\t   u8 *mac_addr, u16 ast_hash, u16 hw_peer_id)\n 122:\t{\n 123:\t\tstruct ath11k_peer *peer;\n 124:\t\n 125:\t\tspin_lock_bh(\u0026ab-\u003ebase_lock);\n 126:\t\tpeer = ath11k_peer_find(ab, vdev_id, mac_addr);\n 127:\t\tif (!peer) {\n 128:\t\t\tpeer = kzalloc_obj(*peer, GFP_ATOMIC);\n 129:\t\t\tif (!peer)\n 130:\t\t\t\tgoto exit;\n 131:\t\n 132:\t\t\tpeer-\u003evdev_id = vdev_id;\n 133:\t\t\tpeer-\u003epeer_id = peer_id;\n 134:\t\t\tpeer-\u003east_hash = ast_hash;\n 135:\t\t\tpeer-\u003ehw_peer_id = hw_peer_id;\n 136:\t\t\tether_addr_copy(peer-\u003eaddr, mac_addr);\n 137:\t\t\tlist_add(\u0026peer-\u003elist, \u0026ab-\u003epeers);\n 138:\t\t\twake_up(\u0026ab-\u003epeer_mapping_wq);\n 139:\t\t}\n 140:\t\n 141:\t\tath11k_dbg(ab, ATH11K_DBG_DP_HTT, \"peer map vdev %d peer %pM id %d\\n\",\n 142:\t\t\t   vdev_id, mac_addr, peer_id);\n 143:\t\n 144:\texit:\n 145:\t\tspin_unlock_bh(\u0026ab-\u003ebase_lock);\n 146:\t}\n 147:\t\n 148:\tstatic int ath11k_wait_for_peer_common(struct ath11k_base *ab, int vdev_id,\n 149:\t\t\t\t\t       const u8 *addr, bool expect_mapped)\n 150:\t{\n 151:\t\tint ret;\n 152:\t\n 153:\t\tret = wait_event_timeout(ab-\u003epeer_mapping_wq, ({\n 154:\t\t\t\t\tbool mapped;\n"
}

91/3 2026/10/03 16:12 llm kmsan-evaluator
0m Model:
gemini-3.8-flash

Args:
null

Results:
null

Tokens:
							input: 55595
							output: 457
							thoughts: 1213
						

Thoughts:
**Uninitialized Memory Risk Assessment for Ath11k Beacon Protection and Airtime Fairness Patch**

Okay, let's break down this patch and see if it introduces any uninitialized memory concerns. First, I see this patch is adding beacon protection and airtime fairness support to the ath11k driver, which involves enabling hardware ciphers for BIP, and also station airtime weight tracking with WMI updates to the firmware, along with exposing WMI services via debugfs.

My immediate thought is, are we potentially leaking uninitialized data to userspace, or are there any read-before-write issues popping up?  The first thing I notice is how memory is being handled. The key structures here – `ath11k_vif`, `ath11k_sta`, and `ath11k_peer` - are all zero-allocated using `kzalloc`. Any dynamically allocated buffers, like those in `ath11k_mac_atf_update`, use `kcalloc` or are initialized with designated initializers; which is good practice. The same goes for the WMI buffers – they are memset to zero. So, initial memory state seems to be consistently well-managed with a zero-state, eliminating the immediate risks of uninitialized reads.

Then I checked the code paths that could potentially leak data. The debugfs interface `ath11k_wmi_services_show` iterates through a bitmap, `svc_map`.  This map, part of the `ath11k_base` struct, is also zero-allocated. The index `i` (representing the WMI service) is printed via `seq_printf` after a `for_each_set_bit` loop. Since it's iterating based on set bits from a zeroed bitmap, this will not result in any uninitialized reads being passed to userspace.

Now, concerning the `airtime_weight`. This is initialized to `IEEE80211_DEFAULT_AIRTIME_WEIGHT` in the `ath11k_mac_op_sta_state` and also in mac80211's `sta_info.c`. That should be fine. It is later passed to the tracepoint, and that's the only potential leak, which does not appear to leak uninitialized memory.

Finally, regarding beacon parsing and other operations, the patch appears to operate on *existing* skb buffers.  So, any potential issues would likely be buffer over-reads, and that will be caught by KASAN – which is already a solid defense. No obvious introduction of new vulnerabilities here.

Thus, based on my analysis, I don't see any scenarios where uninitialized memory is read or leaked to userspace, or where uninitialized memory could cause a crash. The patch uses zero-allocation (`kzalloc`, `kcalloc`), memset, and explicit initialization, and the debugfs interface doesn't reveal any uninitialized data, and any buffer-related issues would be caught by KASAN.  So, I conclude that KMSAN is not specifically needed here.  KASAN should be sufficient to catch any subtle issues that might be present.



92/3 2026/10/03 16:12 tool set-results
0m Args:
{
  "KMSANReasoning": "The patch adds beacon protection and airtime fairness (ATF) support to the ath11k driver and mac80211 subsystem, expands supported cipher suites and key table indices, and exposes WMI services via debugfs.\n\nThere are no uninitialized memory risks or kernel-to-user info-leak vectors introduced:\n- All new struct fields (`beacon_prot` in `struct ath11k_vif`, `airtime_weight` in `struct ath11k_sta`, and the expanded `keys` array in `struct ath11k_peer`) are part of structures allocated via `kzalloc` (or explicitly cleared via `memset` in `ath11k_mac_op_sta_state`) and set to well-defined default constants (`IEEE80211_DEFAULT_AIRTIME_WEIGHT`).\n- In `ath11k_mac_atf_update()`, local structs use designated initializers (zeroing remaining fields) and buffers are allocated using `kcalloc`.\n- WMI command skbs are allocated using `ath11k_wmi_alloc_skb()`, which explicitly zeroes the buffer (`memset(skb-\u003edata, 0, round_len)`).\n- The debugfs attribute `ath11k_wmi_services_show()` iterates over `ab-\u003ewmi_ab.svc_map` (part of kzalloc'd `ath11k_base`) using `for_each_set_bit()` up to `WMI_MAX_EXT2_SERVICE` and prints bit indices; it does not read uninitialized data.\n- Beacon parsing in `ath11k_mac_bcn_prot_enabled()` parses IE buffers; any potential indexing issues or bounds errors would be out-of-bounds reads covered by KASAN.\n\nBecause the changes do not expose uninitialized memory reads or information leaks to userspace, a dedicated KMSAN fuzzing run is not justified; standard KASAN fuzzing is sufficient.",
  "NeedsKMSAN": false
}

Results:
{
  "KMSANReasoning": "The patch adds beacon protection and airtime fairness (ATF) support to the ath11k driver and mac80211 subsystem, expands supported cipher suites and key table indices, and exposes WMI services via debugfs.\n\nThere are no uninitialized memory risks or kernel-to-user info-leak vectors introduced:\n- All new struct fields (`beacon_prot` in `struct ath11k_vif`, `airtime_weight` in `struct ath11k_sta`, and the expanded `keys` array in `struct ath11k_peer`) are part of structures allocated via `kzalloc` (or explicitly cleared via `memset` in `ath11k_mac_op_sta_state`) and set to well-defined default constants (`IEEE80211_DEFAULT_AIRTIME_WEIGHT`).\n- In `ath11k_mac_atf_update()`, local structs use designated initializers (zeroing remaining fields) and buffers are allocated using `kcalloc`.\n- WMI command skbs are allocated using `ath11k_wmi_alloc_skb()`, which explicitly zeroes the buffer (`memset(skb-\u003edata, 0, round_len)`).\n- The debugfs attribute `ath11k_wmi_services_show()` iterates over `ab-\u003ewmi_ab.svc_map` (part of kzalloc'd `ath11k_base`) using `for_each_set_bit()` up to `WMI_MAX_EXT2_SERVICE` and prints bit indices; it does not read uninitialized data.\n- Beacon parsing in `ath11k_mac_bcn_prot_enabled()` parses IE buffers; any potential indexing issues or bounds errors would be out-of-bounds reads covered by KASAN.\n\nBecause the changes do not expose uninitialized memory reads or information leaks to userspace, a dedicated KMSAN fuzzing run is not justified; standard KASAN fuzzing is sufficient.",
  "NeedsKMSAN": 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)