All of lore.kernel.org
 help / color / mirror / Atom feed
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



WARNING: multiple messages have this Message-ID (diff)
From: Michael Reeves <michael.reeves077@gmail.com>
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>

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


  parent reply	other threads:[~2026-09-25 13:43 UTC|newest]

Thread overview: 29+ 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 ` Michael Reeves
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   ` Michael Reeves
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   ` Michael Reeves
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   ` Michael Reeves
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   ` Michael Reeves
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   ` Michael Reeves
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
2026-09-25 13:43 ` Michael Reeves via B4 Relay [this message]
2026-09-25 13:43   ` [PATCH 07/13] wifi: brcmfmac: Use event_msgs_ext for event masks Michael Reeves
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   ` Michael Reeves
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   ` Michael Reeves
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   ` Michael Reeves
2026-09-25 13:43 ` [PATCH 11/13] wifi: brcmfmac: Support versioned join requests Michael Reeves via B4 Relay
2026-09-25 13:43   ` Michael Reeves
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   ` Michael Reeves
2026-09-25 13:43 ` [PATCH 13/13] wifi: brcmfmac: Add BCM4388 support Michael Reeves via B4 Relay
2026-09-25 13:43   ` Michael Reeves
2026-10-07 12:54 ` [PATCH 00/13] " Arend van Spriel

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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.