Date: Fri, 27 Feb 2026 02:30:08 +0000 From: Bjoern A. Zeeb <bz@FreeBSD.org> To: src-committers@FreeBSD.org, dev-commits-src-all@FreeBSD.org, dev-commits-src-branches@FreeBSD.org Subject: git: a32802d07dc0 - stable/15 - brcm80211: import Broadcom wireless brcmsmac and brcmfmac drivers Message-ID: <69a101b0.21afa.61c82ca1@gitrepo.freebsd.org>
index | next in thread | raw e-mail
The branch stable/15 has been updated by bz: URL: https://cgit.FreeBSD.org/src/commit/?id=a32802d07dc0ef95854abd892ccba7b016a7490f commit a32802d07dc0ef95854abd892ccba7b016a7490f Author: Bjoern A. Zeeb <bz@FreeBSD.org> AuthorDate: 2026-02-10 21:22:03 +0000 Commit: Bjoern A. Zeeb <bz@FreeBSD.org> 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 ***home | help
Want to link to this message? Use this
URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?69a101b0.21afa.61c82ca1>
