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 05/13] wifi: brcmfmac: Negotiate PCIe mailbox transport with firmware
Date: Fri, 25 Sep 2026 23:43:40 +1000 [thread overview]
Message-ID: <20260925-brcm4388-submit-v1-5-b5cbc2cde2fb@gmail.com> (raw)
In-Reply-To: <20260925-brcm4388-submit-v1-0-b5cbc2cde2fb@gmail.com>
From: Hector Martin <marcan@marcan.st>
Shared protocol version 6 and later allows mailbox messages over the
control ring as an alternative to the shared-memory mailbox.
Advertise host capabilities using the negotiated shared protocol
version. Select the control-ring transport when firmware does not set
BRCMF_PCIE_SHARED_USE_MAILBOX, and dispatch received mailbox data
through bus operations.
Signed-off-by: Hector Martin <marcan@marcan.st>
Co-developed-by: Michael Reeves <michael.reeves077@gmail.com>
Signed-off-by: Michael Reeves <michael.reeves077@gmail.com>
---
.../net/wireless/broadcom/brcm80211/brcmfmac/bus.h | 9 +++
.../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 57 +++++++++++++++
.../wireless/broadcom/brcm80211/brcmfmac/msgbuf.h | 5 ++
.../wireless/broadcom/brcm80211/brcmfmac/pcie.c | 83 ++++++++++++++++++----
4 files changed, 139 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
index 9371c14899..421039759b 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bus.h
@@ -86,6 +86,8 @@ struct brcmf_bus_dcmd {
* @get_ramsize: obtain size of device memory.
* @get_memdump: obtain device memory dump in provided buffer.
* @get_blob: obtain a firmware blob.
+ * @d2h_mb_rx: handle device-to-host mailbox data received through a transport
+ * specific side channel.
* @remove: initiate unbind of the device.
*
* This structure provides an abstract interface towards the
@@ -108,6 +110,7 @@ struct brcmf_bus_ops {
void (*debugfs_create)(struct device *dev);
int (*reset)(struct device *dev);
void (*remove)(struct device *dev);
+ void (*d2h_mb_rx)(struct device *dev, u32 data);
};
@@ -292,6 +295,12 @@ static inline void brcmf_bus_remove(struct brcmf_bus *bus)
bus->ops->remove(bus->dev);
}
+static inline void brcmf_bus_d2h_mb_rx(struct brcmf_bus *bus, u32 data)
+{
+ if (bus->ops->d2h_mb_rx)
+ bus->ops->d2h_mb_rx(bus->dev, data);
+}
+
/*
* interface functions from common layer
*/
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
index 069ba70166..8e5c697e7f 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
@@ -47,6 +47,8 @@
#define MSGBUF_TYPE_RX_CMPLT 0x12
#define MSGBUF_TYPE_LPBK_DMAXFER 0x13
#define MSGBUF_TYPE_LPBK_DMAXFER_CMPLT 0x14
+#define MSGBUF_TYPE_H2D_MAILBOX_DATA 0x23
+#define MSGBUF_TYPE_D2H_MAILBOX_DATA 0x24
#define NR_TX_PKTIDS 2048
#define NR_RX_PKTIDS 1024
@@ -218,6 +220,19 @@ struct msgbuf_flowring_flush_resp {
__le32 rsvd0[3];
};
+struct msgbuf_h2d_mailbox_data {
+ struct msgbuf_common_hdr msg;
+ __le32 data;
+ __le32 rsvd0[7];
+};
+
+struct msgbuf_d2h_mailbox_data {
+ struct msgbuf_common_hdr msg;
+ struct msgbuf_completion_hdr compl_hdr;
+ __le32 data;
+ __le32 rsvd0[2];
+};
+
struct brcmf_msgbuf_work_item {
struct list_head queue;
u32 flowid;
@@ -1319,6 +1334,15 @@ brcmf_msgbuf_process_flow_ring_delete_response(struct brcmf_msgbuf *msgbuf,
brcmf_msgbuf_remove_flowring(msgbuf, flowid);
}
+static void brcmf_msgbuf_process_d2h_mailbox_data(struct brcmf_msgbuf *msgbuf,
+ void *buf)
+{
+ struct msgbuf_d2h_mailbox_data *d2h_mb_data = buf;
+
+ brcmf_bus_d2h_mb_rx(msgbuf->drvr->bus_if,
+ le32_to_cpu(d2h_mb_data->data));
+}
+
static void brcmf_msgbuf_process_msgtype(struct brcmf_msgbuf *msgbuf, void *buf)
{
@@ -1362,6 +1386,10 @@ static void brcmf_msgbuf_process_msgtype(struct brcmf_msgbuf *msgbuf, void *buf)
brcmf_dbg(MSGBUF, "MSGBUF_TYPE_RX_CMPLT\n");
brcmf_msgbuf_process_rx_complete(msgbuf, buf);
break;
+ case MSGBUF_TYPE_D2H_MAILBOX_DATA:
+ brcmf_dbg(MSGBUF, "MSGBUF_TYPE_D2H_MAILBOX_DATA\n");
+ brcmf_msgbuf_process_d2h_mailbox_data(msgbuf, buf);
+ break;
default:
bphy_err(drvr, "Unsupported msgtype %d\n", msg->msgtype);
break;
@@ -1500,6 +1528,35 @@ void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid)
}
}
+int brcmf_msgbuf_h2d_mb_write(struct brcmf_pub *drvr, u32 data)
+{
+ struct brcmf_msgbuf *msgbuf = (struct brcmf_msgbuf *)drvr->proto->pd;
+ struct brcmf_commonring *commonring;
+ struct msgbuf_h2d_mailbox_data *request;
+ void *ret_ptr;
+ int err;
+
+ commonring = msgbuf->commonrings[BRCMF_H2D_MSGRING_CONTROL_SUBMIT];
+ brcmf_commonring_lock(commonring);
+ ret_ptr = brcmf_commonring_reserve_for_write(commonring);
+ if (!ret_ptr) {
+ bphy_err(drvr, "Failed to reserve space in commonring\n");
+ brcmf_commonring_unlock(commonring);
+ return -ENOMEM;
+ }
+
+ request = (struct msgbuf_h2d_mailbox_data *)ret_ptr;
+ memset(request, 0, sizeof(*request));
+ request->msg.msgtype = MSGBUF_TYPE_H2D_MAILBOX_DATA;
+ request->msg.ifidx = 0xff;
+ request->data = cpu_to_le32(data);
+
+ err = brcmf_commonring_write_complete(commonring);
+ brcmf_commonring_unlock(commonring);
+
+ return err;
+}
+
#ifdef DEBUG
static int brcmf_msgbuf_stats_read(struct seq_file *seq, void *data)
{
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
index 6a849f4a94..18b56d0789 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.h
@@ -32,12 +32,17 @@ int brcmf_proto_msgbuf_rx_trigger(struct device *dev);
void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u16 flowid);
int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr);
void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr);
+int brcmf_msgbuf_h2d_mb_write(struct brcmf_pub *drvr, u32 data);
#else
static inline int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr)
{
return 0;
}
static inline void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr) {}
+static inline int brcmf_msgbuf_h2d_mb_write(struct brcmf_pub *drvr, u32 data)
+{
+ return -EOPNOTSUPP;
+}
#endif
#endif /* BRCMFMAC_MSGBUF_H */
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
index 5917ee5fd7..ad8567e2b9 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/pcie.c
@@ -219,9 +219,13 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
#define BRCMF_PCIE_SHARED_VERSION_MASK 0x00FF
#define BRCMF_PCIE_SHARED_DMA_INDEX 0x10000
#define BRCMF_PCIE_SHARED_DMA_2B_IDX 0x100000
+#define BRCMF_PCIE_SHARED_USE_MAILBOX 0x2000000
#define BRCMF_PCIE_SHARED_HOSTRDY_DB1 0x10000000
#define BRCMF_PCIE_SHARED_DAR 0x80000000
+#define BRCMF_HOSTCAP_H2D_ENABLE_HOSTRDY 0x400
+#define BRCMF_HOSTCAP_DS_NO_OOB_DW 0x1000
+#define BRCMF_HOSTCAP_H2D_DAR 0x10000
#define BRCMF_PCIE_FLAGS_HTOD_SPLIT 0x4000
#define BRCMF_PCIE_FLAGS_DTOH_SPLIT 0x8000
@@ -237,6 +241,8 @@ static const struct brcmf_firmware_mapping brcmf_pcie_fwnames[] = {
#define BRCMF_SHARED_DMA_SCRATCH_ADDR_OFFSET 56
#define BRCMF_SHARED_DMA_RINGUPD_LEN_OFFSET 64
#define BRCMF_SHARED_DMA_RINGUPD_ADDR_OFFSET 68
+#define BRCMF_SHARED_HOST_CAP_OFFSET 84
+#define BRCMF_SHARED_HOST_CAP2_OFFSET 112
#define BRCMF_RING_H2D_RING_COUNT_OFFSET 0
#define BRCMF_RING_D2H_RING_COUNT_OFFSET 1
@@ -318,6 +324,7 @@ struct brcmf_pcie_shared_info {
void *ringupd;
dma_addr_t ringupd_dmahandle;
u8 version;
+ bool mb_via_ctl;
};
#define BRCMF_OTP_MAX_PARAM_LEN 16
@@ -843,6 +850,18 @@ brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)
u32 i;
shared = &devinfo->shared;
+ if (shared->mb_via_ctl) {
+ struct pci_dev *pdev = devinfo->pdev;
+ struct brcmf_bus *bus = dev_get_drvdata(&pdev->dev);
+ int ret;
+
+ ret = brcmf_msgbuf_h2d_mb_write(bus->drvr, htod_mb_data);
+ if (ret < 0)
+ brcmf_err(bus, "Failed to send H2D mailbox data (%d)\n",
+ ret);
+ return ret;
+ }
+
addr = shared->htod_mb_data_addr;
cur_htod_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
@@ -871,21 +890,9 @@ brcmf_pcie_send_mb_data(struct brcmf_pciedev_info *devinfo, u32 htod_mb_data)
}
-static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo)
+static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo,
+ u32 dtoh_mb_data)
{
- struct brcmf_pcie_shared_info *shared;
- u32 addr;
- u32 dtoh_mb_data;
-
- shared = &devinfo->shared;
- addr = shared->dtoh_mb_data_addr;
- dtoh_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
-
- if (!dtoh_mb_data)
- return;
-
- brcmf_pcie_write_tcm32(devinfo, addr, 0);
-
brcmf_dbg(PCIE, "D2H_MB_DATA: 0x%04x\n", dtoh_mb_data);
if (dtoh_mb_data & BRCMF_D2H_DEV_DS_ENTER_REQ) {
brcmf_dbg(PCIE, "D2H_MB_DATA: DEEP SLEEP REQ\n");
@@ -906,6 +913,32 @@ static void brcmf_pcie_handle_mb_data(struct brcmf_pciedev_info *devinfo)
}
+static void brcmf_pcie_poll_mb_data(struct brcmf_pciedev_info *devinfo)
+{
+ struct brcmf_pcie_shared_info *shared;
+ u32 addr;
+ u32 dtoh_mb_data;
+
+ shared = &devinfo->shared;
+ addr = shared->dtoh_mb_data_addr;
+ dtoh_mb_data = brcmf_pcie_read_tcm32(devinfo, addr);
+
+ if (!dtoh_mb_data)
+ return;
+
+ brcmf_pcie_write_tcm32(devinfo, addr, 0);
+
+ brcmf_pcie_handle_mb_data(devinfo, dtoh_mb_data);
+}
+
+static void brcmf_pcie_d2h_mb_rx(struct device *dev, u32 data)
+{
+ struct brcmf_bus *bus = dev_get_drvdata(dev);
+ struct brcmf_pciedev *buspub = bus->bus_priv.pcie;
+
+ brcmf_pcie_handle_mb_data(buspub->devinfo, data);
+}
+
static void brcmf_pcie_bus_console_init(struct brcmf_pciedev_info *devinfo)
{
struct brcmf_pcie_shared_info *shared;
@@ -1042,7 +1075,7 @@ static irqreturn_t brcmf_pcie_isr_thread(int irq, void *arg)
if (status) {
brcmf_pcie_write_pcie32(devinfo, devinfo->reginfo->mailboxint, status);
if (status & devinfo->reginfo->int_fn0)
- brcmf_pcie_handle_mb_data(devinfo);
+ brcmf_pcie_poll_mb_data(devinfo);
}
if (devinfo->have_msi || status & devinfo->reginfo->int_d2h_db) {
if (devinfo->state == BRCMFMAC_PCIE_STATE_UP)
@@ -1695,6 +1728,7 @@ static const struct brcmf_bus_ops brcmf_pcie_bus_ops = {
.get_blob = brcmf_pcie_get_blob,
.reset = brcmf_pcie_reset,
.debugfs_create = brcmf_pcie_debugfs_create,
+ .d2h_mb_rx = brcmf_pcie_d2h_mb_rx,
};
@@ -1726,6 +1760,7 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
{
struct brcmf_bus *bus = dev_get_drvdata(&devinfo->pdev->dev);
struct brcmf_pcie_shared_info *shared;
+ u32 host_cap;
u32 addr;
shared = &devinfo->shared;
@@ -1766,6 +1801,24 @@ brcmf_pcie_init_share_ram_info(struct brcmf_pciedev_info *devinfo,
addr = sharedram_addr + BRCMF_SHARED_RING_INFO_ADDR_OFFSET;
shared->ring_info_addr = brcmf_pcie_read_tcm32(devinfo, addr);
+ if (shared->version >= 6) {
+ shared->mb_via_ctl =
+ !(shared->flags & BRCMF_PCIE_SHARED_USE_MAILBOX);
+
+ host_cap = shared->version;
+ if (shared->flags & BRCMF_PCIE_SHARED_HOSTRDY_DB1)
+ host_cap |= BRCMF_HOSTCAP_H2D_ENABLE_HOSTRDY;
+ if (shared->flags & BRCMF_PCIE_SHARED_DAR)
+ host_cap |= BRCMF_HOSTCAP_H2D_DAR;
+ host_cap |= BRCMF_HOSTCAP_DS_NO_OOB_DW;
+
+ brcmf_pcie_write_tcm32(devinfo, sharedram_addr +
+ BRCMF_SHARED_HOST_CAP_OFFSET,
+ host_cap);
+ brcmf_pcie_write_tcm32(devinfo, sharedram_addr +
+ BRCMF_SHARED_HOST_CAP2_OFFSET, 0);
+ }
+
brcmf_dbg(PCIE, "max rx buf post %d, rx dataoffset %d\n",
shared->max_rxbufpost, shared->rx_dataoffset);
--
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 ` Michael Reeves via B4 Relay [this message]
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 ` [PATCH 07/13] wifi: brcmfmac: Use event_msgs_ext for event masks Michael Reeves via B4 Relay
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-5-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®