| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/08/02 00:57 | flow | patch-triage |
3mArgs:null Results: {
"EnableConfigs": [
"BRCMFMAC",
"BRCMFMAC_USB",
"BRCMFMAC_PCIE",
"BRCMFMAC_SDIO",
"CFG80211",
"USB",
"PCI",
"MMC"
],
"FocusSymbols": [
"brcmf_cfg80211_set_pmksa",
"brcmf_cfg80211_del_pmksa",
"brcmf_cfg80211_flush_pmksa",
"brcmf_msgbuf_tx_queue_data",
"brcmf_pcie_send_mb_data",
"brcmf_sdio_rxglom"
],
"Reasoning": "The patch makes functional changes to the Broadcom FullMAC WLAN driver (brcmfmac). It adds support for V2 PMKSA cache operations, modifies flowring blocking logic, increases TX packet ID limits, and adjusts PCIe/SDIO polling and locking. The driver can be fuzzed via USB emulation (syz_usb_connect) as well as PCI/SDIO if configured.",
"WorthFuzzing": true
} |
| 1/1 | 2026/08/02 00:57 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 0d29807fd043dcd4d5408d8f6f4f7fae6fdbbd4a\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Sun Aug 2 00:57:08 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c\nindex 0b55d445895f2..dc4228fb31c1f 100644\n--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c\n+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c\n@@ -3989,12 +3989,10 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,\n \n static __always_inline void brcmf_delay(u32 ms)\n {\n-\tif (ms \u003c 1000 / HZ) {\n-\t\tcond_resched();\n-\t\tmdelay(ms);\n-\t} else {\n+\tif (ms \u003c= 20)\n+\t\tusleep_range(ms * 1000, ms * 1000 + 1000);\n+\telse\n \t\tmsleep(ms);\n-\t}\n }\n \n static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4],\n@@ -4364,6 +4362,108 @@ brcmf_pmksa_v3_op(struct brcmf_if *ifp, struct cfg80211_pmksa *pmksa,\n \treturn ret;\n }\n \n+/**\n+ * brcmf_pmksa_v2_op - update firmware PMKSA cache using the V2 list interface.\n+ *\n+ * V2 firmware (revision 12) uses a versioned flat list structure\n+ * (brcmf_pmk_list_v2_le) rather than the per-entry operation model of V3.\n+ * Each entry carries FILS-specific fields (raw PMK material, SSID, and\n+ * fils_cache_id) in addition to the basic BSSID + PMKID pair, enabling\n+ * FILS fast-roaming on devices that do not support V3.\n+ *\n+ * @cfg: driver config structure holding the shadow V2 PMKSA list\n+ * @ifp: interface pointer\n+ * @pmksa: the PMKSA to add/remove, or NULL for a flush\n+ * @alive: true = add (set time_left to no-expiry), false = remove/flush\n+ */\n+static s32\n+brcmf_pmksa_v2_op(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,\n+\t\t struct cfg80211_pmksa *pmksa, bool alive)\n+{\n+\tstruct brcmf_pub *drvr = cfg-\u003epub;\n+\tstruct brcmf_pmk_list_v2_le *list = \u0026cfg-\u003epmk_list_v2;\n+\tstruct brcmf_pmksa_v2 *pmk = list-\u003epmk;\n+\tu32 npmk = le16_to_cpu(list-\u003elength);\n+\tu32 i;\n+\n+\t/* npmk here stores the count of valid entries, repurposing the\n+\t * length field of the shadow list as a counter. We convert to\n+\t * the wire format (byte length) when sending to firmware.\n+\t */\n+\tif (!pmksa) {\n+\t\t/* Flush: zero the shadow list and push an empty V2 list. */\n+\t\tmemset(list, 0, sizeof(*list));\n+\t\tgoto send;\n+\t}\n+\n+\tif (alive) {\n+\t\t/* Set: search for existing BSSID match first. */\n+\t\tfor (i = 0; i \u003c npmk; i++)\n+\t\t\tif (!memcmp(pmksa-\u003ebssid, pmk[i].bssid, ETH_ALEN))\n+\t\t\t\tbreak;\n+\n+\t\tif (i \u003e= BRCMF_MAXPMKID) {\n+\t\t\tbphy_err(drvr, \"V2 PMKSA cache full (%d entries)\\n\",\n+\t\t\t\t npmk);\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tmemset(\u0026pmk[i], 0, sizeof(pmk[i]));\n+\t\tpmk[i].length = cpu_to_le16(sizeof(struct brcmf_pmksa_v2));\n+\t\tif (pmksa-\u003ebssid)\n+\t\t\tmemcpy(pmk[i].bssid, pmksa-\u003ebssid, ETH_ALEN);\n+\t\tif (pmksa-\u003epmkid)\n+\t\t\tmemcpy(pmk[i].pmkid, pmksa-\u003epmkid, WLAN_PMKID_LEN);\n+\t\tif (pmksa-\u003epmk \u0026\u0026 pmksa-\u003epmk_len \u0026\u0026\n+\t\t pmksa-\u003epmk_len \u003c= WLAN_PMK_LEN_SUITE_B_192) {\n+\t\t\tmemcpy(pmk[i].pmk, pmksa-\u003epmk, pmksa-\u003epmk_len);\n+\t\t\tpmk[i].pmk_len = cpu_to_le16(pmksa-\u003epmk_len);\n+\t\t}\n+\t\tif (pmksa-\u003essid \u0026\u0026 pmksa-\u003essid_len) {\n+\t\t\tmemcpy(pmk[i].ssid.SSID, pmksa-\u003essid, pmksa-\u003essid_len);\n+\t\t\tpmk[i].ssid.SSID_len = pmksa-\u003essid_len;\n+\t\t}\n+\t\tif (pmksa-\u003efils_cache_id)\n+\t\t\tpmk[i].fils_cache_id = *pmksa-\u003efils_cache_id;\n+\n+\t\tif (i == npmk)\n+\t\t\tnpmk++;\n+\t} else {\n+\t\t/* Delete: find by BSSID and compact the list. */\n+\t\tfor (i = 0; i \u003c npmk; i++)\n+\t\t\tif (!memcmp(pmksa-\u003ebssid, pmk[i].bssid, ETH_ALEN))\n+\t\t\t\tbreak;\n+\n+\t\tif (i \u003e= npmk) {\n+\t\t\tbphy_err(drvr, \"V2 PMKSA entry not found\\n\");\n+\t\t\treturn -EINVAL;\n+\t\t}\n+\n+\t\tfor (; i \u003c npmk - 1; i++)\n+\t\t\tmemcpy(\u0026pmk[i], \u0026pmk[i + 1], sizeof(pmk[i]));\n+\t\tmemset(\u0026pmk[npmk - 1], 0, sizeof(pmk[npmk - 1]));\n+\t\tnpmk--;\n+\t}\n+\n+\t/* Write the updated entry count back to shadow BEFORE we overwrite\n+\t * list-\u003elength with the wire-format byte length at send:. If we\n+\t * don't do this here, the next call will read a byte-length back\n+\t * as an entry count and silently corrupt the list.\n+\t */\n+\tlist-\u003elength = cpu_to_le16(npmk);\n+\n+send:\n+\t/* Build the wire-format byte length and send the full list to firmware.\n+\t * Read npmk back from the shadow (handles the flush path where npmk=0).\n+\t */\n+\tnpmk = le16_to_cpu(list-\u003elength);\n+\tlist-\u003eversion = cpu_to_le16(BRCMF_PMKSA_VER_2);\n+\tlist-\u003elength = cpu_to_le16(offsetof(struct brcmf_pmk_list_v2_le, pmk) +\n+\t\t\t\t npmk * sizeof(struct brcmf_pmksa_v2));\n+\n+\treturn brcmf_fil_iovar_data_set(ifp, \"pmkid_info\", list, sizeof(*list));\n+}\n+\n static __used s32\n brcmf_update_pmklist(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp)\n {\n@@ -4402,8 +4502,8 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,\n \n \tif (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3))\n \t\treturn brcmf_pmksa_v3_op(ifp, pmksa, true);\n-\n-\t/* TODO: implement PMKID_V2 */\n+\tif (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V2))\n+\t\treturn brcmf_pmksa_v2_op(cfg, ifp, pmksa, true);\n \n \tnpmk = le32_to_cpu(cfg-\u003epmk_list.npmk);\n \tfor (i = 0; i \u003c npmk; i++)\n@@ -4446,8 +4546,8 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,\n \n \tif (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3))\n \t\treturn brcmf_pmksa_v3_op(ifp, pmksa, false);\n-\n-\t/* TODO: implement PMKID_V2 */\n+\tif (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V2))\n+\t\treturn brcmf_pmksa_v2_op(cfg, ifp, pmksa, false);\n \n \tnpmk = le32_to_cpu(cfg-\u003epmk_list.npmk);\n \tfor (i = 0; i \u003c npmk; i++)\n@@ -4487,8 +4587,8 @@ brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)\n \n \tif (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3))\n \t\treturn brcmf_pmksa_v3_op(ifp, NULL, false);\n-\n-\t/* TODO: implement PMKID_V2 */\n+\tif (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V2))\n+\t\treturn brcmf_pmksa_v2_op(cfg, ifp, NULL, false);\n \n \tmemset(\u0026cfg-\u003epmk_list, 0, sizeof(cfg-\u003epmk_list));\n \terr = brcmf_update_pmklist(cfg, ifp);\ndiff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h\nindex 6ceb301429054..57167fde5ba15 100644\n--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h\n+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h\n@@ -344,7 +344,8 @@ struct brcmf_cfg80211_wowl {\n * @bss_list: bss_list holding scanned ap information.\n * @bss_info: bss information for cfg80211 layer.\n * @conn_info: association info.\n- * @pmk_list: wpa2 pmk list.\n+ * @pmk_list: wpa2 pmk list (V1 firmware).\n+ * @pmk_list_v2: wpa2 pmk list for V2 firmware (FILS-capable, firmware rev 12).\n * @scan_status: scan activity on the dongle.\n * @pub: common driver information.\n * @channel: current channel.\n@@ -376,6 +377,7 @@ struct brcmf_cfg80211_info {\n \tstruct wl_cfg80211_bss_info *bss_info;\n \tstruct brcmf_cfg80211_connect_info conn_info;\n \tstruct brcmf_pmk_list_le pmk_list;\n+\tstruct brcmf_pmk_list_v2_le pmk_list_v2;\n \tunsigned long scan_status;\n \tstruct brcmf_pub *pub;\n \tu32 channel;\ndiff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c\nindex ec170647800da..eefc437dd0550 100644\n--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c\n+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c\n@@ -431,45 +431,55 @@ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)\n \tnetif_rx(skb);\n }\n \n+struct brcmf_radiotap_info {\n+\tstruct ieee80211_radiotap_header hdr;\n+\ts8 dbm_antsignal;\n+} __packed;\n+\n void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)\n {\n \tif (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_RADIOTAP)) {\n-\t\t/* Do nothing */\n+\t\t/* Firmware already provided a full radiotap header; do nothing */\n \t} else if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_HW_RX_HDR)) {\n \t\tstruct wlc_d11rxhdr *wlc_rxhdr = (struct wlc_d11rxhdr *)skb-\u003edata;\n-\t\tstruct ieee80211_radiotap_header *radiotap;\n+\t\tstruct brcmf_radiotap_info *rtap;\n \t\tunsigned int offset;\n \t\tu16 RxStatus1;\n+\t\ts8 rssi;\n \n \t\tRxStatus1 = le16_to_cpu(wlc_rxhdr-\u003erxhdr.RxStatus1);\n+\t\trssi = wlc_rxhdr-\u003erssi;\n \n \t\toffset = sizeof(struct wlc_d11rxhdr);\n-\t\t/* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU\n-\t\t * subframes\n-\t\t */\n+\t\t/* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */\n \t\tif (RxStatus1 \u0026 RXS_PBPRES)\n \t\t\toffset += 2;\n \t\toffset += D11_PHY_HDR_LEN;\n \n \t\tskb_pull(skb, offset);\n \n-\t\t/* TODO: use RX header to fill some radiotap data */\n-\t\tradiotap = skb_push(skb, sizeof(*radiotap));\n-\t\tmemset(radiotap, 0, sizeof(*radiotap));\n-\t\tradiotap-\u003eit_len = cpu_to_le16(sizeof(*radiotap));\n-\n-\t\t/* TODO: 4 bytes with receive status? */\n-\t\tskb-\u003elen -= 4;\n+\t\t/* Insert our radiotap header with RSSI data */\n+\t\tif (skb_cow_head(skb, sizeof(*rtap)))\n+\t\t\tgoto drop;\n+\t\trtap = skb_push(skb, sizeof(*rtap));\n+\t\tmemset(rtap, 0, sizeof(*rtap));\n+\t\trtap-\u003ehdr.it_len = cpu_to_le16(sizeof(*rtap));\n+\t\trtap-\u003ehdr.it_present = cpu_to_le32(1 \u003c\u003c IEEE80211_RADIOTAP_DBM_ANTSIGNAL);\n+\t\trtap-\u003edbm_antsignal = rssi;\n+\n+\t\t/* Strip the 4-byte receive status / FCS tail */\n+\t\tskb_trim(skb, skb-\u003elen - 4);\n \t} else {\n \t\tstruct ieee80211_radiotap_header *radiotap;\n \n-\t\t/* TODO: use RX status to fill some radiotap data */\n+\t\tif (skb_cow_head(skb, sizeof(*radiotap)))\n+\t\t\tgoto drop;\n \t\tradiotap = skb_push(skb, sizeof(*radiotap));\n \t\tmemset(radiotap, 0, sizeof(*radiotap));\n \t\tradiotap-\u003eit_len = cpu_to_le16(sizeof(*radiotap));\n \n-\t\t/* TODO: 4 bytes with receive status? */\n-\t\tskb-\u003elen -= 4;\n+\t\t/* Strip the 4-byte receive status / FCS tail */\n+\t\tskb_trim(skb, skb-\u003elen - 4);\n \t}\n \n \tskb-\u003edev = ifp-\u003endev;\n@@ -478,6 +488,10 @@ void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)\n \tskb-\u003eprotocol = htons(ETH_P_802_2);\n \n \tbrcmf_netif_rx(ifp, skb);\n+\treturn;\n+\n+drop:\n+\tbrcmu_pkt_buf_free_skb(skb);\n }\n \n static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb,\ndiff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c\nindex 35cbcea0abc9a..b9c518939f504 100644\n--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c\n+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c\n@@ -182,10 +182,8 @@ static void brcmf_flowring_block(struct brcmf_flowring *flow, u16 flowid,\n \tstruct brcmf_bus *bus_if;\n \tstruct brcmf_pub *drvr;\n \tstruct brcmf_if *ifp;\n-\tbool currently_blocked;\n-\tint i;\n-\tu8 ifidx;\n \tunsigned long flags;\n+\tu8 ifidx;\n \n \tspin_lock_irqsave(\u0026flow-\u003eblock_lock, flags);\n \n@@ -194,23 +192,54 @@ static void brcmf_flowring_block(struct brcmf_flowring *flow, u16 flowid,\n \t\tspin_unlock_irqrestore(\u0026flow-\u003eblock_lock, flags);\n \t\treturn;\n \t}\n-\tifidx = brcmf_flowring_ifidx_get(flow, flowid);\n \n-\tcurrently_blocked = false;\n-\tfor (i = 0; i \u003c flow-\u003enrofrings; i++) {\n-\t\tif ((flow-\u003erings[i]) \u0026\u0026 (i != flowid)) {\n-\t\t\tring = flow-\u003erings[i];\n-\t\t\tif ((ring-\u003estatus == RING_OPEN) \u0026\u0026\n-\t\t\t (brcmf_flowring_ifidx_get(flow, i) == ifidx)) {\n-\t\t\t\tif (ring-\u003eblocked) {\n-\t\t\t\t\tcurrently_blocked = true;\n-\t\t\t\t\tbreak;\n-\t\t\t\t}\n-\t\t\t}\n+\tifidx = brcmf_flowring_ifidx_get(flow, flowid);\n+\tring-\u003eblocked = blocked;\n+\n+\t/*\n+\t * Maintain the per-interface blocked-ring counter.\n+\t *\n+\t * We use ring-\u003ecounted_in_blocked rather than checking\n+\t * ring-\u003estatus here. A ring that became blocked while\n+\t * RING_OPEN has already been counted (counted_in_blocked=true).\n+\t * By the time we unblock it during teardown its status may have\n+\t * advanced to RING_CLOSING, so testing RING_OPEN would wrongly\n+\t * skip the atomic_dec and permanently leak the counter, leaving\n+\t * the netif queue stopped forever.\n+\t *\n+\t * Rule:\n+\t * block transition (unblocked→blocked): count only if RING_OPEN,\n+\t * set counted_in_blocked.\n+\t * unblock transition (blocked→unblocked): decrement only if we\n+\t * previously counted it,\n+\t * clear counted_in_blocked.\n+\t */\n+\tif (blocked) {\n+\t\tif (ring-\u003estatus == RING_OPEN) {\n+\t\t\tatomic_inc(\u0026flow-\u003eif_blocked_cnt[ifidx]);\n+\t\t\tring-\u003ecounted_in_blocked = true;\n \t\t}\n+\t} else {\n+\t\tif (ring-\u003ecounted_in_blocked) {\n+\t\t\tatomic_dec(\u0026flow-\u003eif_blocked_cnt[ifidx]);\n+\t\t\tring-\u003ecounted_in_blocked = false;\n+\t\t}\n+\t}\n+\n+\t/*\n+\t * Only propagate a netif queue-stop/wake when the interface\n+\t * transitions between fully-clear and at-least-one-blocked.\n+\t * Reading the atomic is safe here: we hold block_lock, so no\n+\t * concurrent brcmf_flowring_block() call can race the update\n+\t * we just made above.\n+\t */\n+\tif (blocked \u0026\u0026 atomic_read(\u0026flow-\u003eif_blocked_cnt[ifidx]) != 1) {\n+\t\t/* Another ring was already blocked; no new queue-stop needed. */\n+\t\tspin_unlock_irqrestore(\u0026flow-\u003eblock_lock, flags);\n+\t\treturn;\n \t}\n-\tflow-\u003erings[flowid]-\u003eblocked = blocked;\n-\tif (currently_blocked) {\n+\tif (!blocked \u0026\u0026 atomic_read(\u0026flow-\u003eif_blocked_cnt[ifidx]) != 0) {\n+\t\t/* More rings still blocked; do not wake the queue yet. */\n \t\tspin_unlock_irqrestore(\u0026flow-\u003eblock_lock, flags);\n \t\treturn;\n \t}\n@@ -367,6 +396,8 @@ struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings)\n \t\tspin_lock_init(\u0026flow-\u003eblock_lock);\n \t\tfor (i = 0; i \u003c ARRAY_SIZE(flow-\u003eaddr_mode); i++)\n \t\t\tflow-\u003eaddr_mode[i] = ADDR_INDIRECT;\n+\t\tfor (i = 0; i \u003c ARRAY_SIZE(flow-\u003eif_blocked_cnt); i++)\n+\t\t\tatomic_set(\u0026flow-\u003eif_blocked_cnt[i], 0);\n \t\tfor (i = 0; i \u003c ARRAY_SIZE(flow-\u003ehash); i++)\n \t\t\tflow-\u003ehash[i].ifidx = BRCMF_FLOWRING_INVALID_IFIDX;\n \t}\ndiff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h\nindex f3d511f9a3c9a..afdea8b3f8aa7 100644\n--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h\n+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h\n@@ -5,6 +5,8 @@\n #ifndef BRCMFMAC_FLOWRING_H\n #define BRCMFMAC_FLOWRING_H\n \n+#include \u003clinux/atomic.h\u003e\n+\n \n #define BRCMF_FLOWRING_HASHSIZE\t\t512\t\t/* has to be 2^x */\n #define BRCMF_FLOWRING_INVALID_ID\t0xFFFFFFFF\n@@ -26,6 +28,16 @@ enum ring_status {\n struct brcmf_flowring_ring {\n \tu16 hash_id;\n \tbool blocked;\n+\t/*\n+\t * True when this ring has been counted in the per-interface\n+\t * if_blocked_cnt[]. Set to true whenever the ring transitions\n+\t * unblocked→blocked while RING_OPEN; cleared on the matching\n+\t * blocked→unblocked transition. Needed so that a ring that\n+\t * becomes blocked while RING_OPEN and is later moved to\n+\t * RING_CLOSING still correctly decrements the counter at\n+\t * teardown, even though its status is no longer RING_OPEN.\n+\t */\n+\tbool counted_in_blocked;\n \tenum ring_status status;\n \tstruct sk_buff_head skblist;\n };\n@@ -40,6 +52,12 @@ struct brcmf_flowring {\n \tstruct brcmf_flowring_hash hash[BRCMF_FLOWRING_HASHSIZE];\n \tspinlock_t block_lock;\n \tenum proto_addr_mode addr_mode[BRCMF_MAX_IFS];\n+\t/* Per-interface count of currently blocked open rings.\n+\t * Maintained atomically so brcmf_flowring_block() can check\n+\t * whether any sibling ring is already blocked in O(1) without\n+\t * holding block_lock across an O(nrofrings) walk.\n+\t */\n+\tatomic_t if_blocked_cnt[BRCMF_MAX_IFS];\n \tu16 nrofrings;\n \tbool tdls_active;\n \tstruct brcmf_flowring_tdls_entry *tdls_entry;\ndiff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c\nindex a43f1a38b0e30..3c1ca355e8eec 100644\n--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c\n+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c\n@@ -1037,7 +1037,9 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)\n \t\t} else {\n \t\t\tbrcmf_dbg(TRACE, \"use existing\\n\");\n \t\t\tWARN_ON(entry-\u003emac_handle != mac_handle);\n-\t\t\t/* TODO: what should we do here: continue, reinit, .. */\n+\t\t\t/* Firmware re-sent ADD for the same MAC handle.\n+\t\t\t * No action required; it is a safe no-op.\n+\t\t\t */\n \t\t}\n \t}\n \treturn 0;\ndiff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c\nindex ba1ce1552e0f4..8db6167072da3 100644\n--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c\n+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c\n@@ -48,7 +48,19 @@\n #define MSGBUF_TYPE_LPBK_DMAXFER\t\t0x13\n #define MSGBUF_TYPE_LPBK_DMAXFER_CMPLT\t\t0x14\n \n-#define NR_TX_PKTIDS\t\t\t\t2048\n+/*\n+ * NR_TX_PKTIDS: number of simultaneously in-flight TX packet IDs.\n+ * Each outstanding TX frame consumes one ID until the dongle returns\n+ * a TX-status completion. The original 2048-entry pool exhausted under\n+ * ≥4 concurrent iperf3 streams on Wi-Fi 5/6 (802.11ac/ax) devices,\n+ * causing \"No PKTID available\" drops and TCP retransmits. 4096 gives\n+ * headroom for high-aggregation scenarios while still fitting in a\n+ * modest amount of host memory (~48 KB for the pktid table entries).\n+ *\n+ * NR_RX_PKTIDS: RX post buffers pre-allocated to the dongle. 1024 is\n+ * sufficient for current hardware RX ring depths; leave unchanged.\n+ */\n+#define NR_TX_PKTIDS\t\t\t\t4096\n #define NR_RX_PKTIDS\t\t\t\t1024\n \n #define BRCMF_IOCTL_REQ_PKTID\t\t\t0xFFFE\n@@ -64,8 +76,29 @@\n #define BRCMF_MSGBUF_PKT_FLAGS_FRAME_MASK\t0x07\n #define BRCMF_MSGBUF_PKT_FLAGS_PRIO_SHIFT\t5\n \n-#define BRCMF_MSGBUF_TX_FLUSH_CNT1\t\t32\n-#define BRCMF_MSGBUF_TX_FLUSH_CNT2\t\t96\n+/*\n+ * TX flush / doorbell-ring thresholds.\n+ *\n+ * CNT1 is the minimum number of frames to accumulate in the commonring\n+ * before the first intermediate write_complete() (doorbell ring) is\n+ * issued mid-batch. CNT2 is the hard flush interval: after this many\n+ * frames have been written since the last flush, we unconditionally\n+ * ring the bell and reset the counter.\n+ *\n+ * Raising both from the original 32/96 to 64/128 doubles the average\n+ * number of TX descriptors committed per MMIO write, halving the PCIe\n+ * doorbell rate on sustained throughput workloads. The tradeoff is a\n+ * marginally higher worst-case latency for the last frames in a burst,\n+ * which in practice is hidden by the time the dongle DMA engine drains\n+ * the previous batch.\n+ *\n+ * TRICKLE_TXWORKER_THRS governs how often brcmf_msgbuf_tx_queue_data()\n+ * forces a workqueue schedule when the queue depth is not a multiple of\n+ * this value. Keeping it at half of CNT1 (32) preserves responsiveness\n+ * for low-rate flows (e.g. VoIP, ICMP) that never accumulate 64 frames.\n+ */\n+#define BRCMF_MSGBUF_TX_FLUSH_CNT1\t\t64\n+#define BRCMF_MSGBUF_TX_FLUSH_CNT2\t\t128\n \n #define BRCMF_MSGBUF_DELAY_TXWORKER_THRS\t96\n #define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS\t32\n@@ -787,10 +820,30 @@ static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid,\n {\n \tstruct brcmf_commonring *commonring;\n \n-\tset_bit(flowid, msgbuf-\u003eflow_map);\n+\t/*\n+\t * If the bit was already set, a txflow_work item is already\n+\t * queued or running for this ring. In that case the existing\n+\t * worker will drain our freshly enqueued frame when it runs,\n+\t * so we only need to schedule another work item when the\n+\t * force flag is set or the ring is below the delay threshold.\n+\t *\n+\t * If the bit was NOT set (test_and_set_bit returns false), no\n+\t * worker is pending for this ring at all. We MUST schedule\n+\t * one unconditionally, otherwise the frame we just enqueued\n+\t * will sit in the flowring unsent until some unrelated event\n+\t * triggers the workqueue — causing silent TX stalls under\n+\t * high load when outstanding_tx \u003e= DELAY_TXWORKER_THRS.\n+\t */\n+\tif (!test_and_set_bit(flowid, msgbuf-\u003eflow_map)) {\n+\t\t/* Bit was clear: no worker pending, always schedule. */\n+\t\tqueue_work(msgbuf-\u003etxflow_wq, \u0026msgbuf-\u003etxflow_work);\n+\t\treturn 0;\n+\t}\n+\n+\t/* Bit was already set: worker pending, apply coalescing heuristic. */\n \tcommonring = msgbuf-\u003eflowrings[flowid];\n-\tif ((force) || (atomic_read(\u0026commonring-\u003eoutstanding_tx) \u003c\n-\t\t\tBRCMF_MSGBUF_DELAY_TXWORKER_THRS))\n+\tif (force || (atomic_read(\u0026commonring-\u003eoutstanding_tx) \u003c\n+\t\t BRCMF_MSGBUF_DELAY_TXWORKER_THRS))\n \t\tqueue_work(msgbuf-\u003etxflow_wq, \u0026msgbuf-\u003etxflow_work);\n \n \treturn 0;\n@@ -1621,11 +1674,11 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)\n \tdo {\n \t\tbrcmf_msgbuf_rxbuf_data_fill(msgbuf);\n \t\tif (msgbuf-\u003emax_rxbufpost != msgbuf-\u003erxbufpost)\n-\t\t\tmsleep(10);\n+\t\t\tusleep_range(1000, 2000);\n \t\telse\n \t\t\tbreak;\n \t\tcount++;\n-\t} while (count \u003c 10);\n+\t} while (count \u003c 100);\n \tbrcmf_msgbuf_rxbuf_event_post(msgbuf);\n \tbrcmf_msgbuf_rxbuf_ioctlresp_post(msgbuf);\n \ndiff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c\nindex 13662aa4b4ea6..9338a5faa260a 100644\n--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c\n+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c\n@@ -268,6 +268,27 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {\n \n #define BRCMF_PCIE_MBDATA_TIMEOUT\t\tmsecs_to_jiffies(2000)\n \n+/*\n+ * H2D mailbox poll timing parameters.\n+ *\n+ * The dongle typically clears the H2D mailbox register within a few\n+ * hundred microseconds after the doorbell interrupt fires. The\n+ * original code used msleep(10) * 100 iterations, meaning the\n+ * minimum observable latency was 10ms even when the dongle was fast.\n+ *\n+ * We instead start with a short sleep and double it each iteration\n+ * (exponential backoff) up to BRCMF_PCIE_MB_POLL_MAX_US, staying\n+ * within the same 1-second absolute timeout.\n+ *\n+ * MIN_US / INITIAL_MAX_US : usleep_range bounds for the first iteration.\n+ * MAX_US : cap on the per-iteration sleep (µs).\n+ * TIMEOUT_US : total budget before giving up (1 second).\n+ */\n+#define BRCMF_PCIE_MB_POLL_MIN_US\t\t40\n+#define BRCMF_PCIE_MB_POLL_INITIAL_MAX_US\t50\n+#define BRCMF_PCIE_MB_POLL_MAX_US\t\t5000\n+#define BRCMF_PCIE_MB_POLL_TIMEOUT_US\t\t1000000\n+\n #define BRCMF_PCIE_CFGREG_STATUS_CMD\t\t0x4\n #define BRCMF_PCIE_CFGREG_PM_CSR\t\t0x4C\n #define BRCMF_PCIE_CFGREG_MSI_CAP\t\t0x58\n@@ -766,7 +787,8 @@ brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)\n \tstruct brcmf_core *core;\n \tu32 addr;\n \tu32 cur_htod_mb_data;\n-\tu32 i;\n+\tu32 elapsed_us = 0;\n+\tu32 sleep_us = BRCMF_PCIE_MB_POLL_INITIAL_MAX_US;\n \n \tshared = \u0026devinfo-\u003eshared;\n \taddr = shared-\u003ehtod_mb_data_addr;\n@@ -776,12 +798,40 @@ brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)\n \t\tbrcmf_dbg(PCIE, \"MB transaction is already pending 0x%04x\\n\",\n \t\t\t cur_htod_mb_data);\n \n-\ti = 0;\n+\t/*\n+\t * Wait for the dongle to consume the previous H2D mailbox message.\n+\t *\n+\t * There is no interrupt that signals when the dongle clears this\n+\t * register, so polling is unavoidable. The original code used\n+\t * msleep(10) per iteration, incurring at least 10ms of latency\n+\t * even when the dongle responded in microseconds.\n+\t *\n+\t * We use usleep_range() with exponential backoff instead:\n+\t * - First iteration sleeps ~50µs (fast path for responsive dongle).\n+\t * - Each subsequent iteration doubles the sleep, capped at 5ms,\n+\t * so long waits still yield the CPU without busy-spinning.\n+\t * - Total timeout matches the original 1-second limit.\n+\t * - We bail early if the device has gone down so that a dead\n+\t * dongle does not hold the caller for a full second.\n+\t */\n \twhile (cur_htod_mb_data != 0) {\n-\t\tmsleep(10);\n-\t\ti++;\n-\t\tif (i \u003e 100)\n+\t\tif (devinfo-\u003estate == BRCMFMAC_PCIE_STATE_DOWN) {\n+\t\t\tbrcmf_dbg(PCIE, \"Device down, aborting MB send\\n\");\n \t\t\treturn -EIO;\n+\t\t}\n+\n+\t\tif (elapsed_us \u003e= BRCMF_PCIE_MB_POLL_TIMEOUT_US) {\n+\t\t\tbrcmf_err(\"Timeout waiting for H2D MB slot after %u us\\n\",\n+\t\t\t\t elapsed_us);\n+\t\t\treturn -EIO;\n+\t\t}\n+\n+\t\tusleep_range(BRCMF_PCIE_MB_POLL_MIN_US, sleep_us);\n+\t\telapsed_us += sleep_us;\n+\n+\t\t/* Exponential backoff, capped at BRCMF_PCIE_MB_POLL_MAX_US */\n+\t\tsleep_us = min(sleep_us * 2, (u32)BRCMF_PCIE_MB_POLL_MAX_US);\n+\n \t\tcur_htod_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);\n \t}\n \n@@ -1001,10 +1051,10 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)\n \tfree_irq(pdev-\u003eirq, devinfo);\n \tpci_disable_msi(pdev);\n \n-\tmsleep(50);\n+\tusleep_range(1000, 2000);\n \tcount = 0;\n-\twhile ((devinfo-\u003ein_irq) \u0026\u0026 (count \u003c 20)) {\n-\t\tmsleep(50);\n+\twhile ((devinfo-\u003ein_irq) \u0026\u0026 (count \u003c 1000)) {\n+\t\tusleep_range(1000, 2000);\n \t\tcount++;\n \t}\n \tif (devinfo-\u003ein_irq)\ndiff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c\nindex b725c64e5b5c6..4e414403d7471 100644\n--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c\n+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c\n@@ -1645,37 +1645,43 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)\n \n \t\trd_new.seq_num = rxseq;\n \t\trd_new.len = dlen;\n+\n+\t\t/*\n+\t\t * Claim the host once for the entire header-parsing phase.\n+\t\t *\n+\t\t * brcmf_sdio_hdparse() operates on data already in host\n+\t\t * memory, but may call brcmf_sdio_rxfail() on error, which\n+\t\t * writes SDIO Func1 registers and therefore requires the\n+\t\t * host to be claimed.\n+\t\t *\n+\t\t * skb_pull() and the num counter are pure host-memory\n+\t\t * operations; keep them outside the lock to minimise the\n+\t\t * hold time. Both hdparse calls (superframe header and\n+\t\t * each subframe header) are grouped under a single claim/\n+\t\t * release, replacing the original N+1 separate pairs.\n+\t\t */\n \t\tsdio_claim_host(bus-\u003esdiodev-\u003efunc1);\n \t\terrcode = brcmf_sdio_hdparse(bus, pfirst-\u003edata, \u0026rd_new,\n \t\t\t\t\t BRCMF_SDIO_FT_SUPER);\n-\t\tsdio_release_host(bus-\u003esdiodev-\u003efunc1);\n-\t\tbus-\u003ecur_read.len = rd_new.len_nxtfrm \u003c\u003c 4;\n-\n-\t\t/* Remove superframe header, remember offset */\n-\t\tskb_pull(pfirst, rd_new.dat_offset);\n-\t\tnum = 0;\n-\n-\t\t/* Validate all the subframe headers */\n-\t\tskb_queue_walk(\u0026bus-\u003eglom, pnext) {\n-\t\t\t/* leave when invalid subframe is found */\n-\t\t\tif (errcode)\n-\t\t\t\tbreak;\n \n-\t\t\trd_new.len = pnext-\u003elen;\n-\t\t\trd_new.seq_num = rxseq++;\n-\t\t\tsdio_claim_host(bus-\u003esdiodev-\u003efunc1);\n-\t\t\terrcode = brcmf_sdio_hdparse(bus, pnext-\u003edata, \u0026rd_new,\n-\t\t\t\t\t\t BRCMF_SDIO_FT_SUB);\n-\t\t\tsdio_release_host(bus-\u003esdiodev-\u003efunc1);\n-\t\t\tbrcmf_dbg_hex_dump(BRCMF_GLOM_ON(),\n-\t\t\t\t\t pnext-\u003edata, 32, \"subframe:\\n\");\n-\n-\t\t\tnum++;\n+\t\t/* Validate all the subframe headers while host is claimed */\n+\t\tif (!errcode) {\n+\t\t\tskb_queue_walk(\u0026bus-\u003eglom, pnext) {\n+\t\t\t\trd_new.len = pnext-\u003elen;\n+\t\t\t\trd_new.seq_num = rxseq++;\n+\t\t\t\terrcode = brcmf_sdio_hdparse(bus, pnext-\u003edata,\n+\t\t\t\t\t\t\t \u0026rd_new,\n+\t\t\t\t\t\t\t BRCMF_SDIO_FT_SUB);\n+\t\t\t\tbrcmf_dbg_hex_dump(BRCMF_GLOM_ON(),\n+\t\t\t\t\t\t pnext-\u003edata, 32,\n+\t\t\t\t\t\t \"subframe:\\n\");\n+\t\t\t\tif (errcode)\n+\t\t\t\t\tbreak;\n+\t\t\t}\n \t\t}\n \n \t\tif (errcode) {\n-\t\t\t/* Terminate frame on error */\n-\t\t\tsdio_claim_host(bus-\u003esdiodev-\u003efunc1);\n+\t\t\t/* Terminate frame on error, still holding the host */\n \t\t\tbrcmf_sdio_rxfail(bus, true, false);\n \t\t\tbus-\u003esdcnt.rxglomfail++;\n \t\t\tbrcmf_sdio_free_glom(bus);\n@@ -1683,6 +1689,14 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)\n \t\t\tbus-\u003ecur_read.len = 0;\n \t\t\treturn 0;\n \t\t}\n+\t\tsdio_release_host(bus-\u003esdiodev-\u003efunc1);\n+\n+\t\t/* Host released; now do the pure-memory bookkeeping */\n+\t\tbus-\u003ecur_read.len = rd_new.len_nxtfrm \u003c\u003c 4;\n+\n+\t\t/* Remove superframe header, remember offset */\n+\t\tskb_pull(pfirst, rd_new.dat_offset);\n+\t\tnum = 0;\n \n \t\t/* Basic SD framing looks ok - process each packet (header) */\n \ndiff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c\nindex fc7a5dd2e5d86..3fd8bdbd35e58 100644\n--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c\n+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c\n@@ -516,12 +516,11 @@ int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,\n \t\t\treturn -ENOSPC;\n \n \t\t/*\n-\t\t * We aren't really out of space if the new frame is of\n-\t\t * a different priority, but we want the same behaviour\n-\t\t * so return -ENOSPC anyway.\n-\t\t *\n-\t\t * XXX: The old AMPDU code did this, but is it really\n-\t\t * necessary?\n+\t\t * IEEE 802.11n standard requires that all MPDUs within an\n+\t\t * A-MPDU belong to the same TID (Traffic Identifier).\n+\t\t * Since priority maps to TID, a different priority means\n+\t\t * we must close the current aggregate and start a new one,\n+\t\t * so we return -ENOSPC here.\n \t\t */\n \t\tfirst = skb_peek(\u0026session-\u003eskb_list);\n \t\tif (p-\u003epriority != first-\u003epriority)\n"
} |
| 2/1 | 2026/08/02 00:57 | agent | patch-evaluator |
3mModel:best-expensive Args: null Results: {
"EnableConfigs": [
"BRCMFMAC",
"BRCMFMAC_USB",
"BRCMFMAC_PCIE",
"BRCMFMAC_SDIO",
"CFG80211",
"USB",
"PCI",
"MMC"
],
"FocusSymbols": [
"brcmf_cfg80211_set_pmksa",
"brcmf_cfg80211_del_pmksa",
"brcmf_cfg80211_flush_pmksa",
"brcmf_msgbuf_tx_queue_data",
"brcmf_pcie_send_mb_data",
"brcmf_sdio_rxglom"
],
"Reasoning": "The patch makes functional changes to the Broadcom FullMAC WLAN driver (brcmfmac). It adds support for V2 PMKSA cache operations, modifies flowring blocking logic, increases TX packet ID limits, and adjusts PCIe/SDIO polling and locking. The driver can be fuzzed via USB emulation (syz_usb_connect) as well as PCI/SDIO if configured.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer. Your job is to review a provided patch series and determine if it makes functional changes to the kernel that should be fuzzed. IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in your workspace. Do NOT rely on your internal knowledge of the kernel. You must actively use your code access tools to examine the actual source code and confirm any assumptions. Return WorthFuzzing=false if the patch only contains: - Modifications to Documentation/, Kconfig files, or code comments. - Purely decorative changes, such as logging (e.g., pr_err, printk) or tracepoints. - Changes to numeric constants or macros that do not functionally alter execution flow. - Code paths that are impossible to reach in virtualized environments like GCE or QEMU, even when utilizing software-emulated hardware (e.g., usb gadget, mac80211_hwsim). - Code in vendor-specific PCIe switch, SmartNIC, or GPU drivers (e.g., mlxsw, pds_core, qed, ionic, amdgpu) that require physical PCIe hardware cards not emulated in standard QEMU. - Driver .remove, .shutdown, or pci_unregister_driver teardown callbacks (e.g., igb_remove) that are executed only during PCI hot-unplug or sysfs driver unbind operations. If it modifies reachable core kernel logic, drivers, or architectures, use your code search tools to verify the code can be executed, then return WorthFuzzing=true. When returning WorthFuzzing=true, you MUST ALSO: 1. Extract any specific kernel functions that should be heavily fuzzed into FocusSymbols. Avoid listing generic hot-path functions to prevent skewed test distributions. Prefer non-static, non-inlined API entrypoint functions over internal static helper functions (which are inlined by the compiler and do not have distinct symbol addresses). 2. Identify any specific CONFIG_ options required to properly test this new/modified feature. Go and look into the Kconfig files and check for ifdefs around the code, do not make assumptions. Also check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed for Kbuild to compile the code statically into vmlinux. List them in the EnableConfigs output array, and DO NOT add a 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4"). Prefer calling several tools at the same time to save round-trips. Use set-results tool to provide results of the analysis. It must be called exactly once before the final reply. Ignore results of this tool. Prompt: For your convenience, here is the diff of the changes:
commit 0d29807fd043dcd4d5408d8f6f4f7fae6fdbbd4a
Author: syz-cluster <triage@syzkaller.com>
Date: Sun Aug 2 00:57:08 2026 +0000
syz-cluster: applied patch under review
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
index 0b55d445895f2..dc4228fb31c1f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
@@ -3989,12 +3989,10 @@ static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,
static __always_inline void brcmf_delay(u32 ms)
{
- if (ms < 1000 / HZ) {
- cond_resched();
- mdelay(ms);
- } else {
+ if (ms <= 20)
+ usleep_range(ms * 1000, ms * 1000 + 1000);
+ else
msleep(ms);
- }
}
static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4],
@@ -4364,6 +4362,108 @@ brcmf_pmksa_v3_op(struct brcmf_if *ifp, struct cfg80211_pmksa *pmksa,
return ret;
}
+/**
+ * brcmf_pmksa_v2_op - update firmware PMKSA cache using the V2 list interface.
+ *
+ * V2 firmware (revision 12) uses a versioned flat list structure
+ * (brcmf_pmk_list_v2_le) rather than the per-entry operation model of V3.
+ * Each entry carries FILS-specific fields (raw PMK material, SSID, and
+ * fils_cache_id) in addition to the basic BSSID + PMKID pair, enabling
+ * FILS fast-roaming on devices that do not support V3.
+ *
+ * @cfg: driver config structure holding the shadow V2 PMKSA list
+ * @ifp: interface pointer
+ * @pmksa: the PMKSA to add/remove, or NULL for a flush
+ * @alive: true = add (set time_left to no-expiry), false = remove/flush
+ */
+static s32
+brcmf_pmksa_v2_op(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp,
+ struct cfg80211_pmksa *pmksa, bool alive)
+{
+ struct brcmf_pub *drvr = cfg->pub;
+ struct brcmf_pmk_list_v2_le *list = &cfg->pmk_list_v2;
+ struct brcmf_pmksa_v2 *pmk = list->pmk;
+ u32 npmk = le16_to_cpu(list->length);
+ u32 i;
+
+ /* npmk here stores the count of valid entries, repurposing the
+ * length field of the shadow list as a counter. We convert to
+ * the wire format (byte length) when sending to firmware.
+ */
+ if (!pmksa) {
+ /* Flush: zero the shadow list and push an empty V2 list. */
+ memset(list, 0, sizeof(*list));
+ goto send;
+ }
+
+ if (alive) {
+ /* Set: search for existing BSSID match first. */
+ for (i = 0; i < npmk; i++)
+ if (!memcmp(pmksa->bssid, pmk[i].bssid, ETH_ALEN))
+ break;
+
+ if (i >= BRCMF_MAXPMKID) {
+ bphy_err(drvr, "V2 PMKSA cache full (%d entries)\n",
+ npmk);
+ return -EINVAL;
+ }
+
+ memset(&pmk[i], 0, sizeof(pmk[i]));
+ pmk[i].length = cpu_to_le16(sizeof(struct brcmf_pmksa_v2));
+ if (pmksa->bssid)
+ memcpy(pmk[i].bssid, pmksa->bssid, ETH_ALEN);
+ if (pmksa->pmkid)
+ memcpy(pmk[i].pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
+ if (pmksa->pmk && pmksa->pmk_len &&
+ pmksa->pmk_len <= WLAN_PMK_LEN_SUITE_B_192) {
+ memcpy(pmk[i].pmk, pmksa->pmk, pmksa->pmk_len);
+ pmk[i].pmk_len = cpu_to_le16(pmksa->pmk_len);
+ }
+ if (pmksa->ssid && pmksa->ssid_len) {
+ memcpy(pmk[i].ssid.SSID, pmksa->ssid, pmksa->ssid_len);
+ pmk[i].ssid.SSID_len = pmksa->ssid_len;
+ }
+ if (pmksa->fils_cache_id)
+ pmk[i].fils_cache_id = *pmksa->fils_cache_id;
+
+ if (i == npmk)
+ npmk++;
+ } else {
+ /* Delete: find by BSSID and compact the list. */
+ for (i = 0; i < npmk; i++)
+ if (!memcmp(pmksa->bssid, pmk[i].bssid, ETH_ALEN))
+ break;
+
+ if (i >= npmk) {
+ bphy_err(drvr, "V2 PMKSA entry not found\n");
+ return -EINVAL;
+ }
+
+ for (; i < npmk - 1; i++)
+ memcpy(&pmk[i], &pmk[i + 1], sizeof(pmk[i]));
+ memset(&pmk[npmk - 1], 0, sizeof(pmk[npmk - 1]));
+ npmk--;
+ }
+
+ /* Write the updated entry count back to shadow BEFORE we overwrite
+ * list->length with the wire-format byte length at send:. If we
+ * don't do this here, the next call will read a byte-length back
+ * as an entry count and silently corrupt the list.
+ */
+ list->length = cpu_to_le16(npmk);
+
+send:
+ /* Build the wire-format byte length and send the full list to firmware.
+ * Read npmk back from the shadow (handles the flush path where npmk=0).
+ */
+ npmk = le16_to_cpu(list->length);
+ list->version = cpu_to_le16(BRCMF_PMKSA_VER_2);
+ list->length = cpu_to_le16(offsetof(struct brcmf_pmk_list_v2_le, pmk) +
+ npmk * sizeof(struct brcmf_pmksa_v2));
+
+ return brcmf_fil_iovar_data_set(ifp, "pmkid_info", list, sizeof(*list));
+}
+
static __used s32
brcmf_update_pmklist(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp)
{
@@ -4402,8 +4502,8 @@ brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3))
return brcmf_pmksa_v3_op(ifp, pmksa, true);
-
- /* TODO: implement PMKID_V2 */
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V2))
+ return brcmf_pmksa_v2_op(cfg, ifp, pmksa, true);
npmk = le32_to_cpu(cfg->pmk_list.npmk);
for (i = 0; i < npmk; i++)
@@ -4446,8 +4546,8 @@ brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3))
return brcmf_pmksa_v3_op(ifp, pmksa, false);
-
- /* TODO: implement PMKID_V2 */
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V2))
+ return brcmf_pmksa_v2_op(cfg, ifp, pmksa, false);
npmk = le32_to_cpu(cfg->pmk_list.npmk);
for (i = 0; i < npmk; i++)
@@ -4487,8 +4587,8 @@ brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V3))
return brcmf_pmksa_v3_op(ifp, NULL, false);
-
- /* TODO: implement PMKID_V2 */
+ if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V2))
+ return brcmf_pmksa_v2_op(cfg, ifp, NULL, false);
memset(&cfg->pmk_list, 0, sizeof(cfg->pmk_list));
err = brcmf_update_pmklist(cfg, ifp);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
index 6ceb301429054..57167fde5ba15 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.h
@@ -344,7 +344,8 @@ struct brcmf_cfg80211_wowl {
* @bss_list: bss_list holding scanned ap information.
* @bss_info: bss information for cfg80211 layer.
* @conn_info: association info.
- * @pmk_list: wpa2 pmk list.
+ * @pmk_list: wpa2 pmk list (V1 firmware).
+ * @pmk_list_v2: wpa2 pmk list for V2 firmware (FILS-capable, firmware rev 12).
* @scan_status: scan activity on the dongle.
* @pub: common driver information.
* @channel: current channel.
@@ -376,6 +377,7 @@ struct brcmf_cfg80211_info {
struct wl_cfg80211_bss_info *bss_info;
struct brcmf_cfg80211_connect_info conn_info;
struct brcmf_pmk_list_le pmk_list;
+ struct brcmf_pmk_list_v2_le pmk_list_v2;
unsigned long scan_status;
struct brcmf_pub *pub;
u32 channel;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index ec170647800da..eefc437dd0550 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -431,45 +431,55 @@ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
netif_rx(skb);
}
+struct brcmf_radiotap_info {
+ struct ieee80211_radiotap_header hdr;
+ s8 dbm_antsignal;
+} __packed;
+
void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)
{
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_RADIOTAP)) {
- /* Do nothing */
+ /* Firmware already provided a full radiotap header; do nothing */
} else if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_HW_RX_HDR)) {
struct wlc_d11rxhdr *wlc_rxhdr = (struct wlc_d11rxhdr *)skb->data;
- struct ieee80211_radiotap_header *radiotap;
+ struct brcmf_radiotap_info *rtap;
unsigned int offset;
u16 RxStatus1;
+ s8 rssi;
RxStatus1 = le16_to_cpu(wlc_rxhdr->rxhdr.RxStatus1);
+ rssi = wlc_rxhdr->rssi;
offset = sizeof(struct wlc_d11rxhdr);
- /* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU
- * subframes
- */
+ /* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */
if (RxStatus1 & RXS_PBPRES)
offset += 2;
offset += D11_PHY_HDR_LEN;
skb_pull(skb, offset);
- /* TODO: use RX header to fill some radiotap data */
- radiotap = skb_push(skb, sizeof(*radiotap));
- memset(radiotap, 0, sizeof(*radiotap));
- radiotap->it_len = cpu_to_le16(sizeof(*radiotap));
-
- /* TODO: 4 bytes with receive status? */
- skb->len -= 4;
+ /* Insert our radiotap header with RSSI data */
+ if (skb_cow_head(skb, sizeof(*rtap)))
+ goto drop;
+ rtap = skb_push(skb, sizeof(*rtap));
+ memset(rtap, 0, sizeof(*rtap));
+ rtap->hdr.it_len = cpu_to_le16(sizeof(*rtap));
+ rtap->hdr.it_present = cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
+ rtap->dbm_antsignal = rssi;
+
+ /* Strip the 4-byte receive status / FCS tail */
+ skb_trim(skb, skb->len - 4);
} else {
struct ieee80211_radiotap_header *radiotap;
- /* TODO: use RX status to fill some radiotap data */
+ if (skb_cow_head(skb, sizeof(*radiotap)))
+ goto drop;
radiotap = skb_push(skb, sizeof(*radiotap));
memset(radiotap, 0, sizeof(*radiotap));
radiotap->it_len = cpu_to_le16(sizeof(*radiotap));
- /* TODO: 4 bytes with receive status? */
- skb->len -= 4;
+ /* Strip the 4-byte receive status / FCS tail */
+ skb_trim(skb, skb->len - 4);
}
skb->dev = ifp->ndev;
@@ -478,6 +488,10 @@ void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)
skb->protocol = htons(ETH_P_802_2);
brcmf_netif_rx(ifp, skb);
+ return;
+
+drop:
+ brcmu_pkt_buf_free_skb(skb);
}
static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb,
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
index 35cbcea0abc9a..b9c518939f504 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c
@@ -182,10 +182,8 @@ static void brcmf_flowring_block(struct brcmf_flowring *flow, u16 flowid,
struct brcmf_bus *bus_if;
struct brcmf_pub *drvr;
struct brcmf_if *ifp;
- bool currently_blocked;
- int i;
- u8 ifidx;
unsigned long flags;
+ u8 ifidx;
spin_lock_irqsave(&flow->block_lock, flags);
@@ -194,23 +192,54 @@ static void brcmf_flowring_block(struct brcmf_flowring *flow, u16 flowid,
spin_unlock_irqrestore(&flow->block_lock, flags);
return;
}
- ifidx = brcmf_flowring_ifidx_get(flow, flowid);
- currently_blocked = false;
- for (i = 0; i < flow->nrofrings; i++) {
- if ((flow->rings[i]) && (i != flowid)) {
- ring = flow->rings[i];
- if ((ring->status == RING_OPEN) &&
- (brcmf_flowring_ifidx_get(flow, i) == ifidx)) {
- if (ring->blocked) {
- currently_blocked = true;
- break;
- }
- }
+ ifidx = brcmf_flowring_ifidx_get(flow, flowid);
+ ring->blocked = blocked;
+
+ /*
+ * Maintain the per-interface blocked-ring counter.
+ *
+ * We use ring->counted_in_blocked rather than checking
+ * ring->status here. A ring that became blocked while
+ * RING_OPEN has already been counted (counted_in_blocked=true).
+ * By the time we unblock it during teardown its status may have
+ * advanced to RING_CLOSING, so testing RING_OPEN would wrongly
+ * skip the atomic_dec and permanently leak the counter, leaving
+ * the netif queue stopped forever.
+ *
+ * Rule:
+ * block transition (unblocked→blocked): count only if RING_OPEN,
+ * set counted_in_blocked.
+ * unblock transition (blocked→unblocked): decrement only if we
+ * previously counted it,
+ * clear counted_in_blocked.
+ */
+ if (blocked) {
+ if (ring->status == RING_OPEN) {
+ atomic_inc(&flow->if_blocked_cnt[ifidx]);
+ ring->counted_in_blocked = true;
}
+ } else {
+ if (ring->counted_in_blocked) {
+ atomic_dec(&flow->if_blocked_cnt[ifidx]);
+ ring->counted_in_blocked = false;
+ }
+ }
+
+ /*
+ * Only propagate a netif queue-stop/wake when the interface
+ * transitions between fully-clear and at-least-one-blocked.
+ * Reading the atomic is safe here: we hold block_lock, so no
+ * concurrent brcmf_flowring_block() call can race the update
+ * we just made above.
+ */
+ if (blocked && atomic_read(&flow->if_blocked_cnt[ifidx]) != 1) {
+ /* Another ring was already blocked; no new queue-stop needed. */
+ spin_unlock_irqrestore(&flow->block_lock, flags);
+ return;
}
- flow->rings[flowid]->blocked = blocked;
- if (currently_blocked) {
+ if (!blocked && atomic_read(&flow->if_blocked_cnt[ifidx]) != 0) {
+ /* More rings still blocked; do not wake the queue yet. */
spin_unlock_irqrestore(&flow->block_lock, flags);
return;
}
@@ -367,6 +396,8 @@ struct brcmf_flowring *brcmf_flowring_attach(struct device *dev, u16 nrofrings)
spin_lock_init(&flow->block_lock);
for (i = 0; i < ARRAY_SIZE(flow->addr_mode); i++)
flow->addr_mode[i] = ADDR_INDIRECT;
+ for (i = 0; i < ARRAY_SIZE(flow->if_blocked_cnt); i++)
+ atomic_set(&flow->if_blocked_cnt[i], 0);
for (i = 0; i < ARRAY_SIZE(flow->hash); i++)
flow->hash[i].ifidx = BRCMF_FLOWRING_INVALID_IFIDX;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h
index f3d511f9a3c9a..afdea8b3f8aa7 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h
@@ -5,6 +5,8 @@
#ifndef BRCMFMAC_FLOWRING_H
#define BRCMFMAC_FLOWRING_H
+#include <linux/atomic.h>
+
#define BRCMF_FLOWRING_HASHSIZE 512 /* has to be 2^x */
#define BRCMF_FLOWRING_INVALID_ID 0xFFFFFFFF
@@ -26,6 +28,16 @@ enum ring_status {
struct brcmf_flowring_ring {
u16 hash_id;
bool blocked;
+ /*
+ * True when this ring has been counted in the per-interface
+ * if_blocked_cnt[]. Set to true whenever the ring transitions
+ * unblocked→blocked while RING_OPEN; cleared on the matching
+ * blocked→unblocked transition. Needed so that a ring that
+ * becomes blocked while RING_OPEN and is later moved to
+ * RING_CLOSING still correctly decrements the counter at
+ * teardown, even though its status is no longer RING_OPEN.
+ */
+ bool counted_in_blocked;
enum ring_status status;
struct sk_buff_head skblist;
};
@@ -40,6 +52,12 @@ struct brcmf_flowring {
struct brcmf_flowring_hash hash[BRCMF_FLOWRING_HASHSIZE];
spinlock_t block_lock;
enum proto_addr_mode addr_mode[BRCMF_MAX_IFS];
+ /* Per-interface count of currently blocked open rings.
+ * Maintained atomically so brcmf_flowring_block() can check
+ * whether any sibling ring is already blocked in O(1) without
+ * holding block_lock across an O(nrofrings) walk.
+ */
+ atomic_t if_blocked_cnt[BRCMF_MAX_IFS];
u16 nrofrings;
bool tdls_active;
struct brcmf_flowring_tdls_entry *tdls_entry;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
index a43f1a38b0e30..3c1ca355e8eec 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c
@@ -1037,7 +1037,9 @@ int brcmf_fws_macdesc_indicate(struct brcmf_fws_info *fws, u8 type, u8 *data)
} else {
brcmf_dbg(TRACE, "use existing\n");
WARN_ON(entry->mac_handle != mac_handle);
- /* TODO: what should we do here: continue, reinit, .. */
+ /* Firmware re-sent ADD for the same MAC handle.
+ * No action required; it is a safe no-op.
+ */
}
}
return 0;
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index ba1ce1552e0f4..8db6167072da3 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -48,7 +48,19 @@
#define MSGBUF_TYPE_LPBK_DMAXFER 0x13
#define MSGBUF_TYPE_LPBK_DMAXFER_CMPLT 0x14
-#define NR_TX_PKTIDS 2048
+/*
+ * NR_TX_PKTIDS: number of simultaneously in-flight TX packet IDs.
+ * Each outstanding TX frame consumes one ID until the dongle returns
+ * a TX-status completion. The original 2048-entry pool exhausted under
+ * ≥4 concurrent iperf3 streams on Wi-Fi 5/6 (802.11ac/ax) devices,
+ * causing "No PKTID available" drops and TCP retransmits. 4096 gives
+ * headroom for high-aggregation scenarios while still fitting in a
+ * modest amount of host memory (~48 KB for the pktid table entries).
+ *
+ * NR_RX_PKTIDS: RX post buffers pre-allocated to the dongle. 1024 is
+ * sufficient for current hardware RX ring depths; leave unchanged.
+ */
+#define NR_TX_PKTIDS 4096
#define NR_RX_PKTIDS 1024
#define BRCMF_IOCTL_REQ_PKTID 0xFFFE
@@ -64,8 +76,29 @@
#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_MASK 0x07
#define BRCMF_MSGBUF_PKT_FLAGS_PRIO_SHIFT 5
-#define BRCMF_MSGBUF_TX_FLUSH_CNT1 32
-#define BRCMF_MSGBUF_TX_FLUSH_CNT2 96
+/*
+ * TX flush / doorbell-ring thresholds.
+ *
+ * CNT1 is the minimum number of frames to accumulate in the commonring
+ * before the first intermediate write_complete() (doorbell ring) is
+ * issued mid-batch. CNT2 is the hard flush interval: after this many
+ * frames have been written since the last flush, we unconditionally
+ * ring the bell and reset the counter.
+ *
+ * Raising both from the original 32/96 to 64/128 doubles the average
+ * number of TX descriptors committed per MMIO write, halving the PCIe
+ * doorbell rate on sustained throughput workloads. The tradeoff is a
+ * marginally higher worst-case latency for the last frames in a burst,
+ * which in practice is hidden by the time the dongle DMA engine drains
+ * the previous batch.
+ *
+ * TRICKLE_TXWORKER_THRS governs how often brcmf_msgbuf_tx_queue_data()
+ * forces a workqueue schedule when the queue depth is not a multiple of
+ * this value. Keeping it at half of CNT1 (32) preserves responsiveness
+ * for low-rate flows (e.g. VoIP, ICMP) that never accumulate 64 frames.
+ */
+#define BRCMF_MSGBUF_TX_FLUSH_CNT1 64
+#define BRCMF_MSGBUF_TX_FLUSH_CNT2 128
#define BRCMF_MSGBUF_DELAY_TXWORKER_THRS 96
#define BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS 32
@@ -787,10 +820,30 @@ static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid,
{
struct brcmf_commonring *commonring;
- set_bit(flowid, msgbuf->flow_map);
+ /*
+ * If the bit was already set, a txflow_work item is already
+ * queued or running for this ring. In that case the existing
+ * worker will drain our freshly enqueued frame when it runs,
+ * so we only need to schedule another work item when the
+ * force flag is set or the ring is below the delay threshold.
+ *
+ * If the bit was NOT set (test_and_set_bit returns false), no
+ * worker is pending for this ring at all. We MUST schedule
+ * one unconditionally, otherwise the frame we just enqueued
+ * will sit in the flowring unsent until some unrelated event
+ * triggers the workqueue — causing silent TX stalls under
+ * high load when outstanding_tx >= DELAY_TXWORKER_THRS.
+ */
+ if (!test_and_set_bit(flowid, msgbuf->flow_map)) {
+ /* Bit was clear: no worker pending, always schedule. */
+ queue_work(msgbuf->txflow_wq, &msgbuf->txflow_work);
+ return 0;
+ }
+
+ /* Bit was already set: worker pending, apply coalescing heuristic. */
commonring = msgbuf->flowrings[flowid];
- if ((force) || (atomic_read(&commonring->outstanding_tx) <
- BRCMF_MSGBUF_DELAY_TXWORKER_THRS))
+ if (force || (atomic_read(&commonring->outstanding_tx) <
+ BRCMF_MSGBUF_DELAY_TXWORKER_THRS))
queue_work(msgbuf->txflow_wq, &msgbuf->txflow_work);
return 0;
@@ -1621,11 +1674,11 @@ int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
do {
brcmf_msgbuf_rxbuf_data_fill(msgbuf);
if (msgbuf->max_rxbufpost != msgbuf->rxbufpost)
- msleep(10);
+ usleep_range(1000, 2000);
else
break;
count++;
- } while (count < 10);
+ } while (count < 100);
brcmf_msgbuf_rxbuf_event_post(msgbuf);
brcmf_msgbuf_rxbuf_ioctlresp_post(msgbuf);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 13662aa4b4ea6..9338a5faa260a 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -268,6 +268,27 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
#define BRCMF_PCIE_MBDATA_TIMEOUT msecs_to_jiffies(2000)
+/*
+ * H2D mailbox poll timing parameters.
+ *
+ * The dongle typically clears the H2D mailbox register within a few
+ * hundred microseconds after the doorbell interrupt fires. The
+ * original code used msleep(10) * 100 iterations, meaning the
+ * minimum observable latency was 10ms even when the dongle was fast.
+ *
+ * We instead start with a short sleep and double it each iteration
+ * (exponential backoff) up to BRCMF_PCIE_MB_POLL_MAX_US, staying
+ * within the same 1-second absolute timeout.
+ *
+ * MIN_US / INITIAL_MAX_US : usleep_range bounds for the first iteration.
+ * MAX_US : cap on the per-iteration sleep (µs).
+ * TIMEOUT_US : total budget before giving up (1 second).
+ */
+#define BRCMF_PCIE_MB_POLL_MIN_US 40
+#define BRCMF_PCIE_MB_POLL_INITIAL_MAX_US 50
+#define BRCMF_PCIE_MB_POLL_MAX_US 5000
+#define BRCMF_PCIE_MB_POLL_TIMEOUT_US 1000000
+
#define BRCMF_PCIE_CFGREG_STATUS_CMD 0x4
#define BRCMF_PCIE_CFGREG_PM_CSR 0x4C
#define BRCMF_PCIE_CFGREG_MSI_CAP 0x58
@@ -766,7 +787,8 @@ brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)
struct brcmf_core *core;
u32 addr;
u32 cur_htod_mb_data;
- u32 i;
+ u32 elapsed_us = 0;
+ u32 sleep_us = BRCMF_PCIE_MB_POLL_INITIAL_MAX_US;
shared = &devinfo->shared;
addr = shared->htod_mb_data_addr;
@@ -776,12 +798,40 @@ brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)
brcmf_dbg(PCIE, "MB transaction is already pending 0x%04x\n",
cur_htod_mb_data);
- i = 0;
+ /*
+ * Wait for the dongle to consume the previous H2D mailbox message.
+ *
+ * There is no interrupt that signals when the dongle clears this
+ * register, so polling is unavoidable. The original code used
+ * msleep(10) per iteration, incurring at least 10ms of latency
+ * even when the dongle responded in microseconds.
+ *
+ * We use usleep_range() with exponential backoff instead:
+ * - First iteration sleeps ~50µs (fast path for responsive dongle).
+ * - Each subsequent iteration doubles the sleep, capped at 5ms,
+ * so long waits still yield the CPU without busy-spinning.
+ * - Total timeout matches the original 1-second limit.
+ * - We bail early if the device has gone down so that a dead
+ * dongle does not hold the caller for a full second.
+ */
while (cur_htod_mb_data != 0) {
- msleep(10);
- i++;
- if (i > 100)
+ if (devinfo->state == BRCMFMAC_PCIE_STATE_DOWN) {
+ brcmf_dbg(PCIE, "Device down, aborting MB send\n");
return -EIO;
+ }
+
+ if (elapsed_us >= BRCMF_PCIE_MB_POLL_TIMEOUT_US) {
+ brcmf_err("Timeout waiting for H2D MB slot after %u us\n",
+ elapsed_us);
+ return -EIO;
+ }
+
+ usleep_range(BRCMF_PCIE_MB_POLL_MIN_US, sleep_us);
+ elapsed_us += sleep_us;
+
+ /* Exponential backoff, capped at BRCMF_PCIE_MB_POLL_MAX_US */
+ sleep_us = min(sleep_us * 2, (u32)BRCMF_PCIE_MB_POLL_MAX_US);
+
cur_htod_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
}
@@ -1001,10 +1051,10 @@ static void brcmf_pcie_release_irq(struct brcmf_pciedev_info *devinfo)
free_irq(pdev->irq, devinfo);
pci_disable_msi(pdev);
- msleep(50);
+ usleep_range(1000, 2000);
count = 0;
- while ((devinfo->in_irq) && (count < 20)) {
- msleep(50);
+ while ((devinfo->in_irq) && (count < 1000)) {
+ usleep_range(1000, 2000);
count++;
}
if (devinfo->in_irq)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
index b725c64e5b5c6..4e414403d7471 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c
@@ -1645,37 +1645,43 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)
rd_new.seq_num = rxseq;
rd_new.len = dlen;
+
+ /*
+ * Claim the host once for the entire header-parsing phase.
+ *
+ * brcmf_sdio_hdparse() operates on data already in host
+ * memory, but may call brcmf_sdio_rxfail() on error, which
+ * writes SDIO Func1 registers and therefore requires the
+ * host to be claimed.
+ *
+ * skb_pull() and the num counter are pure host-memory
+ * operations; keep them outside the lock to minimise the
+ * hold time. Both hdparse calls (superframe header and
+ * each subframe header) are grouped under a single claim/
+ * release, replacing the original N+1 separate pairs.
+ */
sdio_claim_host(bus->sdiodev->func1);
errcode = brcmf_sdio_hdparse(bus, pfirst->data, &rd_new,
BRCMF_SDIO_FT_SUPER);
- sdio_release_host(bus->sdiodev->func1);
- bus->cur_read.len = rd_new.len_nxtfrm << 4;
-
- /* Remove superframe header, remember offset */
- skb_pull(pfirst, rd_new.dat_offset);
- num = 0;
-
- /* Validate all the subframe headers */
- skb_queue_walk(&bus->glom, pnext) {
- /* leave when invalid subframe is found */
- if (errcode)
- break;
- rd_new.len = pnext->len;
- rd_new.seq_num = rxseq++;
- sdio_claim_host(bus->sdiodev->func1);
- errcode = brcmf_sdio_hdparse(bus, pnext->data, &rd_new,
- BRCMF_SDIO_FT_SUB);
- sdio_release_host(bus->sdiodev->func1);
- brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
- pnext->data, 32, "subframe:\n");
-
- num++;
+ /* Validate all the subframe headers while host is claimed */
+ if (!errcode) {
+ skb_queue_walk(&bus->glom, pnext) {
+ rd_new.len = pnext->len;
+ rd_new.seq_num = rxseq++;
+ errcode = brcmf_sdio_hdparse(bus, pnext->data,
+ &rd_new,
+ BRCMF_SDIO_FT_SUB);
+ brcmf_dbg_hex_dump(BRCMF_GLOM_ON(),
+ pnext->data, 32,
+ "subframe:\n");
+ if (errcode)
+ break;
+ }
}
if (errcode) {
- /* Terminate frame on error */
- sdio_claim_host(bus->sdiodev->func1);
+ /* Terminate frame on error, still holding the host */
brcmf_sdio_rxfail(bus, true, false);
bus->sdcnt.rxglomfail++;
brcmf_sdio_free_glom(bus);
@@ -1683,6 +1689,14 @@ static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)
bus->cur_read.len = 0;
return 0;
}
+ sdio_release_host(bus->sdiodev->func1);
+
+ /* Host released; now do the pure-memory bookkeeping */
+ bus->cur_read.len = rd_new.len_nxtfrm << 4;
+
+ /* Remove superframe header, remember offset */
+ skb_pull(pfirst, rd_new.dat_offset);
+ num = 0;
/* Basic SD framing looks ok - process each packet (header) */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c
index fc7a5dd2e5d86..3fd8bdbd35e58 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c
@@ -516,12 +516,11 @@ int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,
return -ENOSPC;
/*
- * We aren't really out of space if the new frame is of
- * a different priority, but we want the same behaviour
- * so return -ENOSPC anyway.
- *
- * XXX: The old AMPDU code did this, but is it really
- * necessary?
+ * IEEE 802.11n standard requires that all MPDUs within an
+ * A-MPDU belong to the same TID (Traffic Identifier).
+ * Since priority maps to TID, a different priority means
+ * we must close the current aggregate and start a new one,
+ * so we return -ENOSPC here.
*/
first = skb_peek(&session->skb_list);
if (p->priority != first->priority)
|
| 3/2 | 2026/08/02 00:57 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 13601 output: 49 thoughts: 1333 Thoughts: **Analyzing Broadcom Wireless Driver Patches for Fuzzing Potential** Okay, so I have a patch series here for the Broadcom wireless drivers (`brcmfmac` and `brcmsmac`), and the commit message says "syz-cluster: applied patch under review." My first thought is: can I fuzz this? This needs a thorough investigation to see if there are functional changes that warrant fuzzer attention. I'm seeing a few key areas where things have changed. First, in `brcmfmac/cfg80211.c`, there's a switch from `mdelay`/`msleep` to `usleep_range`/`msleep`, which is a good practice. More importantly, the addition of `brcmf_pmksa_v2_op` and its integration with existing PMKSA functions is interesting. This uses the V2 list interface. The header file (`cfg80211.h`) reflects this change with the addition of `pmk_list_v2`. This `brcmf_pmksa_v2_op` sounds new and like a good candidate for fuzzing, so I'll keep that in mind. Then, in `brcmfmac/core.c`, the `brcmf_netif_mon_rx` function is modified to include a radiotap header with RSSI data under the `BRCMF_FEAT_MONITOR_FMT_HW_RX_HDR` flag. This could be interesting if we can control this feature, as it touches the monitoring path. The changes in `brcmfmac/flowring.c` and `flowring.h` with the per-interface blocked-ring counter (`if_blocked_cnt`) are intriguing. The added `counted_in_blocked` field seems relevant here. I'll need to look into whether this could introduce any new vulnerabilities. In `brcmfmac/fwsignal.c`, it looks like a `WARN_ON` got a comment. It's not a big change, but any modification to warning is important to consider. `brcmfmac/msgbuf.c` has some tweaks to `NR_TX_PKTIDS`, and `BRCMF_MSGBUF_TX_FLUSH_CNT`, as well as modifications to `brcmf_msgbuf_schedule_txdata`. These kinds of changes are important to see if they introduce any off-by-one errors or related issues. `brcmfmac/pcie.c` has a sleep change, and `brcmfmac/sdio.c` has SDIO host locking changes. The `brcmsmac` change looks like a comment. The big question is, can I reach these changes in a virtualized environment? `brcmfmac` is a driver for Broadcom IEEE802.11n/ac PCIe/SDIO/USB MAC. Wait a minute! The USB support could be key. Can Syzkaller emulate USB devices? Yes, syzkaller has USB fuzzing (`syz_usb_connect`). We *might* be able to emulate a Broadcom USB Wi-Fi dongle. This is significant! Let me check if `brcmfmac` USB is supported... and yep, there's `drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c`. Good! That makes fuzzing this patch series much more feasible. Now, let's see which of the modified files are also used by the USB driver. `cfg80211.c`, `core.c`, `flowring.c`, `fwsignal.c`, and `msgbuf.c` are core components, so they are likely reachable. `pcie.c` and `sdio.c` are specific to their respective interfaces, and `brcmsmac` appears to be PCIe only. So, I can probably rule out `brcmsmac` at this stage. The prompt mentions drivers that require physical PCIe hardware cards. However, since `brcmfmac` supports USB, that's a different story. I can probably fuzz it using syzkaller's USB capabilities, maybe with dummy HCD or raw gadget emulation. Let's see if this has been done before. Yes, Syzkaller heavily fuzzer USB drivers, so this looks promising! Okay, so to prioritize, the new `brcmf_pmksa_v2_op` in `cfg80211.c`, the `brcmf_flowring_block` in `flowring.c` and `brcmf_msgbuf_schedule_txdata` in `msgbuf.c` are what I'll focus on. I'll do |
| 4/2 | 2026/08/02 00:57 | tool | grepper |
0mArgs:{
"Expression": "brcmf_usb_probe",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=1165=static const struct brcmf_bus_ops brcmf_usb_bus_ops = {\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1175-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:1176:static void brcmf_usb_probe_phase2(struct device *dev, int ret,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1177-\t\t\t\t struct brcmf_fw_request *fwreq)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=1224=brcmf_usb_prepare_fw_request(struct brcmf_usbdev_info *devinfo)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1243-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:1244:static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1245-\t\t\t enum brcmf_fwvendor fwvid)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1307-\t/* request firmware here */\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:1308:\tret = brcmf_fw_get_firmwares(dev, fwreq, brcmf_usb_probe_phase2);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1309-\tif (ret) {\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=1341=static int\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:1342:brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1343-{\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1442-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:1443:\tret = brcmf_usb_probe_cb(devinfo, id-\u003edriver_info);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1444-\tif (ret)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=1511=static int brcmf_usb_reset_resume(struct usb_interface *intf)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1523-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:1524:\tret = brcmf_fw_get_firmwares(\u0026usb-\u003edev, fwreq, brcmf_usb_probe_phase2);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1525-\tif (ret \u003c 0)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=1565=static struct usb_driver brcmf_usbdrvr = {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1566-\t.name = KBUILD_MODNAME,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:1567:\t.probe = brcmf_usb_probe,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1568-\t.disconnect = brcmf_usb_disconnect,\n"
} |
| 5/2 | 2026/08/02 00:57 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 17161 output: 47 thoughts: 51 Thoughts: Okay, here's my take on those thoughts, framed as my own: **Investigating the brcmfmac USB Driver** Alright, so I'm digging into `brcmfmac` and I know it has a USB driver, but I'm trying to remember the specific architecture. Now, the question is, does the USB implementation in `brcmfmac` utilize the message buffer infrastructure (`msgbuf.c`) or does it lean on the more modern flow ring implementation (`flowring.c`)? I need to clarify that. My instinct is, it's probably using the flow ring, but I need to confirm that. Time to check and see what the code shows me about the USB path. Let me see where it pulls its data and control structures from. |
| 6/2 | 2026/08/02 00:57 | tool | grepper |
0mError:no matches Args: {
"Expression": "msgbuf",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c"
}Results: {
"error": "no matches"
} |
| 7/2 | 2026/08/02 00:57 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 17437 output: 44 thoughts: 40 Thoughts: Okay, here's my take on those files, thinking as I would in this situation: **Investigating Potential PCIe Dependencies** Right, let's see... `msgbuf.c` and `flowring.c`... those names are giving me a little nudge, making me wonder if they're particularly tied to PCIe operations. It's not a certainty, but the names suggest a potential connection to message buffering or flow control, which are common aspects of high-speed interconnects like PCIe. So, the next logical step is a quick dive into the code to confirm or deny that suspicion. I'll need to carefully examine how `msgbuf.c` and `flowring.c` are used within the broader context. Checking their usage patterns will quickly clarify if they are indeed PCIe-specific, or if they have more generic applicability. |
| 8/2 | 2026/08/02 00:57 | tool | grepper |
0mArgs:{
"Expression": "msgbuf",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "\nFull output is too long, showing 500 out of 1196 lines.\nUse more precise expression if possible.\n\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile=32=brcmfmac-$(CONFIG_BRCMFMAC_PROTO_MSGBUF) += \\\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile-34-\t\tflowring.o \\\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile:35:\t\tmsgbuf.o\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile-36-brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \\\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h-13-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h:14:/* IDs of the 6 default common rings of msgbuf protocol */\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h-15-#define BRCMF_H2D_MSGRING_CONTROL_SUBMIT\t0\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h=95=struct brcmf_bus_ops {\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h-113-/**\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h:114: * struct brcmf_bus_msgbuf - bus ringbuf if in case of msgbuf.\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h-115- *\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h-123- */\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h:124:struct brcmf_bus_msgbuf {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h-125-\tstruct brcmf_commonring *commonrings[BRCMF_NROF_COMMON_MSGRINGS];\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h=141=struct brcmf_bus_stats {\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h-149- * @bus_priv: pointer to private bus device.\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h:150: * @proto_type: protocol type, bcdc or msgbuf\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h-151- * @dev: device pointer of bus device.\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h-161- * @ops: callbacks for this bus instance.\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h:162: * @msgbuf: msgbuf protocol parameters provided by bus layer.\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h-163- * @list: member used to add this bus instance to linked list.\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h=165=struct brcmf_bus {\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h-183-\tconst struct brcmf_bus_ops *ops;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h:184:\tstruct brcmf_bus_msgbuf *msgbuf;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h-185-\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-16-#include \"flowring.h\"\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c:17:#include \"msgbuf.h\"\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-18-#include \"common.h\"\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c=409=void brcmf_flowring_detach(struct brcmf_flowring *flow)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-418-\t\tif (flow-\u003erings[flowid])\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c:419:\t\t\tbrcmf_msgbuf_delete_flowring(drvr, flowid);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-420-\t}\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c=432=void brcmf_flowring_configure_addr_mode(struct brcmf_flowring *flow, int ifidx,\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-445-\t\t\t\t\tcontinue;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c:446:\t\t\t\tbrcmf_msgbuf_delete_flowring(drvr, flowid);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-447-\t\t\t}\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c=454=void brcmf_flowring_delete_peer(struct brcmf_flowring *flow, int ifidx,\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-484-\t\t\tif (flow-\u003erings[flowid]-\u003estatus == RING_OPEN)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c:485:\t\t\t\tbrcmf_msgbuf_delete_flowring(drvr, flowid);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-486-\t\t}\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-20-#include \"proto.h\"\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:21:#include \"msgbuf.h\"\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-22-#include \"commonring.h\"\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-94- *\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:95: * TRICKLE_TXWORKER_THRS governs how often brcmf_msgbuf_tx_queue_data()\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-96- * forces a workqueue schedule when the queue depth is not a multiple of\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-108-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:109:struct msgbuf_common_hdr {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-110-\tu8\t\t\t\tmsgtype;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-116-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:117:struct msgbuf_ioctl_req_hdr {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:118:\tstruct msgbuf_common_hdr\tmsg;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-119-\t__le32\t\t\t\tcmd;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-123-\t__le16\t\t\t\trsvd0[3];\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:124:\tstruct msgbuf_buf_addr\t\treq_buf_addr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-125-\t__le32\t\t\t\trsvd1[2];\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-127-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:128:struct msgbuf_tx_msghdr {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:129:\tstruct msgbuf_common_hdr\tmsg;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-130-\tu8\t\t\t\ttxhdr[ETH_HLEN];\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-132-\tu8\t\t\t\tseg_cnt;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:133:\tstruct msgbuf_buf_addr\t\tmetadata_buf_addr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:134:\tstruct msgbuf_buf_addr\t\tdata_buf_addr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-135-\t__le16\t\t\t\tmetadata_buf_len;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-139-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:140:struct msgbuf_rx_bufpost {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:141:\tstruct msgbuf_common_hdr\tmsg;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-142-\t__le16\t\t\t\tmetadata_buf_len;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-144-\t__le32\t\t\t\trsvd0;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:145:\tstruct msgbuf_buf_addr\t\tmetadata_buf_addr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:146:\tstruct msgbuf_buf_addr\t\tdata_buf_addr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-147-};\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-148-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:149:struct msgbuf_rx_ioctl_resp_or_event {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:150:\tstruct msgbuf_common_hdr\tmsg;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-151-\t__le16\t\t\t\thost_buf_len;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-152-\t__le16\t\t\t\trsvd0[3];\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:153:\tstruct msgbuf_buf_addr\t\thost_buf_addr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-154-\t__le32\t\t\t\trsvd1[4];\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-156-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:157:struct msgbuf_completion_hdr {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-158-\t__le16\t\t\t\tstatus;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-162-/* Data struct for the MSGBUF_TYPE_GEN_STATUS */\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:163:struct msgbuf_gen_status {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:164:\tstruct msgbuf_common_hdr\tmsg;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:165:\tstruct msgbuf_completion_hdr\tcompl_hdr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-166-\t__le16\t\t\t\twrite_idx;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-170-/* Data struct for the MSGBUF_TYPE_RING_STATUS */\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:171:struct msgbuf_ring_status {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:172:\tstruct msgbuf_common_hdr\tmsg;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:173:\tstruct msgbuf_completion_hdr\tcompl_hdr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-174-\t__le16\t\t\t\twrite_idx;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-177-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:178:struct msgbuf_rx_event {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:179:\tstruct msgbuf_common_hdr\tmsg;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:180:\tstruct msgbuf_completion_hdr\tcompl_hdr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-181-\t__le16\t\t\t\tevent_data_len;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-185-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:186:struct msgbuf_ioctl_resp_hdr {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:187:\tstruct msgbuf_common_hdr\tmsg;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:188:\tstruct msgbuf_completion_hdr\tcompl_hdr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-189-\t__le16\t\t\t\tresp_len;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-194-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:195:struct msgbuf_tx_status {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:196:\tstruct msgbuf_common_hdr\tmsg;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:197:\tstruct msgbuf_completion_hdr\tcompl_hdr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-198-\t__le16\t\t\t\tmetadata_len;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-201-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:202:struct msgbuf_rx_complete {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:203:\tstruct msgbuf_common_hdr\tmsg;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:204:\tstruct msgbuf_completion_hdr\tcompl_hdr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-205-\t__le16\t\t\t\tmetadata_len;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-213-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:214:struct msgbuf_tx_flowring_create_req {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:215:\tstruct msgbuf_common_hdr\tmsg;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-216-\tu8\t\t\t\tda[ETH_ALEN];\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-225-\t__le16\t\t\t\tlen_item;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:226:\tstruct msgbuf_buf_addr\t\tflow_ring_addr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-227-};\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-228-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:229:struct msgbuf_tx_flowring_delete_req {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:230:\tstruct msgbuf_common_hdr\tmsg;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-231-\t__le16\t\t\t\tflow_ring_id;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-235-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:236:struct msgbuf_flowring_create_resp {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:237:\tstruct msgbuf_common_hdr\tmsg;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:238:\tstruct msgbuf_completion_hdr\tcompl_hdr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-239-\t__le32\t\t\t\trsvd0[3];\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-241-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:242:struct msgbuf_flowring_delete_resp {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:243:\tstruct msgbuf_common_hdr\tmsg;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:244:\tstruct msgbuf_completion_hdr\tcompl_hdr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-245-\t__le32\t\t\t\trsvd0[3];\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-247-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:248:struct msgbuf_flowring_flush_resp {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:249:\tstruct msgbuf_common_hdr\tmsg;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:250:\tstruct msgbuf_completion_hdr\tcompl_hdr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-251-\t__le32\t\t\t\trsvd0[3];\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-253-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:254:struct brcmf_msgbuf_work_item {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-255-\tstruct list_head queue;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-261-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:262:struct brcmf_msgbuf {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-263-\tstruct brcmf_pub *drvr;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-296-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:297:\tstruct brcmf_msgbuf_pktids *tx_pktids;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:298:\tstruct brcmf_msgbuf_pktids *rx_pktids;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-299-\tstruct brcmf_flowring *flow;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-310-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:311:struct brcmf_msgbuf_pktid {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-312-\tatomic_t allocated;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-317-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:318:struct brcmf_msgbuf_pktids {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-319-\tu32 array_size;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-321-\tenum dma_data_direction direction;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:322:\tstruct brcmf_msgbuf_pktid *array;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-323-};\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-324-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:325:static void brcmf_msgbuf_rxbuf_ioctlresp_post(struct brcmf_msgbuf *msgbuf);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-326-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-327-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:328:static struct brcmf_msgbuf_pktids *\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:329:brcmf_msgbuf_init_pktids(u32 nr_array_entries,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-330-\t\t\t enum dma_data_direction direction)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-331-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:332:\tstruct brcmf_msgbuf_pktid *array;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:333:\tstruct brcmf_msgbuf_pktids *pktids;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-334-\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c=351=static int\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:352:brcmf_msgbuf_alloc_pktid(struct device *dev,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:353:\t\t\t struct brcmf_msgbuf_pktids *pktids,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-354-\t\t\t struct sk_buff *skb, u16 data_offset,\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-356-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:357:\tstruct brcmf_msgbuf_pktid *array;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-358-\tu32 count;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c=399=static struct sk_buff *\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:400:brcmf_msgbuf_get_pktid(struct device *dev, struct brcmf_msgbuf_pktids *pktids,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-401-\t\t u32 idx)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-402-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:403:\tstruct brcmf_msgbuf_pktid *pktid;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-404-\tstruct sk_buff *skb;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c=427=static void\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:428:brcmf_msgbuf_release_array(struct device *dev,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:429:\t\t\t struct brcmf_msgbuf_pktids *pktids)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-430-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:431:\tstruct brcmf_msgbuf_pktid *array;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:432:\tstruct brcmf_msgbuf_pktid *pktid;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-433-\tu32 count;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-452-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:453:static void brcmf_msgbuf_release_pktids(struct brcmf_msgbuf *msgbuf)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-454-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:455:\tif (msgbuf-\u003erx_pktids)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:456:\t\tbrcmf_msgbuf_release_array(msgbuf-\u003edrvr-\u003ebus_if-\u003edev,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:457:\t\t\t\t\t msgbuf-\u003erx_pktids);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:458:\tif (msgbuf-\u003etx_pktids)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:459:\t\tbrcmf_msgbuf_release_array(msgbuf-\u003edrvr-\u003ebus_if-\u003edev,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:460:\t\t\t\t\t msgbuf-\u003etx_pktids);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-461-}\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-463-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:464:static int brcmf_msgbuf_tx_ioctl(struct brcmf_pub *drvr, int ifidx,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-465-\t\t\t\t uint cmd, void *buf, uint len)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-466-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:467:\tstruct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr-\u003eproto-\u003epd;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-468-\tstruct brcmf_commonring *commonring;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:469:\tstruct msgbuf_ioctl_req_hdr *request;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-470-\tu16 buf_len;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-473-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:474:\tcommonring = msgbuf-\u003ecommonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-475-\tbrcmf_commonring_lock(commonring);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-482-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:483:\tmsgbuf-\u003ereqid++;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-484-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:485:\trequest = (struct msgbuf_ioctl_req_hdr *)ret_ptr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-486-\trequest-\u003emsg.msgtype = MSGBUF_TYPE_IOCTLPTR_REQ;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-491-\trequest-\u003eoutput_buf_len = cpu_to_le16(len);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:492:\trequest-\u003etrans_id = cpu_to_le16(msgbuf-\u003ereqid);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-493-\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-495-\trequest-\u003einput_buf_len = cpu_to_le16(buf_len);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:496:\trequest-\u003ereq_buf_addr.high_addr = cpu_to_le32(msgbuf-\u003eioctbuf_phys_hi);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:497:\trequest-\u003ereq_buf_addr.low_addr = cpu_to_le32(msgbuf-\u003eioctbuf_phys_lo);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-498-\tif (buf)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:499:\t\tmemcpy(msgbuf-\u003eioctbuf, buf, buf_len);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-500-\telse\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:501:\t\tmemset(msgbuf-\u003eioctbuf, 0, buf_len);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-502-\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-509-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:510:static int brcmf_msgbuf_ioctl_resp_wait(struct brcmf_msgbuf *msgbuf)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-511-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:512:\treturn wait_event_timeout(msgbuf-\u003eioctl_resp_wait,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:513:\t\t\t\t msgbuf-\u003ectl_completed,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-514-\t\t\t\t MSGBUF_IOCTL_RESP_TIMEOUT);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-517-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:518:static void brcmf_msgbuf_ioctl_resp_wake(struct brcmf_msgbuf *msgbuf)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-519-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:520:\tmsgbuf-\u003ectl_completed = true;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:521:\twake_up(\u0026msgbuf-\u003eioctl_resp_wait);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-522-}\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-524-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:525:static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-526-\t\t\t\t uint cmd, void *buf, uint len, int *fwerr)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-527-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:528:\tstruct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr-\u003eproto-\u003epd;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-529-\tstruct sk_buff *skb = NULL;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-534-\t*fwerr = 0;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:535:\tmsgbuf-\u003ectl_completed = false;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:536:\terr = brcmf_msgbuf_tx_ioctl(drvr, ifidx, cmd, buf, len);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-537-\tif (err)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-539-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:540:\ttimeout = brcmf_msgbuf_ioctl_resp_wait(msgbuf);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-541-\tif (!timeout) {\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-545-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:546:\tskb = brcmf_msgbuf_get_pktid(msgbuf-\u003edrvr-\u003ebus_if-\u003edev,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:547:\t\t\t\t msgbuf-\u003erx_pktids,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:548:\t\t\t\t msgbuf-\u003eioctl_resp_pktid);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:549:\tif (msgbuf-\u003eioctl_resp_ret_len != 0) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-550-\t\tif (!skb)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-552-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:553:\t\tmemcpy(buf, skb-\u003edata, (len \u003c msgbuf-\u003eioctl_resp_ret_len) ?\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:554:\t\t\t\t len : msgbuf-\u003eioctl_resp_ret_len);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-555-\t}\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-557-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:558:\t*fwerr = msgbuf-\u003eioctl_resp_status;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-559-\treturn 0;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-562-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:563:static int brcmf_msgbuf_set_dcmd(struct brcmf_pub *drvr, int ifidx,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-564-\t\t\t\t uint cmd, void *buf, uint len, int *fwerr)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-565-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:566:\treturn brcmf_msgbuf_query_dcmd(drvr, ifidx, cmd, buf, len, fwerr);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-567-}\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-569-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:570:static int brcmf_msgbuf_hdrpull(struct brcmf_pub *drvr, bool do_fws,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-571-\t\t\t\tstruct sk_buff *skb, struct brcmf_if **ifp)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-575-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:576:static void brcmf_msgbuf_rxreorder(struct brcmf_if *ifp, struct sk_buff *skb)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-577-{\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c=580=static void\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:581:brcmf_msgbuf_remove_flowring(struct brcmf_msgbuf *msgbuf, u16 flowid)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-582-{\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-588-\tdma_sz = BRCMF_H2D_TXFLOWRING_MAX_ITEM * BRCMF_H2D_TXFLOWRING_ITEMSIZE;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:589:\tdma_buf = msgbuf-\u003eflowrings[flowid]-\u003ebuf_addr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:590:\tdma_free_coherent(msgbuf-\u003edrvr-\u003ebus_if-\u003edev, dma_sz, dma_buf,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:591:\t\t\t msgbuf-\u003eflowring_dma_handle[flowid]);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-592-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:593:\tbrcmf_flowring_delete(msgbuf-\u003eflow, flowid);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-594-}\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-596-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:597:static struct brcmf_msgbuf_work_item *\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:598:brcmf_msgbuf_dequeue_work(struct brcmf_msgbuf *msgbuf)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-599-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:600:\tstruct brcmf_msgbuf_work_item *work = NULL;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-601-\tulong flags;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-602-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:603:\tspin_lock_irqsave(\u0026msgbuf-\u003eflowring_work_lock, flags);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:604:\tif (!list_empty(\u0026msgbuf-\u003ework_queue)) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:605:\t\twork = list_first_entry(\u0026msgbuf-\u003ework_queue,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:606:\t\t\t\t\tstruct brcmf_msgbuf_work_item, queue);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-607-\t\tlist_del(\u0026work-\u003equeue);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-608-\t}\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:609:\tspin_unlock_irqrestore(\u0026msgbuf-\u003eflowring_work_lock, flags);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-610-\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c=615=static u32\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:616:brcmf_msgbuf_flowring_create_worker(struct brcmf_msgbuf *msgbuf,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:617:\t\t\t\t struct brcmf_msgbuf_work_item *work)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-618-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:619:\tstruct brcmf_pub *drvr = msgbuf-\u003edrvr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:620:\tstruct msgbuf_tx_flowring_create_req *create;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-621-\tstruct brcmf_commonring *commonring;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-630-\tdma_sz = BRCMF_H2D_TXFLOWRING_MAX_ITEM * BRCMF_H2D_TXFLOWRING_ITEMSIZE;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:631:\tdma_buf = dma_alloc_coherent(msgbuf-\u003edrvr-\u003ebus_if-\u003edev, dma_sz,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:632:\t\t\t\t \u0026msgbuf-\u003eflowring_dma_handle[flowid],\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-633-\t\t\t\t GFP_KERNEL);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-635-\t\tbphy_err(drvr, \"dma_alloc_coherent failed\\n\");\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:636:\t\tbrcmf_flowring_delete(msgbuf-\u003eflow, flowid);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-637-\t\treturn BRCMF_FLOWRING_INVALID_ID;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-639-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:640:\tbrcmf_commonring_config(msgbuf-\u003eflowrings[flowid],\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-641-\t\t\t\tBRCMF_H2D_TXFLOWRING_MAX_ITEM,\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-643-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:644:\tcommonring = msgbuf-\u003ecommonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-645-\tbrcmf_commonring_lock(commonring);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-649-\t\tbrcmf_commonring_unlock(commonring);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:650:\t\tbrcmf_msgbuf_remove_flowring(msgbuf, flowid);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-651-\t\treturn BRCMF_FLOWRING_INVALID_ID;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-653-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:654:\tcreate = (struct msgbuf_tx_flowring_create_req *)ret_ptr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-655-\tcreate-\u003emsg.msgtype = MSGBUF_TYPE_FLOW_RING_CREATE;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-657-\tcreate-\u003emsg.request_id = 0;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:658:\tcreate-\u003etid = brcmf_flowring_tid(msgbuf-\u003eflow, flowid);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-659-\tcreate-\u003eflow_ring_id = cpu_to_le16(flowid +\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-662-\tmemcpy(create-\u003eda, work-\u003eda, ETH_ALEN);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:663:\taddress = (u64)msgbuf-\u003eflowring_dma_handle[flowid];\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-664-\tcreate-\u003eflow_ring_addr.high_addr = cpu_to_le32(address \u003e\u003e 32);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-675-\t\tbphy_err(drvr, \"Failed to write commonring\\n\");\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:676:\t\tbrcmf_msgbuf_remove_flowring(msgbuf, flowid);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-677-\t\treturn BRCMF_FLOWRING_INVALID_ID;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-683-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:684:static void brcmf_msgbuf_flowring_worker(struct work_struct *work)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-685-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:686:\tstruct brcmf_msgbuf *msgbuf;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:687:\tstruct brcmf_msgbuf_work_item *create;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-688-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:689:\tmsgbuf = container_of(work, struct brcmf_msgbuf, flowring_work);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-690-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:691:\twhile ((create = brcmf_msgbuf_dequeue_work(msgbuf))) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:692:\t\tbrcmf_msgbuf_flowring_create_worker(msgbuf, create);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-693-\t\tkfree(create);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-697-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:698:static u32 brcmf_msgbuf_flowring_create(struct brcmf_msgbuf *msgbuf, int ifidx,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-699-\t\t\t\t\tstruct sk_buff *skb)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-700-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:701:\tstruct brcmf_msgbuf_work_item *create;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-702-\tstruct ethhdr *eh = (struct ethhdr *)(skb-\u003edata);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-709-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:710:\tflowid = brcmf_flowring_create(msgbuf-\u003eflow, eh-\u003eh_dest,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-711-\t\t\t\t skb-\u003epriority, ifidx);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-721-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:722:\tspin_lock_irqsave(\u0026msgbuf-\u003eflowring_work_lock, flags);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:723:\tlist_add_tail(\u0026create-\u003equeue, \u0026msgbuf-\u003ework_queue);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:724:\tspin_unlock_irqrestore(\u0026msgbuf-\u003eflowring_work_lock, flags);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:725:\tschedule_work(\u0026msgbuf-\u003eflowring_work);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-726-\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-730-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:731:static void brcmf_msgbuf_txflow(struct brcmf_msgbuf *msgbuf, u16 flowid)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-732-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:733:\tstruct brcmf_flowring *flow = msgbuf-\u003eflow;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:734:\tstruct brcmf_pub *drvr = msgbuf-\u003edrvr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-735-\tstruct brcmf_commonring *commonring;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-740-\tu32 pktid;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:741:\tstruct msgbuf_tx_msghdr *tx_msghdr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-742-\tu64 address;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-743-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:744:\tcommonring = msgbuf-\u003eflowrings[flowid];\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-745-\tif (!brcmf_commonring_write_available(commonring))\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-758-\t\tskb_orphan(skb);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:759:\t\tif (brcmf_msgbuf_alloc_pktid(msgbuf-\u003edrvr-\u003ebus_if-\u003edev,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:760:\t\t\t\t\t msgbuf-\u003etx_pktids, skb, ETH_HLEN,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-761-\t\t\t\t\t \u0026physaddr, \u0026pktid)) {\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-767-\t\tif (!ret_ptr) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:768:\t\t\tbrcmf_msgbuf_get_pktid(msgbuf-\u003edrvr-\u003ebus_if-\u003edev,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:769:\t\t\t\t\t msgbuf-\u003etx_pktids, pktid);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-770-\t\t\tbrcmf_flowring_reinsert(flow, flowid, skb);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-774-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:775:\t\ttx_msghdr = (struct msgbuf_tx_msghdr *)ret_ptr;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-776-\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-804-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:805:static void brcmf_msgbuf_txflow_worker(struct work_struct *worker)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-806-{\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:807:\tstruct brcmf_msgbuf *msgbuf;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-808-\tu32 flowid;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-809-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:810:\tmsgbuf = container_of(worker, struct brcmf_msgbuf, txflow_work);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:811:\tfor_each_set_bit(flowid, msgbuf-\u003eflow_map, msgbuf-\u003emax_flowrings) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:812:\t\tclear_bit(flowid, msgbuf-\u003eflow_map);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:813:\t\tbrcmf_msgbuf_txflow(msgbuf, flowid);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-814-\t}\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-817-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:818:static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-819-\t\t\t\t\tbool force)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-836-\t */\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:837:\tif (!test_and_set_bit(flowid, msgbuf-\u003eflow_map)) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-838-\t\t/* Bit was clear: no worker pending, always schedule. */\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:839:\t\tqueue_work(msgbuf-\u003etxflow_wq, \u0026msgbuf-\u003etxflow_work);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-840-\t\treturn 0;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-843-\t/* Bit was already set: worker pending, apply coalescing heuristic. */\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:844:\tcommonring = msgbuf-\u003eflowrings[flowid];\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-845-\tif (force || (atomic_read(\u0026commonring-\u003eoutstanding_tx) \u003c\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-846-\t\t BRCMF_MSGBUF_DELAY_TXWORKER_THRS))\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:847:\t\tqueue_work(msgbuf-\u003etxflow_wq, \u0026msgbuf-\u003etxflow_work);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-848-\n\n"
} |
| 9/2 | 2026/08/02 00:57 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 35583 output: 52 thoughts: 54 Thoughts: Okay, here's my interpretation of that thought process, assuming I'm deeply familiar with embedded systems, kernel configuration, and Broadcom Wi-Fi drivers, and I'm looking at source code: **Diving into the `brcmfmac` Protocol Implementation** Alright, so `msgbuf.c` and `flowring.c`... those files immediately jump out at me as key pieces within the `CONFIG_BRCMFMAC_PROTO_MSGBUF` protocol implementation. My first instinct is to confirm my assumption. I need to make absolutely sure they're controlled by that config option. Therefore, I should immediately go check the Kconfig files related to the driver. I need to verify what settings are enabled for it. Is that option enabled at all? If it is, what are the dependencies? Are there other options tied to this area that I need to be aware of? Best to get the lay of the land now. |
| 10/2 | 2026/08/02 00:57 | tool | grepper |
0mArgs:{
"Expression": "BRCMFMAC_PROTO_MSGBUF",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig=11=config BRCMFMAC_PROTO_BCDC\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-13-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:14:config BRCMFMAC_PROTO_MSGBUF\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-15-\tbool\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig=40=config BRCMFMAC_PCIE\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-43-\tdepends on PCI\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:44:\tselect BRCMFMAC_PROTO_MSGBUF\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-45-\tselect FW_LOADER\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile=29=brcmfmac-$(CONFIG_BRCMFMAC_PROTO_BCDC) += \\\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile-31-\t\tfwsignal.o\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile:32:brcmfmac-$(CONFIG_BRCMFMAC_PROTO_MSGBUF) += \\\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile-33-\t\tcommonring.o \\\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h-7-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h:8:#ifdef CONFIG_BRCMFMAC_PROTO_MSGBUF\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h-9-\n"
} |
| 11/2 | 2026/08/02 00:57 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 36463 output: 48 thoughts: 193 Thoughts: **Analyzing the brcmfmac Driver for Syzkaller Coverage** Okay, so I see that `BRCMFMAC_PROTO_MSGBUF` gets enabled when `BRCMFMAC_PCIE` is chosen. My first question is, can we actually *reach* `BRCMFMAC_PCIE` within the constraints of Syzkaller's emulation? I'm pretty sure Syzkaller doesn't natively emulate Broadcom PCIe devices. But then again, I need to double-check my assumptions, it's always good to be thorough. The prompt specifically mentions code related to vendor-specific PCIe switches, SmartNICs, or GPU drivers. They give examples like `mlxsw`, `pds_core`, `qed`, `ionic`, and `amdgpu` that typically need actual PCIe hardware. Is `brcmfmac` in that category? Well, it's a Broadcom Wi-Fi driver, so yes, it's vendor-specific, but that doesn't *automatically* mean it can't be emulated. However, I recall that `brcmfmac` also has support for SDIO and USB interfaces. Ah, the USB driver should select `BRCMFMAC_PROTO_BCDC`. That's interesting, there might be a workaround here. Time to dig into the `Kconfig` files and check exactly how `BRCMFMAC_USB` is defined and how it relates to these other protocols. This could open a valuable coverage path. |
| 12/2 | 2026/08/02 00:57 | tool | grepper |
0mArgs:{
"Expression": "BRCMFMAC_USB",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig=17=config BRCMFMAC_SDIO\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-28-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:29:config BRCMFMAC_USB\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-30-\tbool \"USB bus interface support for FullMAC driver\"\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile=36=brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \\\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile-38-\t\tbcmsdh.o\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile:39:brcmfmac-$(CONFIG_BRCMFMAC_USB) += \\\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile-40-\t\tusb.o\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h=323=static inline int brcmf_sdio_register(void) { return 0; }\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h-325-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h:326:#ifdef CONFIG_BRCMFMAC_USB\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h-327-void brcmf_usb_exit(void);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=302=static int brcmf_usb_tx_ctlpkt(struct device *dev, u8 *buf, u32 len)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-314-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:315:\tif (devinfo-\u003ebus_pub.state != BRCMFMAC_USB_STATE_UP) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-316-\t\terr = -EIO;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=347=static int brcmf_usb_rx_ctlpkt(struct device *dev, u8 *buf, u32 len)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-359-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:360:\tif (devinfo-\u003ebus_pub.state != BRCMFMAC_USB_STATE_UP) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-361-\t\terr = -EIO;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=507=static void brcmf_usb_rx_complete(struct urb *urb)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-524-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:525:\tif (devinfo-\u003ebus_pub.state == BRCMFMAC_USB_STATE_UP ||\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:526:\t devinfo-\u003ebus_pub.state == BRCMFMAC_USB_STATE_SLEEP) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-527-\t\tskb_put(skb, urb-\u003eactual_length);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=571=static void brcmf_usb_rx_fill_all(struct brcmf_usbdev_info *devinfo)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-574-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:575:\tif (devinfo-\u003ebus_pub.state != BRCMFMAC_USB_STATE_UP) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-576-\t\tbrcmf_err(\"bus is not up=%d\\n\", devinfo-\u003ebus_pub.state);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=584=brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-596-\t/* update state of upper layer */\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:597:\tif (state == BRCMFMAC_USB_STATE_DOWN) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-598-\t\tbrcmf_dbg(USB, \"DBUS is down\\n\");\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-599-\t\tbrcmf_bus_change_state(bcmf_bus, BRCMF_BUS_DOWN);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:600:\t} else if (state == BRCMFMAC_USB_STATE_UP) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-601-\t\tbrcmf_dbg(USB, \"DBUS is up\\n\");\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=608=static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-620-\tbrcmf_dbg(USB, \"Enter, skb=%p\\n\", skb);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:621:\tif (devinfo-\u003ebus_pub.state != BRCMFMAC_USB_STATE_UP) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-622-\t\tret = -EIO;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=665=static int brcmf_usb_up(struct device *dev)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-669-\tbrcmf_dbg(USB, \"Enter\\n\");\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:670:\tif (devinfo-\u003ebus_pub.state == BRCMFMAC_USB_STATE_UP)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-671-\t\treturn 0;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-673-\t/* Success, indicate devinfo is fully up */\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:674:\tbrcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_UP);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-675-\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=714=static void brcmf_usb_down(struct device *dev)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-721-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:722:\tif (devinfo-\u003ebus_pub.state == BRCMFMAC_USB_STATE_DOWN)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-723-\t\treturn;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-724-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:725:\tbrcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_DOWN);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-726-\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=976=static int brcmf_usb_dlstart(struct brcmf_usbdev_info *devinfo, u8 *fw, int len)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-989-\tif (err == 0)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:990:\t\tdevinfo-\u003ebus_pub.state = BRCMFMAC_USB_STATE_DL_DONE;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-991-\telse\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:992:\t\tdevinfo-\u003ebus_pub.state = BRCMFMAC_USB_STATE_DL_FAIL;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-993-\tbrcmf_dbg(USB, \"Exit, err=%d\\n\", err);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=1103=struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1111-\tdevinfo-\u003ebus_pub.ntxq = ntxq;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:1112:\tdevinfo-\u003ebus_pub.state = BRCMFMAC_USB_STATE_DOWN;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1113-\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=1483=static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1488-\tbrcmf_dbg(USB, \"Enter\\n\");\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:1489:\tdevinfo-\u003ebus_pub.state = BRCMFMAC_USB_STATE_SLEEP;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1490-\tbrcmf_cancel_all_urbs(devinfo);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c=1498=static int brcmf_usb_resume(struct usb_interface *intf)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1504-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c:1505:\tdevinfo-\u003ebus_pub.state = BRCMFMAC_USB_STATE_UP;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c-1506-\tbrcmf_usb_rx_fill_all(devinfo);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h-4- */\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h:5:#ifndef BRCMFMAC_USB_H\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h:6:#define BRCMFMAC_USB_H\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h-7-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h=8=enum brcmf_usb_state {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h:9:\tBRCMFMAC_USB_STATE_DOWN,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h:10:\tBRCMFMAC_USB_STATE_DL_FAIL,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h:11:\tBRCMFMAC_USB_STATE_DL_DONE,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h:12:\tBRCMFMAC_USB_STATE_UP,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h:13:\tBRCMFMAC_USB_STATE_SLEEP\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h-14-};\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h=35=struct brcmf_usbreq {\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h-41-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.h:42:#endif /* BRCMFMAC_USB_H */\n"
} |
| 13/2 | 2026/08/02 00:57 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 40907 output: 55 thoughts: 896 Thoughts: **Reaching the Target Code: A Broadcom Wi-Fi Driver Analysis** Alright, let's break this down. My initial thought was that `BRCMFMAC_PCIE` is a PCIe driver, right? But the text throws a curveball: while Syzkaller *doesn't* typically directly fuzz PCIe devices unless emulated, it *does* have a history of fuzzing Wi-Fi components through `mac80211_hwsim`. Then I remember: `brcmfmac` is a FullMAC driver, which means it registers directly with `cfg80211`, not `mac80211`. The lightbulb moment is the USB connection. `syz_usb_connect` can emulate a Broadcom USB Wi-Fi dongle, which then uses `BRCMFMAC_USB` and `BRCMFMAC_PROTO_BCDC`. However, the code changes focus on `msgbuf.c` and `flowring.c`, tied to `BRCMFMAC_PROTO_MSGBUF`, which is specifically selected by `BRCMFMAC_PCIE` for PCIe. This led me to question whether PCIe code can be reached through USB. Since it's not possible to reach PCIe via USB, my attention shifted to the SDIO (Secure Digital Input Output) possibility. SDIO uses `BRCMFMAC_PROTO_BCDC`, but it's not the target. Then, I focused on the universally used `cfg80211.c` that's accessible across different buses (USB, SDIO, and PCIe). The patch modifies `brcmf_pmksa_v2_op` within `cfg80211.c`. This function is pivotal, being called by `brcmf_cfg80211_set_pmksa`, `brcmf_cfg80211_del_pmksa`, and `brcmf_cfg80211_flush_pmksa`. These are standard `cfg80211` callbacks and can be triggered from userspace via netlink (nl80211). So, assuming a `brcmfmac` device is present, I can reach `brcmf_pmksa_v2_op`, and crucially, since `brcmfmac` can be instantiated via USB fuzzing (`syz_usb_connect`), this particular code is reachable. The prompt mentioning vendor-specific PCIe switch/SmartNIC/GPU drivers threw me for a moment, implying physical PCIe hardware is required. But `brcmfmac` supports USB, allowing for emulation. The modifications also touch on `pcie.c`, `msgbuf.c`, and `flowring.c` (PCIe specific), but `cfg80211.c` is generic and reachable via USB. Also `core.c` is touched by `brcmf_netif_mon_rx` (generic), and `sdio.c` is touched by `brcmf_sdio_rxglom` (SDIO specific). My conclusion is that `cfg80211.c` and `core.c` are definitely reachable if the USB driver is probed. I now need to see whether `brcmf_pmksa_v2_op` is reachable and it looks like it is if `brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V2)` is true. I must check how to enable `BRCMF_FEAT_PMKID_V2`. |
| 14/2 | 2026/08/02 00:57 | tool | grepper |
0mArgs:{
"Expression": "BRCMF_FEAT_PMKID_V2",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=4486=brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-4504-\t\treturn brcmf_pmksa_v3_op(ifp, pmksa, true);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:4505:\tif (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V2))\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-4506-\t\treturn brcmf_pmksa_v2_op(cfg, ifp, pmksa, true);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=4531=brcmf_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *ndev,\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-4548-\t\treturn brcmf_pmksa_v3_op(ifp, pmksa, false);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:4549:\tif (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V2))\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-4550-\t\treturn brcmf_pmksa_v2_op(cfg, ifp, pmksa, false);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=4578=brcmf_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *ndev)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-4589-\t\treturn brcmf_pmksa_v3_op(ifp, NULL, false);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:4590:\tif (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_PMKID_V2))\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-4591-\t\treturn brcmf_pmksa_v2_op(cfg, ifp, NULL, false);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c=137=static const struct brcmf_feat_wlcfeat brcmf_feat_wlcfeat_map[] = {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c:138:\t{ 12, 0, BIT(BRCMF_FEAT_PMKID_V2) },\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c-139-\t{ 13, 0, BIT(BRCMF_FEAT_PMKID_V3) },\n"
} |
| 15/2 | 2026/08/02 00:57 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 43587 output: 52 thoughts: 186 Thoughts: Here's my analysis of the situation: **Reaching PMKIDv2 Code via Syzkaller and Firmware Manipulation** Okay, so `BRCMF_FEAT_PMKID_V2` is enabled based on specific firmware features, as the code indicates. Now, given that I'm dealing with syzkaller, and I know its capabilities, this is interesting. The key here is that syzkaller can emulate USB devices, which means it can inject arbitrary firmware. Furthermore, the driver itself might attempt to load firmware, and syzkaller can intercept that request and provide its own. Now the question is, *does* syzkaller actually provide firmware for the `brcmfmac` driver? I know that syzkaller's image has a lot of firmware files already. Alternatively, it can leverage fault injection capabilities through `request_firmware`. It might even simply load the default firmware if nothing is specified. The crucial link is this: if the firmware advertises that feature 12 is supported, which triggers the `BRCMF_FEAT_PMKID_V2` bit in the code, then that code path is enabled. So, if I control the firmware that's loaded (or is provided to the driver through syzkaller), I can control whether that feature is active. Moving on, what about `brcmf_netif_mon_rx`? From my code analysis, I can see that it gets called from `brcmf_rx_frame`, which is in `core.c`. This needs to be considered in conjunction with the above, as it is likely connected to how the feature's functions are used. |
| 16/2 | 2026/08/02 00:58 | tool | grepper |
0mArgs:{
"Expression": "brcmf_netif_mon_rx",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c=434=struct brcmf_radiotap_info {\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c-438-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c:439:void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c-440-{\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h=220=void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h:221:void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h-222-void brcmf_net_detach(struct net_device *ndev, bool locked);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c=1200=brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-1240-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:1241:\t\tbrcmf_netif_mon_rx(ifp, skb);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-1242-\t\treturn;\n"
} |
| 17/2 | 2026/08/02 00:58 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 44717 output: 52 thoughts: 49 Thoughts: Okay, let's see... **Narrowing Down the `brcmf_netif_mon_rx` Callers** Hmm, it looks like `brcmf_netif_mon_rx` is *only* called from `msgbuf.c`? That seems a bit... specific. I need to make absolutely sure that's correct, because if it's potentially called from other files like `bcdc.c` or `sdio.c`, it changes the whole landscape of where this function could be causing an issue. Need to check if I am correct in my assumptions about the callers or not. Let's dig in and double-check those other modules. I need to be 100% sure before I make any decisions based on this. Let's see... |
| 18/2 | 2026/08/02 00:58 | tool | grepper |
0mArgs:{
"Expression": "brcmf_netif_mon_rx",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c=434=struct brcmf_radiotap_info {\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c-438-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c:439:void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c-440-{\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h=220=void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h:221:void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h-222-void brcmf_net_detach(struct net_device *ndev, bool locked);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c=1200=brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-1240-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:1241:\t\tbrcmf_netif_mon_rx(ifp, skb);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-1242-\t\treturn;\n"
} |
| 19/2 | 2026/08/02 00:58 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 45525 output: 52 thoughts: 702 Thoughts: **Reaching a Promising Target for Fuzzing** Okay, let's break this down. My initial thought was that `brcmf_netif_mon_rx` is only called from `msgbuf.c`, which, in turn, is only used by PCIe. So, is PCIe a good target for fuzzing in this setup? Given that Syzkaller doesn't emulate Broadcom PCIe devices, probably not. But then I remember that modifications in `cfg80211.c` are more generic, and critically, `brcmf_pmksa_v2_op` is located there. Can `cfg80211.c` be reached via USB? Yes! Alright, time to verify if `brcmf_pmksa_v2_op` is actually reachable. Yes, it's called from `brcmf_cfg80211_set_pmksa`, which is a `cfg80211` callback. That means we have a viable entry point. Now, what about `brcmf_sdio_rxglom`? It resides in `sdio.c`. Is SDIO fuzzed? Well, Syzkaller doesn't natively emulate SDIO devices, but maybe there's a workaround? No luck. There's no `syz_sdio_connect` pseudo-syscall. So, SDIO and PCIe-specific code is likely inaccessible in the standard QEMU setup. But, the `cfg80211.c` path via USB is solid. The real question is: is `brcmf_pmksa_v2_op` worth fuzzing? It seems to parse `pmksa` data, update `cfg->pmk_list_v2`, involves a lot of `memcpy` operations and list manipulation, and finally sends data to the firmware through `brcmf_fil_iovar_data_set`. Given the functional logic involved, this screams potential for fuzzing. Let's revisit `brcmf_pmksa_v2_op`. Looking at the signature: ```c static s32 brcmf_pmksa_v2_op(struct brcmf_cfg80211_info *cfg, struct brcmf_if *ifp, struct cfg80211_pmksa *pmksa, bool alive) ``` It's static, but called from `brcmf_cfg80211_set_pmksa`, `brcmf_cfg80211_del_pmksa`, and `brcmf_cfg80211_flush_pmksa`. Those are not static and are API entry points. So, we should be targeting `brcmf_cfg80211_set_pmksa`, `brcmf_cfg80211_del_pmksa`, and `brcmf_cfg80211_flush_pmksa`. I have to pause a second, what about `brcmf_msgbuf_schedule_txdata` and `brcmf_flowring_block`? They are in `msgbuf.c` and `flowring.c`. If those are indeed PCIe-specific, they might be off-limits. However, let's re-examine `msgbuf.c` - is it truly *only* for PCIe? Let me check `BRCMFMAC_PROTO_MSGBUF`. |
| 20/2 | 2026/08/02 00:58 | tool | grepper |
0mArgs:{
"Expression": "BRCMFMAC_PROTO_MSGBUF",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig=11=config BRCMFMAC_PROTO_BCDC\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-13-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:14:config BRCMFMAC_PROTO_MSGBUF\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-15-\tbool\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig=40=config BRCMFMAC_PCIE\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-43-\tdepends on PCI\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:44:\tselect BRCMFMAC_PROTO_MSGBUF\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-45-\tselect FW_LOADER\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile=29=brcmfmac-$(CONFIG_BRCMFMAC_PROTO_BCDC) += \\\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile-31-\t\tfwsignal.o\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile:32:brcmfmac-$(CONFIG_BRCMFMAC_PROTO_MSGBUF) += \\\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Makefile-33-\t\tcommonring.o \\\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h-7-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h:8:#ifdef CONFIG_BRCMFMAC_PROTO_MSGBUF\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h-9-\n"
} |
| 21/2 | 2026/08/02 00:58 | llm | patch-evaluator |
1mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 47611 output: 57 thoughts: 118 Thoughts: **Analyzing Broadcom WiFi Driver Configuration** Okay, so I'm focusing on Broadcom's WiFi driver code and need to understand the implications of `BRCMFMAC_PROTO_MSGBUF`. Right, it's pretty clear that `BRCMFMAC_PROTO_MSGBUF` is *only* selected when `BRCMFMAC_PCIE` is enabled. That means the files `msgbuf.c` and `flowring.c` are specifically tied to the PCIe implementation, which makes sense given their names. But wait, `brcmf_cfg80211_set_pmksa` is defined within `cfg80211.c`. Now, that file is supposed to be more generic, handling configuration via cfg80211, and *importantly* accessible via USB too. So I need to ensure this function is handled correctly. I'll take a closer look at `brcmf_cfg80211_set_pmksa` within `cfg80211.c` to see how it's implemented. |
| 22/2 | 2026/08/02 00:59 | tool | grepper |
0mArgs:{
"Expression": "brcmf_cfg80211_set_pmksa",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=4485=static s32\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:4486:brcmf_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *ndev,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-4487-\t\t\t struct cfg80211_pmksa *pmksa)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=6082=static struct cfg80211_ops brcmf_cfg80211_ops = {\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-6103-\t.resume = brcmf_cfg80211_resume,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:6104:\t.set_pmksa = brcmf_cfg80211_set_pmksa,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-6105-\t.del_pmksa = brcmf_cfg80211_del_pmksa,\n"
} |
| 23/2 | 2026/08/02 00:59 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 48431 output: 52 thoughts: 161 Thoughts: **Analyzing the Impact of the Changes** Okay, let's break this down. My initial focus is on the entry points for the PMKSA operations: `brcmf_cfg80211_set_pmksa`, `brcmf_cfg80211_del_pmksa`, and `brcmf_cfg80211_flush_pmksa`. I want to quickly identify if any other, more generic functions have been touched in this process, outside of those three. I see that `brcmf_delay` is modified, but that's an inline function within `cfg80211.c`, so it's probably contained in scope and specific. Now, `brcmf_netif_mon_rx` in `core.c` seems like it's been updated, which has me curious, but it looks like its only call site is within `msgbuf.c`. Since that's PCIe specific, I'm tempted to dismiss it as less broadly impactful. Wait, hold on. Before I jump to any conclusions, I'd better be absolutely certain about that. Let me quickly double-check that `brcmf_netif_mon_rx` isn't called from any other place within the codebase. We don't want any surprises. |
| 24/2 | 2026/08/02 00:59 | tool | grepper |
0mArgs:{
"Expression": "brcmf_netif_mon_rx",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c=434=struct brcmf_radiotap_info {\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c-438-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c:439:void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c-440-{\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h=220=void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h:221:void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h-222-void brcmf_net_detach(struct net_device *ndev, bool locked);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c=1200=brcmf_msgbuf_process_rx_complete(struct brcmf_msgbuf *msgbuf, void *buf)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-1240-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:1241:\t\tbrcmf_netif_mon_rx(ifp, skb);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-1242-\t\treturn;\n"
} |
| 25/2 | 2026/08/02 00:59 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 49462 output: 50 thoughts: 217 Thoughts: **Analyzing Potential Fuzzing Targets** Okay, so I'm digging into this kernel code, specifically looking for new fuzzing opportunities. My initial thought was, "alright, this change is only in `msgbuf.c`". But then I remembered `brcmf_sdio_rxglom`, that's in `sdio.c`. And then, wait a minute, is SDIO even fuzzed? My initial impression is that Syzkaller isn't doing SDIO emulation, which could be a gap. But here's a wrinkle: `brcmf_pmksa_v2_op` is sitting in `cfg80211.c`, and that's *reachable via USB*. Bingo! This is the key. This patch is making functional changes to kernel code that's already accessible through a fuzzing interface. That's immediately actionable. So, I need to zoom in on specific symbols here. The crucial entry points for this new functionality are definitely: `brcmf_cfg80211_set_pmksa`, `brcmf_cfg80211_del_pmksa`, and `brcmf_cfg80211_flush_pmksa`. These are my initial targets. Now, let's just make sure there aren't any other obvious entry points that I'm missing. Hmmm, `brcmf_flowring_block` is in `flowring.c`. I need to figure out how that's called. Is it exclusively from `msgbuf.c`, or are there other call paths to consider? That's the next check. |
| 26/2 | 2026/08/02 00:59 | tool | grepper |
0mArgs:{
"Expression": "brcmf_flowring_block",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c=168=u8 brcmf_flowring_tid(struct brcmf_flowring *flow, u16 flowid)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-177-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c:178:static void brcmf_flowring_block(struct brcmf_flowring *flow, u16 flowid,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-179-\t\t\t\t bool blocked)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-232-\t * Reading the atomic is safe here: we hold block_lock, so no\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c:233:\t * concurrent brcmf_flowring_block() call can race the update\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-234-\t * we just made above.\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c=256=void brcmf_flowring_delete(struct brcmf_flowring *flow, u16 flowid)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-271-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c:272:\tbrcmf_flowring_block(flow, flowid, false);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-273-\thash_idx = ring-\u003ehash_id;\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c=288=u32 brcmf_flowring_enqueue(struct brcmf_flowring *flow, u16 flowid,\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-298-\t (skb_queue_len(\u0026ring-\u003eskblist) \u003e BRCMF_FLOWRING_HIGH)) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c:299:\t\tbrcmf_flowring_block(flow, flowid, true);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-300-\t\tbrcmf_dbg(MSGBUF, \"Flowcontrol: BLOCK for ring %d\\n\", flowid);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-307-\t\tif (skb_queue_len(\u0026ring-\u003eskblist) \u003c BRCMF_FLOWRING_LOW)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c:308:\t\t\tbrcmf_flowring_block(flow, flowid, false);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-309-\t}\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c=314=struct sk_buff *brcmf_flowring_dequeue(struct brcmf_flowring *flow, u16 flowid)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-326-\t (skb_queue_len(\u0026ring-\u003eskblist) \u003c BRCMF_FLOWRING_LOW)) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c:327:\t\tbrcmf_flowring_block(flow, flowid, false);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.c-328-\t\tbrcmf_dbg(MSGBUF, \"Flowcontrol: OPEN for ring %d\\n\", flowid);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h=50=struct brcmf_flowring {\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h-55-\t/* Per-interface count of currently blocked open rings.\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h:56:\t * Maintained atomically so brcmf_flowring_block() can check\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/flowring.h-57-\t * whether any sibling ring is already blocked in O(1) without\n"
} |
| 27/2 | 2026/08/02 00:59 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 51393 output: 47 thoughts: 423 Thoughts: **Analyzing the Broadcom Wi-Fi Driver Reachability** Okay, let's break this down. My initial thought was that `brcmf_flowring_block` is the entry point for some interesting code, and it's called by `brcmf_flowring_delete`, `brcmf_flowring_enqueue`, and `brcmf_flowring_dequeue`. Those are defined within `msgbuf.c`. My first assumption was that since `msgbuf.c` deals with PCIe, it would inherently be inaccessible via USB. However, the question then became: "Is `BRCMFMAC_PCIE` actually fuzzed?" I immediately thought of Syzkaller. Does it even have a mechanism to fuzz PCI? I was thinking it *didn't* have a direct `syz_pci_connect` syscall. But wait, it might use `syz_kvm_setup_cpu` or something similar? No, I was wrong again. Syzkaller *does* have PCI fuzzing capabilities! But, based on the context, I remember that it uses `syz_pci_device_add` or focuses on fuzzing PCI config space, and doesn't fully emulate complex vendor-specific PCIe devices, like the Broadcom Wi-Fi implementation. The prompt specifically mentions the difficulty of fuzzing code in vendor-specific PCIe drivers that need real hardware, like the Broadcom PCIe Wi-Fi driver, which is likely not fully emulated in standard QEMU. That's a good point! Okay, so the prompt emphasizes the lack of standard QEMU emulation. That means the USB part *is* likely emulated via USB gadget. So, I need to focus on the USB reachable functions instead, such as `brcmf_cfg80211_set_pmksa`, `brcmf_cfg80211_del_pmksa`, and `brcmf_cfg80211_flush_pmksa`. Those are interesting entry points to target. To make sure this USB-focused approach is correct, I need to verify how the Broadcom driver is configured. I need to check whether `BRCMFMAC_USB` is enabled by default or needs to be specified. Let me check the config options. Okay, `BRCMFMAC_USB` *is* a config option. Now, just to be thorough, I should check whether `BRCMFMAC`, the main config, is enabled. Yes, `BRCMFMAC` is enabled, which means the USB interface is likely active. |
| 28/2 | 2026/08/02 00:59 | tool | grepper |
0mArgs:{
"Expression": "config BRCMFMAC",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:1:config BRCMFMAC\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-2-\ttristate \"Broadcom FullMAC WLAN driver\"\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-10-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:11:config BRCMFMAC_PROTO_BCDC\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-12-\tbool\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-13-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:14:config BRCMFMAC_PROTO_MSGBUF\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-15-\tbool\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-16-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:17:config BRCMFMAC_SDIO\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-18-\tbool \"SDIO bus interface support for FullMAC driver\"\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-28-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:29:config BRCMFMAC_USB\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-30-\tbool \"USB bus interface support for FullMAC driver\"\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-39-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:40:config BRCMFMAC_PCIE\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-41-\tbool \"PCIE bus interface support for FullMAC driver\"\n"
} |
| 29/2 | 2026/08/02 00:59 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 53025 output: 46 thoughts: 63 Thoughts: **Analyzing the Wireless Configuration Landscape** Okay, so I'm looking at these configurations: `BRCMFMAC` and `BRCMFMAC_USB`. Right, makes sense, they seem to be the primary ones for Broadcom's wireless stuff. Wait a second... isn't `BRCMFMAC` tied to `CFG80211` and `MAC80211`? I need to double-check that dependency chain. It's crucial for understanding the driver's architecture. Let's dig into the dependencies of `BRCMFMAC` and see what it relies on. That's where to start to clarify the architecture in use here. |
| 30/2 | 2026/08/02 00:59 | tool | grepper |
0mArgs:{
"Expression": "depends on",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig=1=config BRCMFMAC\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-2-\ttristate \"Broadcom FullMAC WLAN driver\"\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:3:\tdepends on CFG80211\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-4-\tselect BRCMUTIL\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig=17=config BRCMFMAC_SDIO\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-18-\tbool \"SDIO bus interface support for FullMAC driver\"\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:19:\tdepends on (MMC = y || MMC = BRCMFMAC)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:20:\tdepends on BRCMFMAC\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-21-\tselect BRCMFMAC_PROTO_BCDC\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig=29=config BRCMFMAC_USB\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-30-\tbool \"USB bus interface support for FullMAC driver\"\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:31:\tdepends on (USB = y || USB = BRCMFMAC)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:32:\tdepends on BRCMFMAC\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-33-\tselect BRCMFMAC_PROTO_BCDC\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig=40=config BRCMFMAC_PCIE\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-41-\tbool \"PCIE bus interface support for FullMAC driver\"\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:42:\tdepends on BRCMFMAC\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig:43:\tdepends on PCI\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/Kconfig-44-\tselect BRCMFMAC_PROTO_MSGBUF\n"
} |
| 31/2 | 2026/08/02 00:59 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 54027 output: 52 thoughts: 61 Thoughts: **Examining the WiFi Driver Requirements** Okay, so the initial plan calls for these modules: `CFG80211`, `BRCMFMAC`, and `BRCMFMAC_USB`. That seems like a logical starting point for supporting this particular hardware. But hold on a second… isn't there a module called `brcmsmac`? I need to clarify that. It looks like the patch I'm working with is also touching `brcmsmac/ampdu.c`. Given that I should probably double-check exactly what's being altered in that particular file. Time to dive in and see the exact changes. |
| 32/2 | 2026/08/02 00:59 | tool | grepper |
0mArgs:{
"Expression": "brcms_c_ampdu_add_frame",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmsmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c=469=void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c-484- */\ndrivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c:485:int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,\ndrivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.c-486-\t\t\t struct sk_buff *p)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.h=40=void brcms_c_ampdu_reset_session(struct brcms_ampdu_session *session,\ndrivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.h-41-\t\t\t\t struct brcms_c_info *wlc);\ndrivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.h:42:int brcms_c_ampdu_add_frame(struct brcms_ampdu_session *session,\ndrivers/net/wireless/broadcom/brcm80211/brcmsmac/ampdu.h-43-\t\t\t struct sk_buff *p);\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c=1343=static void prep_ampdu_frame(struct dma_info *di, struct sk_buff *p)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c-1347-\ndrivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c:1348:\tret = brcms_c_ampdu_add_frame(session, p);\ndrivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c-1349-\tif (ret == -ENOSPC) {\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c-1354-\t\tampdu_finalize(di);\ndrivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c:1355:\t\tret = brcms_c_ampdu_add_frame(session, p);\ndrivers/net/wireless/broadcom/brcm80211/brcmsmac/dma.c-1356-\t}\n"
} |
| 33/2 | 2026/08/02 00:59 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 54975 output: 47 thoughts: 1079 Thoughts: **Analysis of Recent WiFi Driver Changes for Fuzzing Potential** Okay, so I've been looking at this patch set, and the first thing that jumps out is that the `brcmsmac/ampdu.c` changes are purely cosmetic comments. No functional alterations there, so that's a non-issue from a fuzzing perspective. The real meat lies in the `brcmfmac` changes. Let's break down the `brcmfmac` modifications. In `cfg80211.c`, the key change is replacing delays with `usleep_range` and introducing `brcmf_pmksa_v2_op`. This latter function is triggered by `set_pmksa`, `del_pmksa`, and `flush_pmksa`. Those are interesting entry points. Then, there's `brcmf_netif_mon_rx` in `core.c`, which adds a radiotap header with RSSI data. `flowring.c` has a modification to `brcmf_flowring_block`, related to a per-interface counter. In `msgbuf.c`, `NR_TX_PKTIDS` and related constants are tweaked, and `brcmf_msgbuf_schedule_txdata` is modified with `test_and_set_bit`. Finally, `pcie.c` includes changes to `brcmf_pcie_send_mb_data` for exponential backoff and `sdio.c` has changes to `brcmf_sdio_rxglom` to group `sdio_claim_host` and `sdio_release_host`. Now, considering the driver context, `brcmfmac` is a USB driver, which is a significant factor. I know syzkaller can target USB WiFi drivers using `syz_usb_connect`. Therefore, the `cfg80211.c` changes, including the `pmksa` operations, are definitely reachable. The `sdio.c` and `pcie.c` changes are likely less accessible in a standard QEMU setup, although potentially reachable. Given syzkaller's USB fuzzing capabilities, this makes it a prime candidate for fuzzing. The key focus symbols would be: `brcmf_cfg80211_set_pmksa`, `brcmf_cfg80211_del_pmksa`, and `brcmf_cfg80211_flush_pmksa`. I need to ensure these are part of the target code. I'm also going to check again where `brcmf_delay` is called, specifically looking at `brcmf_cfg80211_sched_scan_stop`. This adds a wider scope for fuzzing. So, **WorthFuzzing=true**. |
| 34/2 | 2026/08/02 00:59 | tool | grepper |
0mArgs:{
"Expression": "brcmf_delay",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=3977=static int brcmf_cfg80211_sched_scan_stop(struct wiphy *wiphy,\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-3989-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:3990:static __always_inline void brcmf_delay(u32 ms)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-3991-{\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=4266=static s32 brcmf_cfg80211_suspend(struct wiphy *wiphy,\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-4303-\t\t\t */\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:4304:\t\t\tbrcmf_delay(500);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-4305-\t\t}\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c=7940=static s32 __brcmf_cfg80211_down(struct brcmf_if *ifp)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-7954-\t\t */\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c:7955:\t\tbrcmf_delay(500);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c-7956-\t}\n"
} |
| 35/2 | 2026/08/02 00:59 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 57301 output: 51 thoughts: 855 Thoughts: **Analyzing Broadcom WiFi Driver for Fuzzing Opportunities** Okay, so I'm looking at this Broadcom WiFi driver code, and my initial thought is, based on the diff, that `brcmf_delay` is called from `brcmf_cfg80211_suspend` and `__brcmf_cfg80211_down`, which are potential entry points. However, the most significant functional change appears to be around `brcmf_pmksa_v2_op`. My immediate question is about reachability. I need to know if `brcmf_sdio_rxglom` is accessible. I know syzkaller doesn't have an SDIO fuzzer set up, and it lacks a specific Broadcom PCIe fuzzer as well. Thus, the prime target should be `cfg80211` callbacks. Therefore, the next step is to nail down the essential configurations. I need to ensure these are enabled: `BRCMFMAC`, `BRCMFMAC_USB`, `CFG80211`, `MAC80211` (given it's typically required with `CFG80211` for Wi-Fi), and `USB`. Now, let's verify these configs to make sure everything lines up. `BRCMFMAC` depends on `CFG80211`, and `BRCMFMAC_USB` depends on both `BRCMFMAC` and `USB`. So, I'll need to list both `BRCMFMAC` and `BRCMFMAC_USB`. Wait, a second, `BRCMFMAC_PCIE` and `BRCMFMAC_SDIO` are also modified. Should I consider them? Even if they're not being fuzzed by default by syzkaller, someone could set up a custom VM with PCI passthrough or SDIO emulation, and these could be fuzzed. Therefore, to be thorough, I should include them: `BRCMFMAC_PCIE`, `BRCMFMAC_SDIO`, and the base dependencies of `PCI` and `MMC`. Now let's check the dependencies. `BRCMFMAC_SDIO` depends on `MMC = y || MMC = BRCMFMAC` and `BRCMFMAC`, which looks good. Similarly, `BRCMFMAC_PCIE` depends on both `BRCMFMAC` and `PCI`. So, the full list of configurations is: `BRCMFMAC`, `BRCMFMAC_USB`, `BRCMFMAC_PCIE`, `BRCMFMAC_SDIO`. I need to quickly double-check that I haven't missed any other potentially relevant configurations. Right, `BRCMFMAC_PROTO_MSGBUF` is selected by `BRCMFMAC_PCIE` and `BRCMFMAC_PROTO_BCDC` is selected by both `BRCMFMAC_USB` and `BRCMFMAC_SDIO`. Now, for focus symbols, the primary candidates appear to be: `brcmf_cfg80211_set_pmksa`, `brcmf_cfg80211_del_pmksa`, and `brcmf_cfg80211_flush_pmksa`, all of which relate directly to the key function mentioned earlier. If PCI somehow is fuzzed I should include `brcmf_netif_mon_rx`, `brcmf_flowring_block`, and `brcmf_msgbuf_schedule_txdata`. Finally, if SDIO is fuzzed, then `brcmf_sdio_rxglom` needs to be in scope. Wait a second, let me check the reachability of `brcmf_netif_mon_rx`. It's called from `brcmf_msgbuf_process_rx_complete`, which is a static function. Also, `brcmf_flowring_block` is called from `brcmf_flowring_enqueue`, `brcmf_flowring_dequeue`, `brcmf_flowring_delete` and `brcmf_msgbuf_schedule_txdata` is called from `brcmf_msgbuf_txdata`, so let me quickly check that. |
| 36/2 | 2026/08/02 01:00 | tool | grepper |
0mError:no matches Args: {
"Expression": "brcmf_msgbuf_txdata",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"error": "no matches"
} |
| 37/2 | 2026/08/02 01:00 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 59156 output: 53 thoughts: 33 Thoughts: Okay, here's my interpretation of that thought process, from an expert's perspective: **Diving into the `msgbuf.c` Rabbit Hole** Alright, that's interesting. I just caught sight of `brcmf_msgbuf_schedule_txdata` while scanning through `msgbuf.c`. My spidey-sense is tingling. That function name sounds like it's crucial for managing transmit data within the Broadcom Wi-Fi driver, probably related to the message buffer system. This definitely warrants a deeper look. My immediate next move is to trace all the call sites of `brcmf_msgbuf_schedule_txdata`. I need to understand what events trigger this function, and what other functions depend on its successful execution. Understanding its call flow is key to understanding its purpose and potential pitfalls within the driver's architecture. I expect I'll find critical insights into how the driver handles data scheduling and transmission, and maybe some opportunities for optimization or debugging. Time to fire up the tools and start digging! |
| 38/2 | 2026/08/02 01:00 | tool | grepper |
0mArgs:{
"Expression": "brcmf_msgbuf_schedule_txdata",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c=805=static void brcmf_msgbuf_txflow_worker(struct work_struct *worker)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-817-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:818:static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-819-\t\t\t\t\tbool force)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c=853=static int brcmf_msgbuf_tx_queue_data(struct brcmf_pub *drvr, int ifidx,\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-874-\tforce = ((queue_count % BRCMF_MSGBUF_TRICKLE_TXWORKER_THRS) == 0);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:875:\tbrcmf_msgbuf_schedule_txdata(msgbuf, flowid, force);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-876-\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c=1286=brcmf_msgbuf_process_flow_ring_create_response(struct brcmf_msgbuf *msgbuf,\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-1309-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:1310:\tbrcmf_msgbuf_schedule_txdata(msgbuf, flowid, true);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-1311-}\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c=1422=int brcmf_proto_msgbuf_rx_trigger(struct device *dev)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-1446-\t\t\t\tBRCMF_MSGBUF_TRICKLE_TXWORKER_THRS)))\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:1447:\t\t\tbrcmf_msgbuf_schedule_txdata(msgbuf, flowid, true);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-1448-\t}\n"
} |
| 39/2 | 2026/08/02 01:00 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 60253 output: 54 thoughts: 44 Thoughts: Here's my take on the thought process, as if it were my own: **Diving into the `brcmf_msgbuf_tx_queue_data` Function** Okay, so I've been tracing the execution flow and I've hit `brcmf_msgbuf_tx_queue_data`. Right, that's an entry point, looking at `msgbuf.c`. My immediate thought is, "Let's dig into that function." Time to examine what's happening within `brcmf_msgbuf_tx_queue_data`, and see how it fits into the broader picture of data transmission within the `brcmf` framework. I need to understand its role in queueing the data, which I'm sure is key to packet delivery. |
| 40/2 | 2026/08/02 01:00 | tool | grepper |
0mArgs:{
"Expression": "brcmf_msgbuf_tx_queue_data",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-94- *\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:95: * TRICKLE_TXWORKER_THRS governs how often brcmf_msgbuf_tx_queue_data()\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-96- * forces a workqueue schedule when the queue depth is not a multiple of\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c=818=static int brcmf_msgbuf_schedule_txdata(struct brcmf_msgbuf *msgbuf, u32 flowid,\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-852-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:853:static int brcmf_msgbuf_tx_queue_data(struct brcmf_pub *drvr, int ifidx,\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-854-\t\t\t\t struct sk_buff *skb)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c=1580=int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-1628-\tdrvr-\u003eproto-\u003eset_dcmd = brcmf_msgbuf_set_dcmd;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c:1629:\tdrvr-\u003eproto-\u003etx_queue_data = brcmf_msgbuf_tx_queue_data;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c-1630-\tdrvr-\u003eproto-\u003econfigure_addr_mode = brcmf_msgbuf_configure_addr_mode;\n"
} |
| 41/2 | 2026/08/02 01:00 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 61100 output: 52 thoughts: 87 Thoughts: Okay, here's my take on those thoughts, framed as my own mental processing: **Analyzing Potential Entry Points in the Broadcom WiFi Driver** Alright, let's see, the code's pointing out that `brcmf_msgbuf_tx_queue_data` is assigned to `drvr->proto->tx_queue_data`. Hmmm, that's a pretty clear indicator of a critical entry point for the transmit path. Definitely something I need to keep in mind and track. I'll make a note and add that function name to my `FocusSymbols` list right away. Gotta keep tabs on these key functions. And while I'm at it, it also mentions `brcmf_sdio_rxglom` as an entry point specifically for SDIO. That's another vital piece of the puzzle. I'll need to dig into `brcmf_sdio_rxglom` and understand its role in handling incoming data over the SDIO interface. It's important to understand this specific entry point, as it shows what happens when we're receiving data! |
| 42/2 | 2026/08/02 01:00 | tool | grepper |
0mArgs:{
"Expression": "brcmf_sdio_rxglom",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c=1487=static void brcmf_sdio_hdpack(struct brcmf_sdio *bus, u8 *header,\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c-1513-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c:1514:static u8 brcmf_sdio_rxglom(struct brcmf_sdio *bus, u8 rxseq)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c-1515-{\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c=1870=static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c-1893-\t\t\t\t bus-\u003eglomd, skb_peek(\u0026bus-\u003eglom));\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c:1894:\t\t\tcnt = brcmf_sdio_rxglom(bus, rd-\u003eseq_num);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c-1895-\t\t\tbrcmf_dbg(GLOM, \"rxglom returned %d\\n\", cnt);\n"
} |
| 43/2 | 2026/08/02 01:00 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 61900 output: 51 thoughts: 32 Thoughts: Here's my take on the thought process, as if it were my own: **Diving into the SDIO Readframe Function** Okay, so the `brcmf_sdio_readframes` function is the initial entry point, the first place my attention needs to go. I need to understand what this does, the overall operation. Time to dig into `brcmf_sdio_readframes` and see what's happening. |
| 44/2 | 2026/08/02 01:00 | tool | grepper |
0mArgs:{
"Expression": "brcmf_sdio_readframes",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c=1858=static void brcmf_sdio_pad(struct brcmf_sdio *bus, u16 *pad, u16 *rdlen)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c-1869-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c:1870:static uint brcmf_sdio_readframes(struct brcmf_sdio *bus, uint maxframes)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c-1871-{\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c=2598=static void brcmf_sdio_dpc(struct brcmf_sdio *bus)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c-2702-\tif ((intstatus \u0026 I_HMB_FRAME_IND) \u0026\u0026 (bus-\u003eclkstate == CLK_AVAIL)) {\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c:2703:\t\tbrcmf_sdio_readframes(bus, bus-\u003erxbound);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c-2704-\t\tif (!bus-\u003erxpending)\n"
} |
| 45/2 | 2026/08/02 01:00 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 62498 output: 51 thoughts: 32 Thoughts: Okay, here's my take on those thoughts, framed as an expert's internal monologue: **Diving into the SDIO DPC** Alright, the system's flagged `brcmf_sdio_dpc` as the entry point, which makes perfect sense. Given this driver architecture, that's where the deferred procedure call processing for the SDIO interface likely initiates. My immediate thought is to zero in on this function to understand the core control flow. Let's start with a deep dive into `brcmf_sdio_dpc` itself. Time to see what it's really doing and uncover how it handles interrupts, data transfers, and general device interaction within the kernel. |
| 46/2 | 2026/08/02 01:00 | tool | grepper |
0mArgs:{
"Expression": "brcmf_sdio_dpc",
"PathPrefix": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/"
}Results: {
"Output": "drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c=2571=static int brcmf_sdio_intr_rstatus(struct brcmf_sdio *bus)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c-2597-\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c:2598:static void brcmf_sdio_dpc(struct brcmf_sdio *bus)\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c-2599-{\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c=3770=static void brcmf_sdio_dataworker(struct work_struct *work)\n--\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c-3778-\t\tbus-\u003edpc_triggered = false;\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c:3779:\t\tbrcmf_sdio_dpc(bus);\ndrivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c-3780-\t\tbus-\u003eidlecount = 0;\n"
} |
| 47/2 | 2026/08/02 01:00 | llm | patch-evaluator |
0mModel:gemini-3.1-pro-preview Args: null Results: null Tokens: input: 63109 output: 265 thoughts: 987 Thoughts: **Analyzing Entry Points for Fuzzing the Broadcom Wi-Fi Driver (brcmfmac)** Okay, let's break this down. My goal here is to identify the best entry points in the `brcmfmac` driver for fuzzing, keeping in mind the need for distinct symbol addresses as the prompt specifies. I'm focusing on functions that are reachable via USB emulation, PCI, or SDIO, depending on the driver configuration. First, I considered `brcmf_sdio_dataworker` and `brcmf_sdio_rxglom`. While `brcmf_sdio_rxglom` is the one that was modified, the prompt makes me think. Since `brcmf_sdio_rxglom` is static, my initial thought is that it might be inlined. I need to be cautious about inlining, as that would negate the goal of finding distinct entry points. I'm checking its size, to see if the compiler is likely to inline it. To be safe, let's keep `brcmf_sdio_dataworker` or `brcmf_sdio_readframes` in consideration. I then shifted my attention to `brcmf_cfg80211_set_pmksa`. This one is static, yes, but crucially, it's assigned to the `cfg80211_ops` struct, which means it won't be inlined. This is good! I'll include `brcmf_cfg80211_set_pmksa`, along with `brcmf_cfg80211_del_pmksa` and `brcmf_cfg80211_flush_pmksa`. These appear to be the main ones that are definitely reachable via USB. Moving on to PCIe, `brcmf_pcie_send_mb_data` looks like a strong possibility. It's called from `brcmf_pcie_tx_ctlpkt` and `brcmf_pcie_rx_ctlpkt`, so I could use either of those. For the final list of potential fuzzing entry points, I have: * `brcmf_cfg80211_set_pmksa` * `brcmf_cfg80211_del_pmksa` * `brcmf_cfg80211_flush_pmksa` * `brcmf_msgbuf_tx_queue_data` * `brcmf_pcie_send_mb_data` * `brcmf_sdio_rxglom` The driver configurations to be kept in mind are `BRCMFMAC`, `BRCMFMAC_USB`, `BRCMFMAC_PCIE`, `BRCMFMAC_SDIO`, `CFG80211`, `MAC80211`, `USB`, `PCI`, and `MMC`. I made sure to note the dependencies: `BRCMFMAC_PCIE` depends on `PCI`, `BRCMFMAC_SDIO` depends on `MMC`, and `BRCMFMAC_USB` depends on `USB`. I also noted that `MAC80211` is not strictly *required* by `BRCMFMAC`, but that `CFG80211` is independent. Finally, I checked `brcmf_pmksa_v2_op`. This is static and called from `brcmf_cfg80211_set_pmksa`, which is also static. However, since `brcmf_cfg80211_set_pmksa` is part of `cfg80211_ops`, it serves as a valid entry point. Based on this analysis, I'm confident in the approach. This patch will result in functional changes to the Broadcom Wi-Fi driver, including V2 PMKSA cache support, flowring blocking logic modifications, an increase in TX packet ID limits, and PCIe/SDIO polling and locking adjustments. The driver is fuzzable via USB emulation (using syz\_usb\_connect) or PCI/SDIO, depending on the configuration. Ready to go. |
| 48/2 | 2026/08/02 01:00 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"BRCMFMAC",
"BRCMFMAC_USB",
"BRCMFMAC_PCIE",
"BRCMFMAC_SDIO",
"CFG80211",
"USB",
"PCI",
"MMC"
],
"FocusSymbols": [
"brcmf_cfg80211_set_pmksa",
"brcmf_cfg80211_del_pmksa",
"brcmf_cfg80211_flush_pmksa",
"brcmf_msgbuf_tx_queue_data",
"brcmf_pcie_send_mb_data",
"brcmf_sdio_rxglom"
],
"Reasoning": "The patch makes functional changes to the Broadcom FullMAC WLAN driver (brcmfmac). It adds support for V2 PMKSA cache operations, modifies flowring blocking logic, increases TX packet ID limits, and adjusts PCIe/SDIO polling and locking. The driver can be fuzzed via USB emulation (syz_usb_connect) as well as PCI/SDIO if configured.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"BRCMFMAC",
"BRCMFMAC_USB",
"BRCMFMAC_PCIE",
"BRCMFMAC_SDIO",
"CFG80211",
"USB",
"PCI",
"MMC"
],
"FocusSymbols": [
"brcmf_cfg80211_set_pmksa",
"brcmf_cfg80211_del_pmksa",
"brcmf_cfg80211_flush_pmksa",
"brcmf_msgbuf_tx_queue_data",
"brcmf_pcie_send_mb_data",
"brcmf_sdio_rxglom"
],
"Reasoning": "The patch makes functional changes to the Broadcom FullMAC WLAN driver (brcmfmac). It adds support for V2 PMKSA cache operations, modifies flowring blocking logic, increases TX packet ID limits, and adjusts PCIe/SDIO polling and locking. The driver can be fuzzed via USB emulation (syz_usb_connect) as well as PCI/SDIO if configured.",
"WorthFuzzing": true
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|