From: Michael Reeves via B4 Relay <devnull+michael.reeves077.gmail.com@kernel.org>
To: Arend van Spriel <arend.vanspriel@broadcom.com>,
Pieter-Paul Giesberts <pieterpg@broadcom.com>,
"Franky Lin (Zhenhui)" <frankyl@broadcom.com>,
Mathy Vanhoef <vanhoefm@gmail.com>,
Kalle Valo <kvalo@kernel.org>, Kees Cook <kees@kernel.org>,
"Gustavo A. R. Silva" <gustavoars@kernel.org>
Cc: linux-wireless@vger.kernel.org, brcm80211@lists.linux.dev,
brcm80211-dev-list.pdl@broadcom.com, asahi@lists.linux.dev,
Hector Martin <marcan@marcan.st>,
Daniel Berlin <dberlin@dberlin.org>, Janne Grunau <j@jannau.net>,
linux-kernel@vger.kernel.org,
Hante Meuleman <meuleman@broadcom.com>,
linux-hardening@vger.kernel.org,
Michael Reeves <michael.reeves077@gmail.com>
Subject: [PATCH 07/13] wifi: brcmfmac: Use event_msgs_ext for event masks
Date: Fri, 25 Sep 2026 23:43:42 +1000 [thread overview]
Message-ID: <20260925-brcm4388-submit-v1-7-b5cbc2cde2fb@gmail.com> (raw)
In-Reply-To: <20260925-brcm4388-submit-v1-0-b5cbc2cde2fb@gmail.com>
From: Michael Reeves <michael.reeves077@gmail.com>
BCM4388 firmware rejects the legacy event_msgs query during preinit but
supports the structured event_msgs_ext command.
Probe event_msgs_ext during feature detection and initialize the event
mask after feature flags are set. Use the extended command when
supported and retain the legacy path otherwise.
Co-developed-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Hector Martin <marcan@marcan.st>
Signed-off-by: Michael Reeves <michael.reeves077@gmail.com>
---
.../wireless/broadcom/brcm80211/brcmfmac/common.c | 23 ----
.../wireless/broadcom/brcm80211/brcmfmac/core.c | 5 +-
.../wireless/broadcom/brcm80211/brcmfmac/feature.c | 39 +++++++
.../wireless/broadcom/brcm80211/brcmfmac/feature.h | 2 +
.../wireless/broadcom/brcm80211/brcmfmac/fweh.c | 130 ++++++++++++++++++++-
.../wireless/broadcom/brcm80211/brcmfmac/fweh.h | 1 +
.../broadcom/brcm80211/brcmfmac/fwil_types.h | 26 +++++
7 files changed, 199 insertions(+), 27 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
index 2a37b42ca9..93458c2fbc 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/common.c
@@ -269,7 +269,6 @@ static int brcmf_c_process_cal_blob(struct brcmf_if *ifp)
int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
{
struct brcmf_pub *drvr = ifp->drvr;
- struct brcmf_fweh_info *fweh = drvr->fweh;
u8 buf[BRCMF_DCMD_SMLEN];
struct brcmf_bus *bus;
struct brcmf_rev_info_le revinfo;
@@ -415,27 +414,6 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
brcmf_c_set_joinpref_default(ifp);
- /* Setup event_msgs, enable E_IF */
- err = brcmf_fil_iovar_data_get(ifp, "event_msgs", fweh->event_mask,
- fweh->event_mask_len);
- if (err) {
- bphy_err(drvr, "Get event_msgs error (%d)\n", err);
- goto done;
- }
- /*
- * BRCMF_E_IF can safely be used to set the appropriate bit
- * in the event_mask as the firmware event code is guaranteed
- * to match the value of BRCMF_E_IF because it is old cruft
- * that all vendors have.
- */
- setbit(fweh->event_mask, BRCMF_E_IF);
- err = brcmf_fil_iovar_data_set(ifp, "event_msgs", fweh->event_mask,
- fweh->event_mask_len);
- if (err) {
- bphy_err(drvr, "Set event_msgs error (%d)\n", err);
- goto done;
- }
-
/* Setup default scan channel time */
err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME,
BRCMF_DEFAULT_SCAN_CHANNEL_TIME);
@@ -637,4 +615,3 @@ static void __exit brcmfmac_module_exit(void)
module_init(brcmfmac_module_init);
module_exit(brcmfmac_module_exit);
-
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index d2ae679856..bb9a0aeb06 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -1260,6 +1260,10 @@ static int brcmf_bus_started(struct brcmf_pub *drvr, struct cfg80211_ops *ops)
brcmf_feat_attach(drvr);
+ ret = brcmf_fweh_init_events(ifp);
+ if (ret < 0)
+ goto fail;
+
ret = brcmf_proto_init_done(drvr);
if (ret < 0)
goto fail;
@@ -1613,4 +1617,3 @@ void __exit brcmf_core_exit(void)
brcmf_usb_exit();
brcmf_pcie_exit();
}
-
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
index a3c221117d..d289451644 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
@@ -5,6 +5,7 @@
#include <linux/netdevice.h>
#include <linux/module.h>
+#include <linux/slab.h>
#include <brcm_hw_ids.h>
#include <brcmu_wifi.h>
@@ -226,6 +227,43 @@ static void brcmf_feat_iovar_data_set(struct brcmf_if *ifp,
ifp->fwil_fwerr = false;
}
+static void brcmf_feat_event_msgs_ext(struct brcmf_if *ifp)
+{
+ struct brcmf_pub *drvr = ifp->drvr;
+ struct brcmf_fweh_info *fweh = drvr->fweh;
+ struct brcmf_eventmsgs_ext_le *eventmsgs;
+ size_t size;
+ int err;
+
+ if (!fweh || fweh->event_mask_len > 0xff)
+ return;
+
+ size = struct_size(eventmsgs, mask, fweh->event_mask_len);
+ eventmsgs = kzalloc(size, GFP_KERNEL);
+ if (!eventmsgs)
+ return;
+
+ eventmsgs->version = EVENTMSGS_VER;
+ eventmsgs->command = EVENTMSGS_NONE;
+ eventmsgs->len = fweh->event_mask_len;
+ eventmsgs->maxgetsize = fweh->event_mask_len;
+
+ ifp->fwil_fwerr = true;
+ err = brcmf_fil_iovar_data_get(ifp, "event_msgs_ext", eventmsgs, size);
+ ifp->fwil_fwerr = false;
+
+ if (!err) {
+ brcmf_dbg(INFO, "enabling feature: %s\n",
+ brcmf_feat_names[BRCMF_FEAT_EVENT_MSGS_EXT]);
+ drvr->feat_flags |= BIT(BRCMF_FEAT_EVENT_MSGS_EXT);
+ } else {
+ brcmf_dbg(TRACE, "%s feature check failed: %d\n",
+ brcmf_feat_names[BRCMF_FEAT_EVENT_MSGS_EXT], err);
+ }
+
+ kfree(eventmsgs);
+}
+
#define MAX_CAPS_BUFFER_SIZE 768
static void brcmf_feat_firmware_capabilities(struct brcmf_if *ifp)
{
@@ -348,6 +386,7 @@ void brcmf_feat_attach(struct brcmf_pub *drvr)
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_FWSUP, "sup_wpa");
brcmf_feat_iovar_int_get(ifp, BRCMF_FEAT_SCAN_V2, "scan_ver");
+ brcmf_feat_event_msgs_ext(ifp);
brcmf_feat_wlc_version_overrides(drvr);
brcmf_feat_firmware_overrides(drvr);
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
index 8165a286b6..45a05642bb 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
@@ -31,6 +31,7 @@
* FWAUTH: Firmware authenticator
* DUMP_OBSS: Firmware has capable to dump obss info to support ACS
* SCAN_V2: Version 2 scan params
+ * EVENT_MSGS_EXT: Firmware supports event_msgs_ext for event masks
* SAE_EXT: SAE authentication handled by user-space supplicant
*/
#define BRCMF_FEAT_LIST \
@@ -59,6 +60,7 @@
BRCMF_FEAT_DEF(SCAN_V2) \
BRCMF_FEAT_DEF(PMKID_V2) \
BRCMF_FEAT_DEF(PMKID_V3) \
+ BRCMF_FEAT_DEF(EVENT_MSGS_EXT) \
BRCMF_FEAT_DEF(SAE_EXT) \
BRCMF_FEAT_DEF(FBT) \
BRCMF_FEAT_DEF(OKC)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
index 1cff4ba769..034f90ad6c 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.c
@@ -12,7 +12,9 @@
#include "debug.h"
#include "tracepoint.h"
#include "fweh.h"
+#include "feature.h"
#include "fwil.h"
+#include "fwil_types.h"
#include "proto.h"
#include "bus.h"
#include "fwvid.h"
@@ -430,6 +432,128 @@ void brcmf_fweh_unregister(struct brcmf_pub *drvr,
drvr->fweh->evt_handler[evt_handler_idx] = NULL;
}
+static bool brcmf_fweh_use_event_msgs_ext(struct brcmf_if *ifp)
+{
+ return brcmf_feat_is_enabled(ifp, BRCMF_FEAT_EVENT_MSGS_EXT);
+}
+
+static const char *brcmf_fweh_event_mask_iovar(struct brcmf_if *ifp)
+{
+ return brcmf_fweh_use_event_msgs_ext(ifp) ? "event_msgs_ext" :
+ "event_msgs";
+}
+
+static int brcmf_fweh_get_event_mask(struct brcmf_if *ifp)
+{
+ struct brcmf_pub *drvr = ifp->drvr;
+ struct brcmf_fweh_info *fweh = drvr->fweh;
+ struct brcmf_eventmsgs_ext_le *eventmsgs;
+ size_t size;
+ u8 fw_len;
+ int err;
+
+ memset(fweh->event_mask, 0, fweh->event_mask_len);
+
+ if (!brcmf_fweh_use_event_msgs_ext(ifp))
+ return brcmf_fil_iovar_data_get(ifp, "event_msgs",
+ fweh->event_mask,
+ fweh->event_mask_len);
+
+ if (fweh->event_mask_len > 0xff)
+ return -E2BIG;
+
+ size = struct_size(eventmsgs, mask, fweh->event_mask_len);
+ eventmsgs = kzalloc(size, GFP_KERNEL);
+ if (!eventmsgs)
+ return -ENOMEM;
+
+ eventmsgs->version = EVENTMSGS_VER;
+ eventmsgs->command = EVENTMSGS_NONE;
+ eventmsgs->len = fweh->event_mask_len;
+ eventmsgs->maxgetsize = fweh->event_mask_len;
+
+ err = brcmf_fil_iovar_data_get(ifp, "event_msgs_ext", eventmsgs, size);
+ if (!err) {
+ fw_len = eventmsgs->len;
+ memcpy(fweh->event_mask, eventmsgs->mask,
+ min_t(u8, fw_len, fweh->event_mask_len));
+ if (fw_len != fweh->event_mask_len)
+ brcmf_dbg(EVENT, "event_msgs_ext returned mask len=%u, driver len=%u\n",
+ fw_len, fweh->event_mask_len);
+ }
+
+ kfree(eventmsgs);
+ return err;
+}
+
+static int brcmf_fweh_set_event_mask(struct brcmf_if *ifp)
+{
+ struct brcmf_pub *drvr = ifp->drvr;
+ struct brcmf_fweh_info *fweh = drvr->fweh;
+ struct brcmf_eventmsgs_ext_le *eventmsgs;
+ size_t size;
+ int err;
+
+ if (!brcmf_fweh_use_event_msgs_ext(ifp))
+ return brcmf_fil_iovar_data_set(ifp, "event_msgs",
+ fweh->event_mask,
+ fweh->event_mask_len);
+
+ if (fweh->event_mask_len > 0xff)
+ return -E2BIG;
+
+ size = struct_size(eventmsgs, mask, fweh->event_mask_len);
+ eventmsgs = kzalloc(size, GFP_KERNEL);
+ if (!eventmsgs)
+ return -ENOMEM;
+
+ eventmsgs->version = EVENTMSGS_VER;
+ eventmsgs->command = EVENTMSGS_SET_MASK;
+ eventmsgs->len = fweh->event_mask_len;
+ memcpy(eventmsgs->mask, fweh->event_mask, fweh->event_mask_len);
+
+ err = brcmf_fil_iovar_data_set(ifp, "event_msgs_ext", eventmsgs, size);
+
+ kfree(eventmsgs);
+ return err;
+}
+
+/**
+ * brcmf_fweh_init_events() - initialize firmware event mask.
+ *
+ * @ifp: primary interface object.
+ */
+int brcmf_fweh_init_events(struct brcmf_if *ifp)
+{
+ struct brcmf_pub *drvr = ifp->drvr;
+ struct brcmf_fweh_info *fweh = drvr->fweh;
+ const char *iovar = brcmf_fweh_event_mask_iovar(ifp);
+ int err;
+
+ brcmf_dbg(EVENT, "using %s for firmware event masks (len=%u)\n", iovar,
+ fweh->event_mask_len);
+
+ err = brcmf_fweh_get_event_mask(ifp);
+ if (err) {
+ bphy_err(drvr, "Get %s error (%d)\n", iovar, err);
+ return err;
+ }
+
+ /*
+ * BRCMF_E_IF can safely be used to set the appropriate bit in the
+ * event mask as the firmware event code is guaranteed to match the
+ * value of BRCMF_E_IF because it is old cruft that all vendors have.
+ */
+ brcmf_dbg(EVENT, "enable event IF\n");
+ setbit(fweh->event_mask, BRCMF_E_IF);
+
+ err = brcmf_fweh_set_event_mask(ifp);
+ if (err)
+ bphy_err(drvr, "Set %s error (%d)\n", iovar, err);
+
+ return err;
+}
+
/**
* brcmf_fweh_activate_events() - enables firmware events registered.
*
@@ -439,6 +563,7 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp)
{
struct brcmf_fweh_info *fweh = ifp->drvr->fweh;
enum brcmf_fweh_event_code code;
+ const char *iovar = brcmf_fweh_event_mask_iovar(ifp);
int i, err;
memset(fweh->event_mask, 0, fweh->event_mask_len);
@@ -459,10 +584,9 @@ int brcmf_fweh_activate_events(struct brcmf_if *ifp)
if (!brcmf_fwvid_activate_events(ifp))
return 0;
- err = brcmf_fil_iovar_data_set(ifp, "event_msgs", fweh->event_mask,
- fweh->event_mask_len);
+ err = brcmf_fweh_set_event_mask(ifp);
if (err)
- bphy_err(fweh->drvr, "Set event_msgs error (%d)\n", err);
+ bphy_err(fweh->drvr, "Set %s error (%d)\n", iovar, err);
return err;
}
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
index e327dd58d2..53c4b58e63 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
@@ -356,6 +356,7 @@ int brcmf_fweh_register(struct brcmf_pub *drvr, enum brcmf_fweh_event_code code,
void *data));
void brcmf_fweh_unregister(struct brcmf_pub *drvr,
enum brcmf_fweh_event_code code);
+int brcmf_fweh_init_events(struct brcmf_if *ifp);
int brcmf_fweh_activate_events(struct brcmf_if *ifp);
void brcmf_fweh_process_event(struct brcmf_pub *drvr,
struct brcmf_event *event_packet,
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
index e74a23e118..d591f17960 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
@@ -1236,4 +1236,30 @@ struct brcmf_mkeep_alive_pkt_le {
u8 data[];
} __packed;
+enum event_msgs_ext_command {
+ EVENTMSGS_NONE = 0,
+ EVENTMSGS_SET_BIT = 1,
+ EVENTMSGS_RESET_BIT = 2,
+ EVENTMSGS_SET_MASK = 3,
+};
+
+#define EVENTMSGS_VER 1
+
+/**
+ * struct brcmf_eventmsgs_ext_le - event_msgs_ext iovar data
+ *
+ * @version: structure version.
+ * @command: requested operation.
+ * @len: mask size for set, actual firmware mask size for get.
+ * @maxgetsize: maximum mask size that may be returned by firmware.
+ * @mask: event mask.
+ */
+struct brcmf_eventmsgs_ext_le {
+ u8 version;
+ u8 command;
+ u8 len;
+ u8 maxgetsize;
+ u8 mask[] __counted_by(len);
+};
+
#endif /* FWIL_TYPES_H_ */
--
2.55.0
next prev parent reply other threads:[~2026-09-25 13:43 UTC|newest]
Thread overview: 14+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-25 13:43 [PATCH 00/13] wifi: brcmfmac: Add BCM4388 support Michael Reeves via B4 Relay
2026-09-25 13:43 ` [PATCH 01/13] wifi: brcmfmac: pcie: Report the detected chip ID to the bus Michael Reeves via B4 Relay
2026-09-25 13:43 ` [PATCH 02/13] wifi: brcmfmac: Match complete firmware capability names Michael Reeves via B4 Relay
2026-09-25 13:43 ` [PATCH 03/13] wifi: brcmfmac: Fall back to RSSI-only default join preferences Michael Reeves via B4 Relay
2026-09-25 13:43 ` [PATCH 04/13] wifi: brcmfmac: Support newer PCIe core startup and interrupts Michael Reeves via B4 Relay
2026-09-25 13:43 ` [PATCH 05/13] wifi: brcmfmac: Negotiate PCIe mailbox transport with firmware Michael Reeves via B4 Relay
2026-09-25 13:43 ` [PATCH 06/13] wifi: brcmfmac: Load signed PCIe firmware images Michael Reeves via B4 Relay
2026-09-25 13:43 ` Michael Reeves via B4 Relay [this message]
2026-09-25 13:43 ` [PATCH 08/13] wifi: brcmfmac: Handle larger firmware band lists Michael Reeves via B4 Relay
2026-09-25 13:43 ` [PATCH 09/13] wifi: brcmfmac: Accept newer BSS information versions Michael Reeves via B4 Relay
2026-09-25 13:43 ` [PATCH 10/13] wifi: brcmfmac: Support versioned scan parameter layouts Michael Reeves via B4 Relay
2026-09-25 13:43 ` [PATCH 11/13] wifi: brcmfmac: Support versioned join requests Michael Reeves via B4 Relay
2026-09-25 13:43 ` [PATCH 12/13] wifi: brcmfmac: Handle extended PMK command payloads Michael Reeves via B4 Relay
2026-09-25 13:43 ` [PATCH 13/13] wifi: brcmfmac: Add BCM4388 support Michael Reeves via B4 Relay
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260925-brcm4388-submit-v1-7-b5cbc2cde2fb@gmail.com \
--to=devnull+michael.reeves077.gmail.com@kernel.org \
--cc=arend.vanspriel@broadcom.com \
--cc=asahi@lists.linux.dev \
--cc=brcm80211-dev-list.pdl@broadcom.com \
--cc=brcm80211@lists.linux.dev \
--cc=dberlin@dberlin.org \
--cc=frankyl@broadcom.com \
--cc=gustavoars@kernel.org \
--cc=j@jannau.net \
--cc=kees@kernel.org \
--cc=kvalo@kernel.org \
--cc=linux-hardening@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
--cc=marcan@marcan.st \
--cc=meuleman@broadcom.com \
--cc=michael.reeves077@gmail.com \
--cc=pieterpg@broadcom.com \
--cc=vanhoefm@gmail.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®