From: Ragul Balaji <ragulbaby@gmail.com>
To: linux-wireless@vger.kernel.org
Cc: Arend van Spriel <arend.vanspriel@broadcom.com>,
Johannes Berg <johannes@sipsolutions.net>,
brcm80211@lists.linux.dev, Ragul Balaji <ragulbaby@gmail.com>,
Ho Jie Feng <hjf3108@gmail.com>,
linux-kernel@vger.kernel.org,
brcm80211-dev-list.pdl@broadcom.com
Subject: [RFC PATCH wireless-next 12/17] wifi: bcm4323x: add the USB transport and firmware setup
Date: Mon, 26 Oct 2026 13:36:18 +0800 [thread overview]
Message-ID: <20261026053633.361454-13-ragulbaby@gmail.com> (raw)
In-Reply-To: <20261026053633.361454-1-ragulbaby@gmail.com>
Adds the usb side of the driver, enumeration, tx/rx and
firmware. Requires brcm/bcm4323x.bin.
The ID table covers the BCM43231 and BCM4323 adapters of
Belkin, Dynex and Netgear.
Signed-off-by: Ragul Balaji <ragulbaby@gmail.com>
Signed-off-by: Ho Jie Feng <hjf3108@gmail.com>
---
.../brcm80211/bcm4323x/bcm4323x_core.c | 545 ++++++++++++++++++
1 file changed, 545 insertions(+)
create mode 100644 drivers/net/wireless/broadcom/brcm80211/bcm4323x/bcm4323x_core.c
diff --git a/drivers/net/wireless/broadcom/brcm80211/bcm4323x/bcm4323x_core.c b/drivers/net/wireless/broadcom/brcm80211/bcm4323x/bcm4323x_core.c
new file mode 100644
index 000000000..e1a3cdf3b
--- /dev/null
+++ b/drivers/net/wireless/broadcom/brcm80211/bcm4323x/bcm4323x_core.c
@@ -0,0 +1,545 @@
+// SPDX-License-Identifier: GPL-2.0-only
+
+#include <linux/device.h>
+#include <linux/firmware.h>
+#include <linux/iopoll.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+
+#include <brcm_usb_rdl.h>
+
+#include "bcm4323x.h"
+
+#define BCM4323X_FW_NAME "brcm/bcm4323x.bin"
+
+#define BCM4323X_REQ_RPC_RESPONSE 9
+#define BCM4323X_REQ_TYPE (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_INTERFACE)
+#define BCM4323X_DL_VALUE 1
+#define BCM4323X_TIMEOUT_MS 2000
+#define BCM4323X_BOOT_CHIP_ID 0x4322
+
+#define BCM4323X_BOOT_POLL_US 40000
+#define BCM4323X_BOOT_TIMEOUT_US 1200000
+#define BCM4323X_CONTROL_MAX 1928
+#define BCM4323X_IO_SIZE 4096
+#define BCM4323X_RPC_READS 16
+
+union bcm4323x_dl_response {
+ struct rdl_state_le rdl;
+ struct {
+ __le32 chip;
+ __le32 chiprev;
+ } id;
+};
+
+struct bcm4323x_handshake {
+ __le32 version;
+ __le32 chip;
+} __packed;
+
+static int bcm4323x_bulk_transfer(struct bcm4323x *dev, void *buffer, int length, bool *sent)
+{
+ int actual = 0;
+ int ret;
+
+ ret = usb_bulk_msg(dev->udev, dev->tx_pipe, buffer, length, &actual, BCM4323X_TIMEOUT_MS);
+ if (sent)
+ *sent = actual > 0;
+ if (ret)
+ return ret;
+
+ if (!(length % usb_maxpacket(dev->udev, dev->tx_pipe)))
+ return usb_bulk_msg(dev->udev, dev->tx_pipe, NULL, 0, &actual, BCM4323X_TIMEOUT_MS);
+
+ return 0;
+}
+
+/* from brcmfmac: check_file */
+static int bcm4323x_check_file(const struct firmware *fw)
+{
+ const struct trx_header_le *trx = (const void *)fw->data;
+
+ /* Unlike brcmfmac's images, this one is not flagged TRX_UNCOMP_IMAGE. */
+ if (fw->size < sizeof(*trx) || trx->magic != cpu_to_le32(TRX_MAGIC) ||
+ le32_to_cpu(trx->len) != fw->size)
+ return -EINVAL;
+ return 0;
+}
+
+/* from brcmfmac: brcmf_usb_dl_cmd */
+static int bcm4323x_dl_cmd(struct bcm4323x *dev, u8 cmd, union bcm4323x_dl_response *buffer)
+{
+ return usb_control_msg_recv(dev->udev, 0, cmd, BCM4323X_REQ_TYPE, BCM4323X_DL_VALUE,
+ dev->intf->cur_altsetting->desc.bInterfaceNumber, buffer,
+ sizeof(*buffer), BCM4323X_TIMEOUT_MS, GFP_KERNEL);
+}
+
+/* from brcmfmac: brcmf_usb_resetcfg */
+static int bcm4323x_wait_postboot(struct bcm4323x *dev)
+{
+ union bcm4323x_dl_response id;
+ int err;
+
+ /* The bootloader stalls or answers short while the runtime starts. */
+ return poll_timeout_us(err = bcm4323x_dl_cmd(dev, DL_GETVER, &id),
+ err ? err != -EPIPE && err != -EREMOTEIO :
+ id.id.chip == cpu_to_le32(BRCMF_POSTBOOT_ID),
+ BCM4323X_BOOT_POLL_US, BCM4323X_BOOT_TIMEOUT_US, true) ?: err;
+}
+
+/* from brcmfmac: brcmf_usb_dl_writeimage */
+static int bcm4323x_dl_writeimage(struct bcm4323x *dev, const u8 *fw, u32 fwlen)
+{
+ union bcm4323x_dl_response state;
+ u32 rdlstate;
+ u32 sent = 0;
+ int err;
+
+ err = bcm4323x_dl_cmd(dev, DL_START, &state);
+ if (err)
+ return err;
+ if (le32_to_cpu(state.rdl.state) != DL_WAITING)
+ return -EINVAL;
+
+ while (sent < fwlen) {
+ u32 sendlen = min_t(u32, fwlen - sent, TRX_RDL_CHUNK);
+
+ memcpy(dev->io_buffer, fw + sent, sendlen);
+ err = bcm4323x_bulk_transfer(dev, dev->io_buffer, sendlen, NULL);
+ if (err)
+ return err;
+ sent += sendlen;
+
+ err = bcm4323x_dl_cmd(dev, DL_GETSTATE, &state);
+ if (err)
+ return err;
+ rdlstate = le32_to_cpu(state.rdl.state);
+ /*
+ * Unlike brcmfmac, expect the bytes to be accepted at once, as the
+ * reference driver does.
+ */
+ if (rdlstate == DL_BAD_HDR || rdlstate == DL_BAD_CRC ||
+ le32_to_cpu(state.rdl.bytes) != sent)
+ return -EINVAL;
+ }
+ return 0;
+}
+
+/* from brcmfmac: brcmf_usb_dlrun */
+static int bcm4323x_dlrun(struct bcm4323x *dev)
+{
+ union bcm4323x_dl_response state;
+ int err;
+
+ err = bcm4323x_dl_cmd(dev, DL_GETSTATE, &state);
+ if (err)
+ return err;
+ if (state.rdl.state != cpu_to_le32(DL_RUNNABLE))
+ return -EINVAL;
+
+ err = bcm4323x_dl_cmd(dev, DL_GO, &state);
+ if (err)
+ return err;
+ return bcm4323x_wait_postboot(dev);
+}
+
+/* from brcmfmac: brcmf_usb_fw_download, brcmf_usb_dlneeded */
+static int bcm4323x_fw_download(struct bcm4323x *dev, const struct firmware *fw)
+{
+ union bcm4323x_dl_response id;
+ int err;
+
+ err = bcm4323x_check_file(fw);
+ if (err)
+ return err;
+
+ err = bcm4323x_dl_cmd(dev, DL_GETVER, &id);
+ if (err)
+ return err;
+ if (id.id.chip != cpu_to_le32(BRCMF_POSTBOOT_ID)) {
+ if (id.id.chip != cpu_to_le32(BCM4323X_BOOT_CHIP_ID))
+ return -ENODEV;
+ err = bcm4323x_dl_writeimage(dev, fw->data, fw->size);
+ if (!err)
+ err = bcm4323x_dlrun(dev);
+ if (err)
+ return err;
+ }
+ bcm4323x_dl_cmd(dev, DL_RESETCFG, &id);
+ return 0;
+}
+
+/*
+ * Reads the response to a control procedure, skipping the responses to other
+ * procedures that the dongle kept, and copies the start of its body, if any.
+ */
+static int bcm4323x_rpc_response_locked(struct bcm4323x *dev, u32 procedure, void *response,
+ size_t response_length)
+{
+ const struct bcm4323x_rpc_header *rpc = (void *)dev->io_buffer;
+ u8 interface = dev->intf->cur_altsetting->desc.bInterfaceNumber;
+ unsigned int reads;
+ size_t length;
+ int ret;
+
+ lockdep_assert_held(&dev->io_mutex);
+ for (reads = 0; reads < BCM4323X_RPC_READS; reads++) {
+ ret = usb_control_msg(dev->udev, usb_rcvctrlpipe(dev->udev, 0),
+ BCM4323X_REQ_RPC_RESPONSE, BCM4323X_REQ_TYPE, 0, interface,
+ dev->io_buffer, BCM4323X_CONTROL_MAX,
+ BCM4323X_TIMEOUT_MS);
+ if (ret < 0)
+ return ret;
+ if (ret < sizeof(*rpc))
+ return -EPROTO;
+
+ length = le32_to_cpu(rpc->length) + sizeof(rpc->length);
+ if (length < sizeof(*rpc) || length > ret ||
+ FIELD_GET(BCM4323X_RPC_CLASS_MASK, le32_to_cpu(rpc->xid_class)) !=
+ BCM4323X_RPC_CLASS_CONTROL)
+ return -EPROTO;
+ if (le32_to_cpu(rpc->procedure) != procedure) {
+ dev_dbg(&dev->intf->dev, "skipped response to RPC 0x%x\n",
+ le32_to_cpu(rpc->procedure));
+ continue;
+ }
+ if (!response)
+ return 0;
+ if (length - sizeof(*rpc) < response_length)
+ return -EPROTO;
+ memcpy(response, rpc + 1, response_length);
+ return 0;
+ }
+ return -EPROTO;
+}
+
+static int bcm4323x_rpc_transact(struct bcm4323x *dev, u8 rpc_class, u32 procedure,
+ const void *body, size_t body_length, void *response,
+ size_t response_length)
+{
+ struct bcm4323x_rpc_header *rpc;
+ bool sent;
+ int ret;
+
+ if (body_length > BCM4323X_IO_SIZE - sizeof(*rpc))
+ return -EMSGSIZE;
+ if (READ_ONCE(dev->dead))
+ return -ENODEV;
+
+ mutex_lock(&dev->io_mutex);
+ rpc = (void *)dev->io_buffer;
+ rpc->length = bcm4323x_rpc_length(body_length);
+ rpc->xid_class = bcm4323x_rpc_xid_class(rpc_class, dev->rpc_xid);
+ rpc->procedure = cpu_to_le32(procedure);
+ memcpy(rpc + 1, body, body_length);
+ ret = bcm4323x_bulk_transfer(dev, dev->io_buffer, sizeof(*rpc) + body_length, &sent);
+ if (sent)
+ dev->rpc_xid++;
+ if (!ret && rpc_class == BCM4323X_RPC_CLASS_CONTROL)
+ ret = bcm4323x_rpc_response_locked(dev, procedure, response, response_length);
+ mutex_unlock(&dev->io_mutex);
+ return ret;
+}
+
+int bcm4323x_rpc_send(struct bcm4323x *dev, u32 procedure, const void *body, size_t body_length)
+{
+ return bcm4323x_rpc_transact(dev, BCM4323X_RPC_CLASS_DATA, procedure, body, body_length,
+ NULL, 0);
+}
+
+int bcm4323x_rpc_call(struct bcm4323x *dev, u32 procedure, const void *body, size_t body_length,
+ void *response, size_t response_length)
+{
+ return bcm4323x_rpc_transact(dev, BCM4323X_RPC_CLASS_CONTROL, procedure, body,
+ body_length, response, response_length);
+}
+
+static int bcm4323x_handshake_step(struct bcm4323x *dev, u32 procedure, __le32 chip)
+{
+ struct bcm4323x_handshake body = {
+ .version = cpu_to_le32(BCM4323X_RPC_VERSION),
+ .chip = chip,
+ };
+ int ret;
+
+ reinit_completion(&dev->handshake_done);
+ ret = bcm4323x_rpc_transact(dev, BCM4323X_RPC_CLASS_TRANSPORT, procedure, &body,
+ sizeof(body), NULL, 0);
+ if (ret)
+ return ret;
+ if (!wait_for_completion_timeout(&dev->handshake_done,
+ msecs_to_jiffies(BCM4323X_TIMEOUT_MS)))
+ return -ETIMEDOUT;
+ /* VERSION sends no chip ID, and CHIP the one that the VERSION reply carried. */
+ if (!dev->handshake_chip || (chip && dev->handshake_chip != chip))
+ return -EPROTO;
+ return 0;
+}
+
+/* Reset the runtime firmware to its initialized state. */
+static int bcm4323x_init_firmware(struct bcm4323x *dev)
+{
+ int ret;
+
+ ret = bcm4323x_start_rx_urbs(dev);
+ if (ret)
+ return ret;
+ ret = bcm4323x_handshake_step(dev, BCM4323X_RPC_PROC_VERSION, 0);
+ if (!ret)
+ ret = bcm4323x_handshake_step(dev, BCM4323X_RPC_PROC_CHIP, dev->handshake_chip);
+
+ dev->rpc_xid = 0;
+ if (!ret)
+ ret = bcm4323x_init_mac(dev);
+ bcm4323x_kill_rx_urbs(dev);
+ if (!ret && READ_ONCE(dev->dead))
+ ret = -EIO;
+ return ret;
+}
+
+void bcm4323x_kill_rx_urbs(struct bcm4323x *dev)
+{
+ unsigned int index;
+
+ for (index = 0; index < BCM4323X_RX_URBS; index++)
+ usb_kill_urb(dev->rx_urbs[index]);
+}
+
+int bcm4323x_start_rx_urbs(struct bcm4323x *dev)
+{
+ unsigned int index;
+ int ret;
+
+ for (index = 0; index < BCM4323X_RX_URBS; index++) {
+ ret = usb_submit_urb(dev->rx_urbs[index], GFP_KERNEL);
+ if (ret) {
+ bcm4323x_kill_rx_urbs(dev);
+ return ret;
+ }
+ }
+ return 0;
+}
+
+static int bcm4323x_alloc_transport(struct bcm4323x *dev)
+{
+ struct usb_endpoint_descriptor *bulk_in;
+ struct usb_endpoint_descriptor *bulk_out;
+ unsigned int rx_pipe;
+ unsigned int index;
+
+ if (usb_find_common_endpoints_reverse(dev->intf->cur_altsetting, &bulk_in, &bulk_out,
+ NULL, NULL))
+ return -ENODEV;
+ dev->tx_pipe = usb_sndbulkpipe(dev->udev, bulk_out->bEndpointAddress);
+ dev->io_buffer = devm_kmalloc(&dev->intf->dev, BCM4323X_IO_SIZE, GFP_KERNEL);
+ if (!dev->io_buffer)
+ return -ENOMEM;
+
+ rx_pipe = usb_rcvbulkpipe(dev->udev, bulk_in->bEndpointAddress);
+ for (index = 0; index < BCM4323X_RX_URBS; index++) {
+ struct urb *urb = usb_alloc_urb(0, GFP_KERNEL);
+ void *buffer;
+
+ if (!urb)
+ return -ENOMEM;
+ dev->rx_urbs[index] = urb;
+ buffer = kmalloc(BCM4323X_RX_SIZE, GFP_KERNEL);
+ if (!buffer)
+ return -ENOMEM;
+ usb_fill_bulk_urb(urb, dev->udev, rx_pipe, buffer, BCM4323X_RX_SIZE,
+ bcm4323x_rx_complete, dev);
+ urb->transfer_flags = URB_FREE_BUFFER;
+ }
+ return 0;
+}
+
+static void bcm4323x_free_transport(struct bcm4323x *dev)
+{
+ unsigned int index;
+
+ for (index = 0; index < BCM4323X_RX_URBS; index++)
+ usb_free_urb(dev->rx_urbs[index]);
+}
+
+struct bcm4323x_reprobe {
+ struct work_struct work;
+ struct device *dev;
+};
+
+static void bcm4323x_reprobe_work(struct work_struct *work)
+{
+ struct bcm4323x_reprobe *reprobe = container_of(work, struct bcm4323x_reprobe, work);
+ int ret;
+
+ ret = device_reprobe(reprobe->dev);
+ if (ret)
+ dev_err(reprobe->dev, "reprobe failed: %d\n", ret);
+ put_device(reprobe->dev);
+ kfree(reprobe);
+ module_put(THIS_MODULE);
+}
+
+/* Reprobe the device in case the firmware stalls */
+void bcm4323x_fatal_error(struct bcm4323x *dev)
+{
+ struct bcm4323x_reprobe *reprobe;
+
+ if (xchg(&dev->dead, true))
+ return;
+
+ wake_up_all(&dev->tx_wait);
+ if (!READ_ONCE(dev->running))
+ return;
+ ieee80211_stop_queues(dev->hw);
+
+ if (!try_module_get(THIS_MODULE))
+ return;
+ reprobe = kzalloc_obj(*reprobe, GFP_ATOMIC);
+ if (!reprobe) {
+ module_put(THIS_MODULE);
+ return;
+ }
+ INIT_WORK(&reprobe->work, bcm4323x_reprobe_work);
+ reprobe->dev = get_device(&dev->intf->dev);
+ queue_work(system_long_wq, &reprobe->work);
+}
+
+static int bcm4323x_probe(struct usb_interface *intf, const struct usb_device_id *id)
+{
+ const struct bcm4323x_chip *chip = (const void *)id->driver_info;
+ struct ieee80211_hw *hw;
+ struct bcm4323x *dev;
+ const char *stage;
+ const struct firmware *firmware = NULL;
+ int ret;
+
+ hw = ieee80211_alloc_hw(sizeof(*dev), &bcm4323x_ops);
+ if (!hw)
+ return -ENOMEM;
+ dev = hw->priv;
+ dev->hw = hw;
+ dev->chip = chip;
+ dev->udev = interface_to_usbdev(intf);
+ dev->intf = intf;
+ mutex_init(&dev->io_mutex);
+ init_completion(&dev->handshake_done);
+ bcm4323x_init_tx(dev);
+ usb_set_intfdata(intf, hw);
+
+ stage = "transport allocation";
+ ret = bcm4323x_alloc_transport(dev);
+ if (ret)
+ goto error;
+ stage = "firmware request";
+ ret = request_firmware(&firmware, BCM4323X_FW_NAME, &intf->dev);
+ if (ret)
+ goto error;
+ stage = "firmware activation";
+ ret = bcm4323x_fw_download(dev, firmware);
+ if (ret)
+ goto error;
+ stage = "runtime initialization";
+ ret = bcm4323x_init_firmware(dev);
+ if (ret)
+ goto error;
+
+ stage = "mac80211 registration";
+ ret = bcm4323x_register_hw(dev);
+ if (ret)
+ goto error;
+ bcm4323x_led_register(dev);
+
+ dev_info(&intf->dev, "BCM4323x RPC mac80211 device ready, MAC %pM\n", hw->wiphy->perm_addr);
+ release_firmware(firmware);
+ return 0;
+
+error:
+ release_firmware(firmware);
+ bcm4323x_free_transport(dev);
+ ieee80211_free_hw(hw);
+ return dev_err_probe(&intf->dev, ret, "%s failed\n", stage);
+}
+
+static void bcm4323x_disconnect(struct usb_interface *intf)
+{
+ struct ieee80211_hw *hw = usb_get_intfdata(intf);
+ struct bcm4323x *dev = hw->priv;
+
+ bcm4323x_led_unregister(dev);
+ ieee80211_unregister_hw(hw);
+ bcm4323x_free_transport(dev);
+ ieee80211_free_hw(hw);
+}
+
+static int bcm4323x_suspend(struct usb_interface *intf, pm_message_t message)
+{
+ return 0;
+}
+
+static int bcm4323x_resume(struct usb_interface *intf)
+{
+ struct ieee80211_hw *hw = usb_get_intfdata(intf);
+ struct bcm4323x *dev = hw->priv;
+ int ret;
+
+ if (READ_ONCE(dev->dead))
+ return 0;
+ ret = bcm4323x_rpc_call(dev, BCM4323X_RPC_PROC_WATCHDOG, NULL, 0, NULL, 0);
+ if (ret) {
+ dev_err(&intf->dev, "firmware lost during suspend: %d\n", ret);
+ WRITE_ONCE(dev->dead, true);
+ intf->needs_binding = 1;
+ }
+ return 0;
+}
+
+static const struct bcm4323x_chip bcm43231_chip = { };
+
+static const struct bcm4323x_chip wna3100_chip = {
+ .has_wps_button = true,
+};
+
+static const struct bcm4323x_chip bcm4323_chip = {
+ .has_5ghz = true,
+};
+
+static const struct bcm4323x_chip f9l1101_chip = {
+ .has_5ghz = true,
+ .channel_data_2ghz = { 0x58, 0x44, 0x3c },
+ .has_wps_led = true,
+ .has_wps_button = true,
+};
+
+static const struct usb_device_id bcm4323x_id_table[] = {
+ /* Belkin Double N+ Wireless USB Adapter */
+ { USB_DEVICE(0x050d, 0x6050), .driver_info = (kernel_ulong_t)&bcm4323_chip },
+ /* Belkin F7D4101/F9L1101v1 */
+ { USB_DEVICE(0x050d, 0x615a), .driver_info = (kernel_ulong_t)&f9l1101_chip },
+ /* Belkin N+ Wireless USB Adapter */
+ { USB_DEVICE(0x050d, 0x825c), .driver_info = (kernel_ulong_t)&bcm4323_chip },
+ /* Dynex DX-NUSB */
+ { USB_DEVICE(0x050d, 0xd321), .driver_info = (kernel_ulong_t)&bcm43231_chip },
+ /* Netgear WNDA3100v2 */
+ { USB_DEVICE(0x0846, 0x9011), .driver_info = (kernel_ulong_t)&bcm4323_chip },
+ /* Netgear WNA3100 */
+ { USB_DEVICE(0x0846, 0x9020), .driver_info = (kernel_ulong_t)&wna3100_chip },
+ { }
+};
+MODULE_DEVICE_TABLE(usb, bcm4323x_id_table);
+
+static struct usb_driver bcm4323x_driver = {
+ .name = KBUILD_MODNAME,
+ .probe = bcm4323x_probe,
+ .disconnect = bcm4323x_disconnect,
+ .suspend = bcm4323x_suspend,
+ .resume = bcm4323x_resume,
+ .id_table = bcm4323x_id_table,
+ .soft_unbind = 1,
+};
+module_usb_driver(bcm4323x_driver);
+
+MODULE_AUTHOR("Ragul Balaji <ragulbaby@gmail.com>");
+MODULE_AUTHOR("Ho Jie Feng <hjf3108@gmail.com>");
+MODULE_DESCRIPTION("Broadcom BCM4323x USB mac80211 driver");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(BCM4323X_FW_NAME);
--
2.53.0
next prev parent reply other threads:[~2026-10-26 5:37 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20261026053633.361454-1-ragulbaby@gmail.com>
2026-10-26 5:36 ` [RFC PATCH wireless-next 01/17] wifi: brcmsmac: make d11.h self-contained Ragul Balaji
2026-10-26 5:36 ` [RFC PATCH wireless-next 02/17] wifi: brcm80211: move d11.h to the shared include directory Ragul Balaji
2026-10-26 5:36 ` [RFC PATCH wireless-next 03/17] wifi: brcmsmac: look up OFDM rates in rate.c Ragul Balaji
2026-10-26 5:36 ` [RFC PATCH wireless-next 04/17] wifi: brcmsmac: give the rate tables and helpers a brcmu_ prefix Ragul Balaji
2026-10-26 5:36 ` [RFC PATCH wireless-next 05/17] wifi: brcmsmac: round short-GI L-SIG lengths up to whole symbols Ragul Balaji
2026-10-26 5:36 ` [RFC PATCH wireless-next 06/17] wifi: brcmsmac: pass the band to the PLCP and frame timing helpers Ragul Balaji
2026-10-26 5:36 ` [RFC PATCH wireless-next 07/17] wifi: brcmsmac: move the PLCP and frame timing helpers to rate.c Ragul Balaji
2026-10-26 5:36 ` [RFC PATCH wireless-next 08/17] wifi: brcm80211: move the rate helpers of brcmsmac to brcmutil Ragul Balaji
2026-10-26 5:36 ` [RFC PATCH wireless-next 09/17] wifi: brcm80211: move the USB bootloader definitions to a shared header Ragul Balaji
2026-10-26 5:36 ` [RFC PATCH wireless-next 10/17] wifi: mac80211: export ieee80211_get_bssid() again Ragul Balaji
2026-10-26 5:36 ` [RFC PATCH wireless-next 11/17] wifi: bcm4323x: add the shared definitions Ragul Balaji
2026-10-26 5:36 ` Ragul Balaji [this message]
2026-10-26 5:36 ` [RFC PATCH wireless-next 13/17] wifi: bcm4323x: add the receive path Ragul Balaji
2026-10-26 5:36 ` [RFC PATCH wireless-next 14/17] wifi: bcm4323x: add the transmit path Ragul Balaji
2026-10-26 5:36 ` [RFC PATCH wireless-next 15/17] wifi: bcm4323x: add the mac80211 operations Ragul Balaji
2026-10-26 5:36 ` [RFC PATCH wireless-next 16/17] wifi: bcm4323x: add LED and WPS button support Ragul Balaji
2026-10-26 5:36 ` [RFC PATCH wireless-next 17/17] wifi: bcm4323x: add Kconfig, Makefile and MAINTAINERS entry Ragul Balaji
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=20261026053633.361454-13-ragulbaby@gmail.com \
--to=ragulbaby@gmail.com \
--cc=arend.vanspriel@broadcom.com \
--cc=brcm80211-dev-list.pdl@broadcom.com \
--cc=brcm80211@lists.linux.dev \
--cc=hjf3108@gmail.com \
--cc=johannes@sipsolutions.net \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-wireless@vger.kernel.org \
/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®