The branch stable/15 has been updated by bz:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=a32802d07dc0ef95854abd892ccba7b016a7490f

commit a32802d07dc0ef95854abd892ccba7b016a7490f
Author:     Bjoern A. Zeeb <[email protected]>
AuthorDate: 2026-02-10 21:22:03 +0000
Commit:     Bjoern A. Zeeb <[email protected]>
CommitDate: 2026-02-26 23:07:02 +0000

    brcm80211: import Broadcom wireless brcmsmac and brcmfmac drivers
    
    This version is based on
    git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
    e5f0a698b34ed76002dc5cff3804a61c80233a7a ( tag: v6.17 ).
    
    We are likely only going to use the brcmfmac driver but given they
    come nicely packaged in a directory structure and bwn(9) still uses
    GPL-only phy files we could use some of the information from brcmsmac
    and fix that (should it ever still be relevant).
    
    (cherry picked from commit b4c3e9b5b09c829b4135aff738bd2893ed052377)
---
 sys/contrib/dev/broadcom/brcm80211/Makefile        |    13 +
 .../dev/broadcom/brcm80211/brcmfmac/Makefile       |    62 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/acpi.c |    51 +
 .../dev/broadcom/brcm80211/brcmfmac/bca/Makefile   |    12 +
 .../dev/broadcom/brcm80211/brcmfmac/bca/core.c     |    39 +
 .../dev/broadcom/brcm80211/brcmfmac/bca/module.c   |    28 +
 .../dev/broadcom/brcm80211/brcmfmac/bca/vops.h     |    11 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/bcdc.c |   490 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/bcdc.h |    20 +
 .../dev/broadcom/brcm80211/brcmfmac/bcmsdh.c       |  1269 +
 .../dev/broadcom/brcm80211/brcmfmac/btcoex.c       |   481 +
 .../dev/broadcom/brcm80211/brcmfmac/btcoex.h       |    18 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/bus.h  |   342 +
 .../dev/broadcom/brcm80211/brcmfmac/cfg80211.c     |  8477 ++++++
 .../dev/broadcom/brcm80211/brcmfmac/cfg80211.h     |   498 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/chip.c |  1472 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/chip.h |    92 +
 .../dev/broadcom/brcm80211/brcmfmac/common.c       |   637 +
 .../dev/broadcom/brcm80211/brcmfmac/common.h       |    95 +
 .../dev/broadcom/brcm80211/brcmfmac/commonring.c   |   236 +
 .../dev/broadcom/brcm80211/brcmfmac/commonring.h   |    62 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/core.c |  1576 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/core.h |   228 +
 .../dev/broadcom/brcm80211/brcmfmac/cyw/Makefile   |    12 +
 .../dev/broadcom/brcm80211/brcmfmac/cyw/core.c     |   373 +
 .../broadcom/brcm80211/brcmfmac/cyw/fwil_types.h   |    87 +
 .../dev/broadcom/brcm80211/brcmfmac/cyw/module.c   |    28 +
 .../dev/broadcom/brcm80211/brcmfmac/cyw/vops.h     |    11 +
 .../dev/broadcom/brcm80211/brcmfmac/debug.c        |    56 +
 .../dev/broadcom/brcm80211/brcmfmac/debug.h        |   143 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/dmi.c  |   215 +
 .../dev/broadcom/brcm80211/brcmfmac/feature.c      |   385 +
 .../dev/broadcom/brcm80211/brcmfmac/feature.h      |   131 +
 .../dev/broadcom/brcm80211/brcmfmac/firmware.c     |   859 +
 .../dev/broadcom/brcm80211/brcmfmac/firmware.h     |    95 +
 .../dev/broadcom/brcm80211/brcmfmac/flowring.c     |   508 +
 .../dev/broadcom/brcm80211/brcmfmac/flowring.h     |    74 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/fweh.c |   514 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/fweh.h |   401 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/fwil.c |   432 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/fwil.h |   224 +
 .../dev/broadcom/brcm80211/brcmfmac/fwil_types.h   |  1239 +
 .../dev/broadcom/brcm80211/brcmfmac/fwsignal.c     |  2514 ++
 .../dev/broadcom/brcm80211/brcmfmac/fwsignal.h     |    48 +
 .../dev/broadcom/brcm80211/brcmfmac/fwvid.c        |   200 +
 .../dev/broadcom/brcm80211/brcmfmac/fwvid.h        |    88 +
 .../dev/broadcom/brcm80211/brcmfmac/msgbuf.c       |  1687 ++
 .../dev/broadcom/brcm80211/brcmfmac/msgbuf.h       |    43 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/of.c   |   155 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/of.h   |    14 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/p2p.c  |  2546 ++
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/p2p.h  |   179 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/pcie.c |  2785 ++
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/pcie.h |    14 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/pno.c  |   595 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/pno.h  |    72 +
 .../dev/broadcom/brcm80211/brcmfmac/proto.c        |    71 +
 .../dev/broadcom/brcm80211/brcmfmac/proto.h        |   155 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/sdio.c |  4650 +++
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/sdio.h |   370 +
 .../dev/broadcom/brcm80211/brcmfmac/tracepoint.c   |    32 +
 .../dev/broadcom/brcm80211/brcmfmac/tracepoint.h   |   144 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/usb.c  |  1604 ++
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/usb.h  |    42 +
 .../dev/broadcom/brcm80211/brcmfmac/vendor.c       |   118 +
 .../dev/broadcom/brcm80211/brcmfmac/vendor.h       |    53 +
 .../dev/broadcom/brcm80211/brcmfmac/wcc/Makefile   |    12 +
 .../dev/broadcom/brcm80211/brcmfmac/wcc/core.c     |    40 +
 .../dev/broadcom/brcm80211/brcmfmac/wcc/module.c   |    28 +
 .../dev/broadcom/brcm80211/brcmfmac/wcc/vops.h     |    11 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/xtlv.c |    84 +
 sys/contrib/dev/broadcom/brcm80211/brcmfmac/xtlv.h |    31 +
 .../dev/broadcom/brcm80211/brcmsmac/Makefile       |    47 +
 .../dev/broadcom/brcm80211/brcmsmac/aiutils.c      |   707 +
 .../dev/broadcom/brcm80211/brcmsmac/aiutils.h      |   221 +
 .../dev/broadcom/brcm80211/brcmsmac/ampdu.c        |  1097 +
 .../dev/broadcom/brcm80211/brcmsmac/ampdu.h        |    53 +
 .../dev/broadcom/brcm80211/brcmsmac/antsel.c       |   309 +
 .../dev/broadcom/brcm80211/brcmsmac/antsel.h       |    27 +
 .../brcm80211/brcmsmac/brcms_trace_brcmsmac.h      |   102 +
 .../brcm80211/brcmsmac/brcms_trace_brcmsmac_msg.h  |    92 +
 .../brcm80211/brcmsmac/brcms_trace_brcmsmac_tx.h   |   110 +
 .../brcm80211/brcmsmac/brcms_trace_events.c        |    23 +
 .../brcm80211/brcmsmac/brcms_trace_events.h        |    40 +
 .../dev/broadcom/brcm80211/brcmsmac/channel.c      |   771 +
 .../dev/broadcom/brcm80211/brcmsmac/channel.h      |    47 +
 sys/contrib/dev/broadcom/brcm80211/brcmsmac/d11.h  |  1902 ++
 .../dev/broadcom/brcm80211/brcmsmac/debug.c        |   246 +
 .../dev/broadcom/brcm80211/brcmsmac/debug.h        |    75 +
 sys/contrib/dev/broadcom/brcm80211/brcmsmac/dma.c  |  1556 +
 sys/contrib/dev/broadcom/brcm80211/brcmsmac/dma.h  |   124 +
 sys/contrib/dev/broadcom/brcm80211/brcmsmac/led.h  |    38 +
 .../dev/broadcom/brcm80211/brcmsmac/mac80211_if.c  |  1738 ++
 .../dev/broadcom/brcm80211/brcmsmac/mac80211_if.h  |   113 +
 sys/contrib/dev/broadcom/brcm80211/brcmsmac/main.c |  8065 ++++++
 sys/contrib/dev/broadcom/brcm80211/brcmsmac/main.h |   670 +
 .../dev/broadcom/brcm80211/brcmsmac/phy/phy_cmn.c  |  2497 ++
 .../dev/broadcom/brcm80211/brcmsmac/phy/phy_hal.h  |   241 +
 .../dev/broadcom/brcm80211/brcmsmac/phy/phy_int.h  |  1113 +
 .../dev/broadcom/brcm80211/brcmsmac/phy/phy_lcn.c  |  5151 ++++
 .../dev/broadcom/brcm80211/brcmsmac/phy/phy_lcn.h  |   110 +
 .../dev/broadcom/brcm80211/brcmsmac/phy/phy_n.c    | 28572 +++++++++++++++++++
 .../broadcom/brcm80211/brcmsmac/phy/phy_qmath.c    |   298 +
 .../broadcom/brcm80211/brcmsmac/phy/phy_qmath.h    |    31 +
 .../broadcom/brcm80211/brcmsmac/phy/phy_radio.h    |  1522 +
 .../dev/broadcom/brcm80211/brcmsmac/phy/phyreg_n.h |   156 +
 .../broadcom/brcm80211/brcmsmac/phy/phytbl_lcn.c   |  3170 ++
 .../broadcom/brcm80211/brcmsmac/phy/phytbl_lcn.h   |    44 +
 .../dev/broadcom/brcm80211/brcmsmac/phy/phytbl_n.c | 10099 +++++++
 .../dev/broadcom/brcm80211/brcmsmac/phy/phytbl_n.h |    39 +
 .../dev/broadcom/brcm80211/brcmsmac/phy_shim.c     |   215 +
 .../dev/broadcom/brcm80211/brcmsmac/phy_shim.h     |   172 +
 sys/contrib/dev/broadcom/brcm80211/brcmsmac/pmu.c  |   165 +
 sys/contrib/dev/broadcom/brcm80211/brcmsmac/pmu.h  |    26 +
 sys/contrib/dev/broadcom/brcm80211/brcmsmac/pub.h  |   341 +
 sys/contrib/dev/broadcom/brcm80211/brcmsmac/rate.c |   514 +
 sys/contrib/dev/broadcom/brcm80211/brcmsmac/rate.h |   245 +
 sys/contrib/dev/broadcom/brcm80211/brcmsmac/scb.h  |    67 +
 sys/contrib/dev/broadcom/brcm80211/brcmsmac/stf.c  |   437 +
 sys/contrib/dev/broadcom/brcm80211/brcmsmac/stf.h  |    36 +
 .../dev/broadcom/brcm80211/brcmsmac/types.h        |   294 +
 .../dev/broadcom/brcm80211/brcmsmac/ucode_loader.c |   109 +
 .../dev/broadcom/brcm80211/brcmsmac/ucode_loader.h |    56 +
 .../dev/broadcom/brcm80211/brcmutil/Makefile       |    10 +
 sys/contrib/dev/broadcom/brcm80211/brcmutil/d11.c  |   247 +
 .../dev/broadcom/brcm80211/brcmutil/utils.c        |   327 +
 .../dev/broadcom/brcm80211/include/brcm_hw_ids.h   |   116 +
 .../dev/broadcom/brcm80211/include/brcmu_d11.h     |   156 +
 .../dev/broadcom/brcm80211/include/brcmu_utils.h   |   216 +
 .../dev/broadcom/brcm80211/include/brcmu_wifi.h    |   247 +
 .../dev/broadcom/brcm80211/include/chipcommon.h    |   311 +
 sys/contrib/dev/broadcom/brcm80211/include/defs.h  |    94 +
 sys/contrib/dev/broadcom/brcm80211/include/soc.h   |    25 +
 133 files changed, 116023 insertions(+)

diff --git a/sys/contrib/dev/broadcom/brcm80211/Makefile 
b/sys/contrib/dev/broadcom/brcm80211/Makefile
new file mode 100644
index 000000000000..88115d072624
--- /dev/null
+++ b/sys/contrib/dev/broadcom/brcm80211/Makefile
@@ -0,0 +1,13 @@
+# SPDX-License-Identifier: ISC
+#
+# Makefile fragment for Broadcom 802.11 Networking Device Driver
+#
+# Copyright (c) 2010 Broadcom Corporation
+#
+
+# common flags
+subdir-ccflags-$(CONFIG_BRCMDBG)       += -DDEBUG
+
+obj-$(CONFIG_BRCMUTIL) += brcmutil/
+obj-$(CONFIG_BRCMFMAC) += brcmfmac/
+obj-$(CONFIG_BRCMSMAC) += brcmsmac/
diff --git a/sys/contrib/dev/broadcom/brcm80211/brcmfmac/Makefile 
b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/Makefile
new file mode 100644
index 000000000000..e5ca0f511822
--- /dev/null
+++ b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/Makefile
@@ -0,0 +1,62 @@
+# SPDX-License-Identifier: ISC
+#
+# Makefile fragment for Broadcom 802.11 Networking Device Driver
+#
+# Copyright (c) 2010 Broadcom Corporation
+#
+
+ccflags-y += \
+       -I $(src) \
+       -I $(src)/../include
+
+obj-$(CONFIG_BRCMFMAC) += brcmfmac.o
+brcmfmac-objs += \
+               cfg80211.o \
+               chip.o \
+               fwil.o \
+               fweh.o \
+               p2p.o \
+               proto.o \
+               common.o \
+               core.o \
+               firmware.o \
+               fwvid.o \
+               feature.o \
+               btcoex.o \
+               vendor.o \
+               pno.o \
+               xtlv.o
+brcmfmac-$(CONFIG_BRCMFMAC_PROTO_BCDC) += \
+               bcdc.o \
+               fwsignal.o
+brcmfmac-$(CONFIG_BRCMFMAC_PROTO_MSGBUF) += \
+               commonring.o \
+               flowring.o \
+               msgbuf.o
+brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
+               sdio.o \
+               bcmsdh.o
+brcmfmac-$(CONFIG_BRCMFMAC_USB) += \
+               usb.o
+brcmfmac-$(CONFIG_BRCMFMAC_PCIE) += \
+               pcie.o
+brcmfmac-$(CONFIG_BRCMDBG) += \
+               debug.o
+brcmfmac-$(CONFIG_BRCM_TRACING) += \
+               tracepoint.o
+brcmfmac-$(CONFIG_OF) += \
+               of.o
+brcmfmac-$(CONFIG_DMI) += \
+               dmi.o
+brcmfmac-$(CONFIG_ACPI) += \
+               acpi.o
+
+ifeq ($(CONFIG_BRCMFMAC),m)
+obj-m += wcc/
+obj-m += cyw/
+obj-m += bca/
+else
+brcmfmac-$(CONFIG_BRCMFMAC) += wcc/core.o
+brcmfmac-$(CONFIG_BRCMFMAC) += cyw/core.o
+brcmfmac-$(CONFIG_BRCMFMAC) += bca/core.o
+endif
diff --git a/sys/contrib/dev/broadcom/brcm80211/brcmfmac/acpi.c 
b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/acpi.c
new file mode 100644
index 000000000000..c4a54861bfb4
--- /dev/null
+++ b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/acpi.c
@@ -0,0 +1,51 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright The Asahi Linux Contributors
+ */
+
+#include <linux/acpi.h>
+#include "debug.h"
+#include "core.h"
+#include "common.h"
+
+void brcmf_acpi_probe(struct device *dev, enum brcmf_bus_type bus_type,
+                     struct brcmf_mp_device *settings)
+{
+       acpi_status status;
+       const union acpi_object *o;
+       struct acpi_buffer buf = {ACPI_ALLOCATE_BUFFER, NULL};
+       struct acpi_device *adev = ACPI_COMPANION(dev);
+
+       if (!adev)
+               return;
+
+       if (!ACPI_FAILURE(acpi_dev_get_property(adev, "module-instance",
+                                               ACPI_TYPE_STRING, &o))) {
+               brcmf_dbg(INFO, "ACPI module-instance=%s\n", o->string.pointer);
+               settings->board_type = devm_kasprintf(dev, GFP_KERNEL,
+                                                     "apple,%s",
+                                                     o->string.pointer);
+       } else {
+               brcmf_dbg(INFO, "No ACPI module-instance\n");
+               return;
+       }
+
+       status = acpi_evaluate_object(adev->handle, "RWCV", NULL, &buf);
+       o = buf.pointer;
+       if (!ACPI_FAILURE(status) && o && o->type == ACPI_TYPE_BUFFER &&
+           o->buffer.length >= 2) {
+               char *antenna_sku = devm_kzalloc(dev, 3, GFP_KERNEL);
+
+               if (antenna_sku) {
+                       memcpy(antenna_sku, o->buffer.pointer, 2);
+                       brcmf_dbg(INFO, "ACPI RWCV data=%*phN antenna-sku=%s\n",
+                                 (int)o->buffer.length, o->buffer.pointer,
+                                 antenna_sku);
+                       settings->antenna_sku = antenna_sku;
+               }
+
+               kfree(buf.pointer);
+       } else {
+               brcmf_dbg(INFO, "No ACPI antenna-sku\n");
+       }
+}
diff --git a/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bca/Makefile 
b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bca/Makefile
new file mode 100644
index 000000000000..5e37c638f966
--- /dev/null
+++ b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bca/Makefile
@@ -0,0 +1,12 @@
+# SPDX-License-Identifier: ISC
+#
+# Copyright (c) 2022 Broadcom Corporation
+
+ccflags-y += \
+       -I $(src) \
+       -I $(src)/.. \
+       -I $(src)/../../include
+
+obj-m += brcmfmac-bca.o
+brcmfmac-bca-objs += \
+               core.o module.o
diff --git a/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bca/core.c 
b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bca/core.c
new file mode 100644
index 000000000000..f471c962104a
--- /dev/null
+++ b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bca/core.c
@@ -0,0 +1,39 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (c) 2022 Broadcom Corporation
+ */
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <core.h>
+#include <bus.h>
+#include <fwvid.h>
+#include <feature.h>
+
+#include "vops.h"
+
+#define BRCMF_BCA_E_LAST               212
+
+static void brcmf_bca_feat_attach(struct brcmf_if *ifp)
+{
+       /* SAE support not confirmed so disabling for now */
+       ifp->drvr->feat_flags &= ~BIT(BRCMF_FEAT_SAE);
+}
+
+static int brcmf_bca_alloc_fweh_info(struct brcmf_pub *drvr)
+{
+       struct brcmf_fweh_info *fweh;
+
+       fweh = kzalloc(struct_size(fweh, evt_handler, BRCMF_BCA_E_LAST),
+                      GFP_KERNEL);
+       if (!fweh)
+               return -ENOMEM;
+
+       fweh->num_event_codes = BRCMF_BCA_E_LAST;
+       drvr->fweh = fweh;
+       return 0;
+}
+
+const struct brcmf_fwvid_ops brcmf_bca_ops = {
+       .feat_attach = brcmf_bca_feat_attach,
+       .alloc_fweh_info = brcmf_bca_alloc_fweh_info,
+};
diff --git a/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bca/module.c 
b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bca/module.c
new file mode 100644
index 000000000000..1e1c79b18c5b
--- /dev/null
+++ b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bca/module.c
@@ -0,0 +1,28 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (c) 2022 Broadcom Corporation
+ */
+#include <linux/module.h>
+#include <bus.h>
+#include <core.h>
+#include <fwvid.h>
+
+#include "vops.h"
+
+static int __init brcmf_bca_init(void)
+{
+       return brcmf_fwvid_register_vendor(BRCMF_FWVENDOR_BCA, THIS_MODULE,
+                                          &brcmf_bca_ops);
+}
+
+static void __exit brcmf_bca_exit(void)
+{
+       brcmf_fwvid_unregister_vendor(BRCMF_FWVENDOR_BCA, THIS_MODULE);
+}
+
+MODULE_DESCRIPTION("Broadcom FullMAC WLAN driver plugin for Broadcom AP 
chipsets");
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_IMPORT_NS("BRCMFMAC");
+
+module_init(brcmf_bca_init);
+module_exit(brcmf_bca_exit);
diff --git a/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bca/vops.h 
b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bca/vops.h
new file mode 100644
index 000000000000..7897e6b6eefb
--- /dev/null
+++ b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bca/vops.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: ISC */
+/*
+ * Copyright (c) 2022 Broadcom Corporation
+ */
+#ifndef _BRCMFMAC_BCA_VOPS_H
+#define _BRCMFMAC_BCA_VOPS_H
+
+extern const struct brcmf_fwvid_ops brcmf_bca_ops;
+#define BCA_VOPS       (&brcmf_bca_ops)
+
+#endif /* _BRCMFMAC_BCA_VOPS_H */
diff --git a/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bcdc.c 
b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bcdc.c
new file mode 100644
index 000000000000..9ec0c60b6da1
--- /dev/null
+++ b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bcdc.c
@@ -0,0 +1,490 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ */
+
+/*******************************************************************************
+ * Communicates with the dongle by using dcmd codes.
+ * For certain dcmd codes, the dongle interprets string data from the host.
+ 
******************************************************************************/
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+
+#include "core.h"
+#include "bus.h"
+#include "fwsignal.h"
+#include "debug.h"
+#include "tracepoint.h"
+#include "proto.h"
+#include "bcdc.h"
+
+struct brcmf_proto_bcdc_dcmd {
+       __le32 cmd;     /* dongle command value */
+       __le32 len;     /* lower 16: output buflen;
+                        * upper 16: input buflen (excludes header) */
+       __le32 flags;   /* flag defns given below */
+       __le32 status;  /* status code returned from the device */
+};
+
+/* BCDC flag definitions */
+#define BCDC_DCMD_ERROR                0x01            /* 1=cmd failed */
+#define BCDC_DCMD_SET          0x02            /* 0=get, 1=set cmd */
+#define BCDC_DCMD_IF_MASK      0xF000          /* I/F index */
+#define BCDC_DCMD_IF_SHIFT     12
+#define BCDC_DCMD_ID_MASK      0xFFFF0000      /* id an cmd pairing */
+#define BCDC_DCMD_ID_SHIFT     16              /* ID Mask shift bits */
+#define BCDC_DCMD_ID(flags)    \
+       (((flags) & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT)
+
+/*
+ * BCDC header - Broadcom specific extension of CDC.
+ * Used on data packets to convey priority across USB.
+ */
+#define        BCDC_HEADER_LEN         4
+#define BCDC_PROTO_VER         2       /* Protocol version */
+#define BCDC_FLAG_VER_MASK     0xf0    /* Protocol version mask */
+#define BCDC_FLAG_VER_SHIFT    4       /* Protocol version shift */
+#define BCDC_FLAG_SUM_GOOD     0x04    /* Good RX checksums */
+#define BCDC_FLAG_SUM_NEEDED   0x08    /* Dongle needs to do TX checksums */
+#define BCDC_PRIORITY_MASK     0x7
+#define BCDC_FLAG2_IF_MASK     0x0f    /* packet rx interface in APSTA */
+#define BCDC_FLAG2_IF_SHIFT    0
+
+#define BCDC_GET_IF_IDX(hdr) \
+       ((int)((((hdr)->flags2) & BCDC_FLAG2_IF_MASK) >> BCDC_FLAG2_IF_SHIFT))
+#define BCDC_SET_IF_IDX(hdr, idx) \
+       ((hdr)->flags2 = (((hdr)->flags2 & ~BCDC_FLAG2_IF_MASK) | \
+       ((idx) << BCDC_FLAG2_IF_SHIFT)))
+
+/**
+ * struct brcmf_proto_bcdc_header - BCDC header format
+ *
+ * @flags: flags contain protocol and checksum info.
+ * @priority: 802.1d priority and USB flow control info (bit 4:7).
+ * @flags2: additional flags containing dongle interface index.
+ * @data_offset: start of packet data. header is following by firmware signals.
+ */
+struct brcmf_proto_bcdc_header {
+       u8 flags;
+       u8 priority;
+       u8 flags2;
+       u8 data_offset;
+};
+
+/*
+ * maximum length of firmware signal data between
+ * the BCDC header and packet data in the tx path.
+ */
+#define BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES       12
+
+#define RETRIES 2 /* # of retries to retrieve matching dcmd response */
+#define BUS_HEADER_LEN (16+64)         /* Must be atleast SDPCM_RESERVE
+                                        * (amount of header tha might be added)
+                                        * plus any space that might be needed
+                                        * for bus alignment padding.
+                                        */
+#define ROUND_UP_MARGIN 2048
+
+struct brcmf_bcdc {
+       u16 reqid;
+       u8 bus_header[BUS_HEADER_LEN];
+       struct brcmf_proto_bcdc_dcmd msg;
+       unsigned char buf[BRCMF_DCMD_MAXLEN];
+       struct brcmf_fws_info *fws;
+};
+
+
+struct brcmf_fws_info *drvr_to_fws(struct brcmf_pub *drvr)
+{
+       struct brcmf_bcdc *bcdc = drvr->proto->pd;
+
+       return bcdc->fws;
+}
+
+static int
+brcmf_proto_bcdc_msg(struct brcmf_pub *drvr, int ifidx, uint cmd, void *buf,
+                    uint len, bool set)
+{
+       struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
+       struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
+       u32 flags;
+
+       brcmf_dbg(BCDC, "Enter\n");
+
+       memset(msg, 0, sizeof(struct brcmf_proto_bcdc_dcmd));
+
+       msg->cmd = cpu_to_le32(cmd);
+       msg->len = cpu_to_le32(len);
+       flags = (++bcdc->reqid << BCDC_DCMD_ID_SHIFT);
+       if (set)
+               flags |= BCDC_DCMD_SET;
+       flags = (flags & ~BCDC_DCMD_IF_MASK) |
+               (ifidx << BCDC_DCMD_IF_SHIFT);
+       msg->flags = cpu_to_le32(flags);
+
+       if (buf)
+               memcpy(bcdc->buf, buf, len);
+
+       len += sizeof(*msg);
+       if (len > BRCMF_TX_IOCTL_MAX_MSG_SIZE)
+               len = BRCMF_TX_IOCTL_MAX_MSG_SIZE;
+
+       /* Send request */
+       return brcmf_bus_txctl(drvr->bus_if, (unsigned char *)&bcdc->msg, len);
+}
+
+static int brcmf_proto_bcdc_cmplt(struct brcmf_pub *drvr, u32 id, u32 len)
+{
+       int ret;
+       struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
+
+       brcmf_dbg(BCDC, "Enter\n");
+       len += sizeof(struct brcmf_proto_bcdc_dcmd);
+       do {
+               ret = brcmf_bus_rxctl(drvr->bus_if, (unsigned char *)&bcdc->msg,
+                                     len);
+               if (ret < 0)
+                       break;
+       } while (BCDC_DCMD_ID(le32_to_cpu(bcdc->msg.flags)) != id);
+
+       return ret;
+}
+
+static int
+brcmf_proto_bcdc_query_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
+                           void *buf, uint len, int *fwerr)
+{
+       struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
+       struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
+       void *info;
+       int ret = 0, retries = 0;
+       u32 id, flags;
+
+       brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
+
+       *fwerr = 0;
+       ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, false);
+       if (ret < 0) {
+               bphy_err(drvr, "brcmf_proto_bcdc_msg failed w/status %d\n",
+                        ret);
+               goto done;
+       }
+
+retry:
+       /* wait for interrupt and get first fragment */
+       ret = brcmf_proto_bcdc_cmplt(drvr, bcdc->reqid, len);
+       if (ret < 0)
+               goto done;
+
+       flags = le32_to_cpu(msg->flags);
+       id = (flags & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT;
+
+       if ((id < bcdc->reqid) && (++retries < RETRIES))
+               goto retry;
+       if (id != bcdc->reqid) {
+               bphy_err(drvr, "%s: unexpected request id %d (expected %d)\n",
+                        brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id,
+                        bcdc->reqid);
+               ret = -EINVAL;
+               goto done;
+       }
+
+       /* Check info buffer */
+       info = (void *)&bcdc->buf[0];
+
+       /* Copy info buffer */
+       if (buf) {
+               if (ret < (int)len)
+                       len = ret;
+               memcpy(buf, info, len);
+       }
+
+       ret = 0;
+
+       /* Check the ERROR flag */
+       if (flags & BCDC_DCMD_ERROR)
+               *fwerr = le32_to_cpu(msg->status);
+done:
+       return ret;
+}
+
+static int
+brcmf_proto_bcdc_set_dcmd(struct brcmf_pub *drvr, int ifidx, uint cmd,
+                         void *buf, uint len, int *fwerr)
+{
+       struct brcmf_bcdc *bcdc = (struct brcmf_bcdc *)drvr->proto->pd;
+       struct brcmf_proto_bcdc_dcmd *msg = &bcdc->msg;
+       int ret;
+       u32 flags, id;
+
+       brcmf_dbg(BCDC, "Enter, cmd %d len %d\n", cmd, len);
+
+       *fwerr = 0;
+       ret = brcmf_proto_bcdc_msg(drvr, ifidx, cmd, buf, len, true);
+       if (ret < 0)
+               goto done;
+
+       ret = brcmf_proto_bcdc_cmplt(drvr, bcdc->reqid, len);
+       if (ret < 0)
+               goto done;
+
+       flags = le32_to_cpu(msg->flags);
+       id = (flags & BCDC_DCMD_ID_MASK) >> BCDC_DCMD_ID_SHIFT;
+
+       if (id != bcdc->reqid) {
+               bphy_err(drvr, "%s: unexpected request id %d (expected %d)\n",
+                        brcmf_ifname(brcmf_get_ifp(drvr, ifidx)), id,
+                        bcdc->reqid);
+               ret = -EINVAL;
+               goto done;
+       }
+
+       ret = 0;
+
+       /* Check the ERROR flag */
+       if (flags & BCDC_DCMD_ERROR)
+               *fwerr = le32_to_cpu(msg->status);
+
+done:
+       return ret;
+}
+
+static void
+brcmf_proto_bcdc_hdrpush(struct brcmf_pub *drvr, int ifidx, u8 offset,
+                        struct sk_buff *pktbuf)
+{
+       struct brcmf_proto_bcdc_header *h;
+
+       brcmf_dbg(BCDC, "Enter\n");
+
+       /* Push BDC header used to convey priority for buses that don't */
+       skb_push(pktbuf, BCDC_HEADER_LEN);
+
+       h = (struct brcmf_proto_bcdc_header *)(pktbuf->data);
+
+       h->flags = (BCDC_PROTO_VER << BCDC_FLAG_VER_SHIFT);
+       if (pktbuf->ip_summed == CHECKSUM_PARTIAL)
+               h->flags |= BCDC_FLAG_SUM_NEEDED;
+
+       h->priority = (pktbuf->priority & BCDC_PRIORITY_MASK);
+       h->flags2 = 0;
+       h->data_offset = offset;
+       BCDC_SET_IF_IDX(h, ifidx);
+       trace_brcmf_bcdchdr(pktbuf->data);
+}
+
+static int
+brcmf_proto_bcdc_hdrpull(struct brcmf_pub *drvr, bool do_fws,
+                        struct sk_buff *pktbuf, struct brcmf_if **ifp)
+{
+       struct brcmf_proto_bcdc_header *h;
+       struct brcmf_if *tmp_if;
+
+       brcmf_dbg(BCDC, "Enter\n");
+
+       /* Pop BCDC header used to convey priority for buses that don't */
+       if (pktbuf->len <= BCDC_HEADER_LEN) {
+               brcmf_dbg(INFO, "rx data too short (%d <= %d)\n",
+                         pktbuf->len, BCDC_HEADER_LEN);
+               return -EBADE;
+       }
+
+       trace_brcmf_bcdchdr(pktbuf->data);
+       h = (struct brcmf_proto_bcdc_header *)(pktbuf->data);
+
+       tmp_if = brcmf_get_ifp(drvr, BCDC_GET_IF_IDX(h));
+       if (!tmp_if) {
+               brcmf_dbg(INFO, "no matching ifp found\n");
+               return -EBADE;
+       }
+       if (((h->flags & BCDC_FLAG_VER_MASK) >> BCDC_FLAG_VER_SHIFT) !=
+           BCDC_PROTO_VER) {
+               bphy_err(drvr, "%s: non-BCDC packet received, flags 0x%x\n",
+                        brcmf_ifname(tmp_if), h->flags);
+               return -EBADE;
+       }
+
+       if (h->flags & BCDC_FLAG_SUM_GOOD) {
+               brcmf_dbg(BCDC, "%s: BDC rcv, good checksum, flags 0x%x\n",
+                         brcmf_ifname(tmp_if), h->flags);
+               pktbuf->ip_summed = CHECKSUM_UNNECESSARY;
+       }
+
+       pktbuf->priority = h->priority & BCDC_PRIORITY_MASK;
+
+       skb_pull(pktbuf, BCDC_HEADER_LEN);
+       if (do_fws)
+               brcmf_fws_hdrpull(tmp_if, h->data_offset << 2, pktbuf);
+       else
+               skb_pull(pktbuf, h->data_offset << 2);
+
+       if (pktbuf->len == 0)
+               return -ENODATA;
+
+       if (ifp != NULL)
+               *ifp = tmp_if;
+       return 0;
+}
+
+static int brcmf_proto_bcdc_tx_queue_data(struct brcmf_pub *drvr, int ifidx,
+                                         struct sk_buff *skb)
+{
+       struct brcmf_if *ifp = brcmf_get_ifp(drvr, ifidx);
+       struct brcmf_bcdc *bcdc = drvr->proto->pd;
+
+       if (!brcmf_fws_queue_skbs(bcdc->fws))
+               return brcmf_proto_txdata(drvr, ifidx, 0, skb);
+
+       return brcmf_fws_process_skb(ifp, skb);
+}
+
+static int
+brcmf_proto_bcdc_txdata(struct brcmf_pub *drvr, int ifidx, u8 offset,
+                       struct sk_buff *pktbuf)
+{
+       brcmf_proto_bcdc_hdrpush(drvr, ifidx, offset, pktbuf);
+       return brcmf_bus_txdata(drvr->bus_if, pktbuf);
+}
+
+void brcmf_proto_bcdc_txflowblock(struct device *dev, bool state)
+{
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_pub *drvr = bus_if->drvr;
+
+       brcmf_dbg(TRACE, "Enter\n");
+
+       brcmf_fws_bus_blocked(drvr, state);
+}
+
+void
+brcmf_proto_bcdc_txcomplete(struct device *dev, struct sk_buff *txp,
+                           bool success)
+{
+       struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+       struct brcmf_bcdc *bcdc = bus_if->drvr->proto->pd;
+       struct brcmf_if *ifp;
+
+       /* await txstatus signal for firmware if active */
+       if (brcmf_fws_fc_active(bcdc->fws)) {
+               brcmf_fws_bustxcomplete(bcdc->fws, txp, success);
+       } else {
+               if (brcmf_proto_bcdc_hdrpull(bus_if->drvr, false, txp, &ifp))
+                       brcmu_pkt_buf_free_skb(txp);
+               else
+                       brcmf_txfinalize(ifp, txp, success);
+       }
+}
+
+static void
+brcmf_proto_bcdc_configure_addr_mode(struct brcmf_pub *drvr, int ifidx,
+                                    enum proto_addr_mode addr_mode)
+{
+}
+
+static void
+brcmf_proto_bcdc_delete_peer(struct brcmf_pub *drvr, int ifidx,
+                            u8 peer[ETH_ALEN])
+{
+}
+
+static void
+brcmf_proto_bcdc_add_tdls_peer(struct brcmf_pub *drvr, int ifidx,
+                              u8 peer[ETH_ALEN])
+{
+}
+
+static void brcmf_proto_bcdc_rxreorder(struct brcmf_if *ifp,
+                                      struct sk_buff *skb)
+{
+       brcmf_fws_rxreorder(ifp, skb);
+}
+
+static void
+brcmf_proto_bcdc_add_if(struct brcmf_if *ifp)
+{
+       brcmf_fws_add_interface(ifp);
+}
+
+static void
+brcmf_proto_bcdc_del_if(struct brcmf_if *ifp)
+{
+       brcmf_fws_del_interface(ifp);
+}
+
+static void
+brcmf_proto_bcdc_reset_if(struct brcmf_if *ifp)
+{
+       brcmf_fws_reset_interface(ifp);
+}
+
+static int
+brcmf_proto_bcdc_init_done(struct brcmf_pub *drvr)
+{
+       struct brcmf_bcdc *bcdc = drvr->proto->pd;
+       struct brcmf_fws_info *fws;
+
+       fws = brcmf_fws_attach(drvr);
+       if (IS_ERR(fws))
+               return PTR_ERR(fws);
+
+       bcdc->fws = fws;
+       return 0;
+}
+
+static void brcmf_proto_bcdc_debugfs_create(struct brcmf_pub *drvr)
+{
+       brcmf_fws_debugfs_create(drvr);
+}
+
+int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr)
+{
+       struct brcmf_bcdc *bcdc;
+
+       bcdc = kzalloc(sizeof(*bcdc), GFP_ATOMIC);
+       if (!bcdc)
+               goto fail;
+
+       /* ensure that the msg buf directly follows the cdc msg struct */
+       if ((unsigned long)(&bcdc->msg + 1) != (unsigned long)bcdc->buf) {
+               bphy_err(drvr, "struct brcmf_proto_bcdc is not correctly 
defined\n");
+               goto fail;
+       }
+
+       drvr->proto->hdrpull = brcmf_proto_bcdc_hdrpull;
+       drvr->proto->query_dcmd = brcmf_proto_bcdc_query_dcmd;
+       drvr->proto->set_dcmd = brcmf_proto_bcdc_set_dcmd;
+       drvr->proto->tx_queue_data = brcmf_proto_bcdc_tx_queue_data;
+       drvr->proto->txdata = brcmf_proto_bcdc_txdata;
+       drvr->proto->configure_addr_mode = brcmf_proto_bcdc_configure_addr_mode;
+       drvr->proto->delete_peer = brcmf_proto_bcdc_delete_peer;
+       drvr->proto->add_tdls_peer = brcmf_proto_bcdc_add_tdls_peer;
+       drvr->proto->rxreorder = brcmf_proto_bcdc_rxreorder;
+       drvr->proto->add_if = brcmf_proto_bcdc_add_if;
+       drvr->proto->del_if = brcmf_proto_bcdc_del_if;
+       drvr->proto->reset_if = brcmf_proto_bcdc_reset_if;
+       drvr->proto->init_done = brcmf_proto_bcdc_init_done;
+       drvr->proto->debugfs_create = brcmf_proto_bcdc_debugfs_create;
+       drvr->proto->pd = bcdc;
+
+       drvr->hdrlen += BCDC_HEADER_LEN + BRCMF_PROT_FW_SIGNAL_MAX_TXBYTES;
+       drvr->bus_if->maxctl = BRCMF_DCMD_MAXLEN +
+                       sizeof(struct brcmf_proto_bcdc_dcmd) + ROUND_UP_MARGIN;
+       return 0;
+
+fail:
+       kfree(bcdc);
+       return -ENOMEM;
+}
+
+void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr)
+{
+       struct brcmf_bcdc *bcdc = drvr->proto->pd;
+
+       drvr->proto->pd = NULL;
+       brcmf_fws_detach(bcdc->fws);
+       kfree(bcdc);
+}
diff --git a/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bcdc.h 
b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bcdc.h
new file mode 100644
index 000000000000..b051d2860cd1
--- /dev/null
+++ b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bcdc.h
@@ -0,0 +1,20 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ */
+#ifndef BRCMFMAC_BCDC_H
+#define BRCMFMAC_BCDC_H
+
+#ifdef CONFIG_BRCMFMAC_PROTO_BCDC
+int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr);
+void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr);
+void brcmf_proto_bcdc_txflowblock(struct device *dev, bool state);
+void brcmf_proto_bcdc_txcomplete(struct device *dev, struct sk_buff *txp,
+                                bool success);
+struct brcmf_fws_info *drvr_to_fws(struct brcmf_pub *drvr);
+#else
+static inline int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { return 0; }
+static inline void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) {}
+#endif
+
+#endif /* BRCMFMAC_BCDC_H */
diff --git a/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bcmsdh.c 
b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bcmsdh.c
new file mode 100644
index 000000000000..8ab7d1e34a6e
--- /dev/null
+++ b/sys/contrib/dev/broadcom/brcm80211/brcmfmac/bcmsdh.c
@@ -0,0 +1,1269 @@
+// SPDX-License-Identifier: ISC
+/*
+ * Copyright (c) 2010 Broadcom Corporation
+ */
+/* ****************** SDIO CARD Interface Functions **************************/
+
+#include <linux/types.h>
+#include <linux/netdevice.h>
+#include <linux/pci.h>
+#include <linux/pci_ids.h>
+#include <linux/sched.h>
+#include <linux/completion.h>
+#include <linux/interrupt.h>
+#include <linux/scatterlist.h>
+#include <linux/mmc/sdio.h>
+#include <linux/mmc/core.h>
+#include <linux/mmc/sdio_func.h>
+#include <linux/mmc/card.h>
+#include <linux/mmc/host.h>
+#include <linux/pm_runtime.h>
+#include <linux/suspend.h>
+#include <linux/errno.h>
+#include <linux/module.h>
+#include <linux/acpi.h>
+#include <net/cfg80211.h>
+
+#include <defs.h>
+#include <brcm_hw_ids.h>
+#include <brcmu_utils.h>
+#include <brcmu_wifi.h>
+#include <chipcommon.h>
+#include <soc.h>
+#include "chip.h"
+#include "bus.h"
+#include "debug.h"
+#include "sdio.h"
+#include "core.h"
+#include "common.h"
+
+#define SDIOH_API_ACCESS_RETRY_LIMIT   2
+
+#define DMA_ALIGN_MASK 0x03
+
*** 115992 LINES SKIPPED ***


Reply via email to