Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/dev - Refactor the firmware loading code into a set of c...
details: https://anonhg.NetBSD.org/src/rev/0d7337a7a3f7
branches: trunk
changeset: 1008511:0d7337a7a3f7
user: thorpej <thorpej%NetBSD.org@localhost>
date: Wed Mar 25 03:44:44 2020 +0000
description:
- Refactor the firmware loading code into a set of common routines in the
core driver that understand how to find model-specific files before the
generic files. This greatly simplifies the firmware loading procedure
in each of the bus front ends. Adding additional firmware file types
(such as CLM files) much simpler.
- Make firmware image selection table-driven rather than a set of switch()
and if() statements.
- Add several additional firmware image entries.
diffstat:
sys/dev/ic/bwfm.c | 176 +++++++++++++++++++++++++++++++-
sys/dev/ic/bwfmvar.h | 53 +++++++++-
sys/dev/pci/if_bwfm_pci.c | 130 +++++++++++++---------
sys/dev/sdmmc/if_bwfm_sdio.c | 240 +++++++++++++++++-------------------------
sys/dev/usb/if_bwfm_usb.c | 118 +++++++++-----------
5 files changed, 450 insertions(+), 267 deletions(-)
diffs (truncated from 987 to 300 lines):
diff -r 92a42a22b898 -r 0d7337a7a3f7 sys/dev/ic/bwfm.c
--- a/sys/dev/ic/bwfm.c Wed Mar 25 01:39:49 2020 +0000
+++ b/sys/dev/ic/bwfm.c Wed Mar 25 03:44:44 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: bwfm.c,v 1.20 2020/01/29 14:14:55 thorpej Exp $ */
+/* $NetBSD: bwfm.c,v 1.21 2020/03/25 03:44:44 thorpej Exp $ */
/* $OpenBSD: bwfm.c,v 1.5 2017/10/16 22:27:16 patrick Exp $ */
/*
* Copyright (c) 2010-2016 Broadcom Corporation
@@ -132,6 +132,180 @@
.proto_set_dcmd = bwfm_proto_bcdc_set_dcmd,
};
+static const struct {
+ const char *suffix;
+ const char *description;
+} bwfm_firmware_filetypes[] = {
+ [BWFM_FILETYPE_UCODE] = {
+ .suffix = "bin",
+ .description = "Firmware",
+ },
+ [BWFM_FILETYPE_NVRAM] = {
+ .suffix = "txt",
+ .description = "NVRAM",
+ },
+};
+
+static void
+bwfm_firmware_read_file(struct bwfm_softc * const sc,
+ const struct bwfm_firmware_selector * const fwp,
+ struct bwfm_firmware_context * const ctx,
+ unsigned int const which)
+{
+ firmware_handle_t fwh;
+ char *names[2];
+ int i, error;
+
+ names[1] = kmem_asprintf("%s.%s", fwp->fwsel_basename,
+ bwfm_firmware_filetypes[which].suffix);
+ if (ctx->ctx_model)
+ names[0] = ctx->ctx_model ? kmem_asprintf("%s.%s.%s",
+ fwp->fwsel_basename, ctx->ctx_model,
+ bwfm_firmware_filetypes[which].suffix) : NULL;
+
+ aprint_verbose_dev(sc->sc_dev, "%s file default: %s\n",
+ bwfm_firmware_filetypes[which].description, names[1]);
+ if (names[0]) {
+ aprint_verbose_dev(sc->sc_dev, "%s file model-spec: %s\n",
+ bwfm_firmware_filetypes[which].description, names[0]);
+ }
+
+ for (i = 0; i < 2; i++) {
+ if (names[i] == NULL)
+ continue;
+ error = firmware_open("if_bwfm", names[i], &fwh);
+ if (error == 0)
+ break;
+ }
+ if (i == 2)
+ goto out;
+
+ aprint_verbose_dev(sc->sc_dev, "Found %s file: %s\n",
+ bwfm_firmware_filetypes[which].description, names[i]);
+
+ size_t size = firmware_get_size(fwh);
+ void *data = firmware_malloc(size);
+ if (data == NULL) {
+ aprint_error_dev(sc->sc_dev,
+ "unable to allocate %zu bytes for %s image\n", size,
+ bwfm_firmware_filetypes[which].description);
+ firmware_close(fwh);
+ goto out;
+ }
+ error = firmware_read(fwh, 0, data, size);
+ firmware_close(fwh);
+ if (error) {
+ aprint_error_dev(sc->sc_dev,
+ "failed to read %s file, error %d\n",
+ bwfm_firmware_filetypes[which].description,
+ error);
+ firmware_free(data, size);
+ goto out;
+ }
+
+ ctx->ctx_file[which].ctx_f_data = data;
+ ctx->ctx_file[which].ctx_f_size = size;
+ out:
+ for (i = 0; i < 2; i++) {
+ if (names[i])
+ kmem_free(names[i], strlen(names[i])+1);
+ }
+}
+
+void
+bwfm_firmware_context_init(struct bwfm_firmware_context * const ctx,
+ uint32_t const chip, uint32_t const chiprev, const char * const model,
+ uint32_t req)
+{
+ memset(ctx, 0, sizeof(*ctx));
+ ctx->ctx_chip = chip;
+ ctx->ctx_chiprev = chiprev;
+ ctx->ctx_model = model;
+
+ /* all devices require ucode */
+ ctx->ctx_req = req | BWFM_FWREQ(BWFM_FILETYPE_UCODE);
+}
+
+bool
+bwfm_firmware_open(struct bwfm_softc * const sc,
+ const struct bwfm_firmware_selector * const fwtab,
+ struct bwfm_firmware_context * const ctx)
+{
+ const struct bwfm_firmware_selector *fwp;
+ unsigned int i;
+
+ KASSERT(fwtab != NULL);
+ KASSERT(ctx != NULL);
+
+ /* First locate the appropriate entry for this chip / rev. */
+ for (fwp = fwtab; fwp->fwsel_basename != NULL; fwp++) {
+ if (fwp->fwsel_chip == ctx->ctx_chip &&
+ fwp->fwsel_revmask & __BIT(ctx->ctx_chiprev))
+ break;
+ }
+ if (fwp->fwsel_basename == NULL) {
+ aprint_error_dev(sc->sc_dev,
+ "No firmware entry for chip 0x%x/%u rev %u model %s\n",
+ ctx->ctx_chip, ctx->ctx_chip, ctx->ctx_chiprev,
+ ctx->ctx_model);
+ return false;
+ }
+
+ bool rv = true;
+
+ /*
+ * Read in each file that the front-end has requested as
+ * either required or optional.
+ */
+ for (i = 0; i < BWFM_NFILETYPES; i++) {
+ if (ctx->ctx_req & (BWFM_FWREQ(i) | BWFM_FWOPT(i)))
+ bwfm_firmware_read_file(sc, fwp, ctx, i);
+ if ((ctx->ctx_req & BWFM_FWREQ(i)) &&
+ ctx->ctx_file[i].ctx_f_data == NULL) {
+ aprint_error_dev(sc->sc_dev,
+ "%s file not available\n",
+ bwfm_firmware_filetypes[i].description);
+ rv = false;
+ }
+ }
+
+ if (rv == false)
+ bwfm_firmware_close(ctx);
+
+ return rv;
+}
+
+void
+bwfm_firmware_close(struct bwfm_firmware_context * const ctx)
+{
+ for (int i = 0; i < BWFM_NFILETYPES; i++) {
+ if (ctx->ctx_file[i].ctx_f_data == NULL)
+ continue;
+ firmware_free(ctx->ctx_file[i].ctx_f_data,
+ ctx->ctx_file[i].ctx_f_size);
+ ctx->ctx_file[i].ctx_f_data = NULL;
+ }
+}
+
+void *
+bwfm_firmware_data(struct bwfm_firmware_context * const ctx,
+ unsigned int const which, size_t *sizep)
+{
+ KASSERT(which < BWFM_NFILETYPES);
+ KASSERT(sizep != NULL);
+
+ *sizep = ctx->ctx_file[which].ctx_f_size;
+ return ctx->ctx_file[which].ctx_f_data;
+}
+
+const char *
+bwfm_firmware_description(unsigned int const which)
+{
+ KASSERT(which < BWFM_NFILETYPES);
+
+ return bwfm_firmware_filetypes[which].description;
+}
+
void
bwfm_attach(struct bwfm_softc *sc)
{
diff -r 92a42a22b898 -r 0d7337a7a3f7 sys/dev/ic/bwfmvar.h
--- a/sys/dev/ic/bwfmvar.h Wed Mar 25 01:39:49 2020 +0000
+++ b/sys/dev/ic/bwfmvar.h Wed Mar 25 03:44:44 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: bwfmvar.h,v 1.6 2020/03/22 23:38:47 thorpej Exp $ */
+/* $NetBSD: bwfmvar.h,v 1.7 2020/03/25 03:44:44 thorpej Exp $ */
/* $OpenBSD: bwfmvar.h,v 1.1 2017/10/11 17:19:50 patrick Exp $ */
/*
* Copyright (c) 2010-2016 Broadcom Corporation
@@ -18,6 +18,7 @@
*/
#include <sys/pcq.h>
+#include <dev/firmload.h>
/* Chipcommon Core Chip IDs */
#define BRCM_CC_43143_CHIP_ID 43143
@@ -62,8 +63,46 @@
#define BWFM_TASK_COUNT 256
+struct bwfm_softc;
-struct bwfm_softc;
+struct bwfm_firmware_selector {
+ uint32_t fwsel_chip; /* chip ID */
+ uint32_t fwsel_revmask; /* mask of applicable chip revs */
+ const char *fwsel_basename;/* firmware file base name */
+};
+#define BWFM_FW_ENTRY(c, r, b) \
+ { .fwsel_chip = (c), \
+ .fwsel_revmask = (r), \
+ .fwsel_basename = b }
+
+#define BWFM_FW_ENTRY_END \
+ { .fwsel_basename = NULL }
+
+#define BWFM_FWSEL_REV_EQ(x) __BIT(x)
+#define BWFM_FWSEL_REV_LE(x) __BITS(0,x)
+#define BWFM_FWSEL_REV_GE(x) __BITS(x,31)
+#define BWFM_FWSEL_ALLREVS __BITS(0,31)
+
+#define BWFM_FILETYPE_UCODE 0
+#define BWFM_FILETYPE_NVRAM 1
+#define BWFM_NFILETYPES 2
+
+struct bwfm_firmware_context {
+ /* inputs */
+ uint32_t ctx_chip;
+ uint32_t ctx_chiprev;
+ const char * ctx_model;
+ uint32_t ctx_req;
+
+#define BWFM_FWREQ(x) __BIT(x)
+#define BWFM_FWOPT(x) __BIT((x)+16)
+
+ /* outputs */
+ struct {
+ void * ctx_f_data;
+ size_t ctx_f_size;
+ } ctx_file[BWFM_NFILETYPES];
+};
struct bwfm_core {
uint16_t co_id;
@@ -190,3 +229,13 @@
struct bwfm_core *bwfm_chip_get_core(struct bwfm_softc *, int);
struct bwfm_core *bwfm_chip_get_pmu(struct bwfm_softc *);
void bwfm_rx(struct bwfm_softc *, struct mbuf *m);
+
+void bwfm_firmware_context_init(struct bwfm_firmware_context *,
+ uint32_t, uint32_t, const char *, uint32_t);
+bool bwfm_firmware_open(struct bwfm_softc *,
+ const struct bwfm_firmware_selector *,
+ struct bwfm_firmware_context *);
+void bwfm_firmware_close(struct bwfm_firmware_context *);
+void * bwfm_firmware_data(struct bwfm_firmware_context *,
+ unsigned int, size_t *);
+const char *bwfm_firmware_description(unsigned int);
diff -r 92a42a22b898 -r 0d7337a7a3f7 sys/dev/pci/if_bwfm_pci.c
--- a/sys/dev/pci/if_bwfm_pci.c Wed Mar 25 01:39:49 2020 +0000
+++ b/sys/dev/pci/if_bwfm_pci.c Wed Mar 25 03:44:44 2020 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: if_bwfm_pci.c,v 1.6 2018/12/09 11:14:02 jdolecek Exp $ */
+/* $NetBSD: if_bwfm_pci.c,v 1.7 2020/03/25 03:44:45 thorpej Exp $ */
/* $OpenBSD: if_bwfm_pci.c,v 1.18 2018/02/08 05:00:38 patrick Exp $ */
/*
* Copyright (c) 2010-2016 Broadcom Corporation
@@ -37,8 +37,6 @@
#include <net80211/ieee80211_var.h>
-#include <dev/firmload.h>
-
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcidevs.h>
@@ -319,6 +317,55 @@
CFATTACH_DECL_NEW(bwfm_pci, sizeof(struct bwfm_pci_softc),
bwfm_pci_match, bwfm_pci_attach, bwfm_pci_detach, NULL);
+static const struct bwfm_firmware_selector bwfm_pci_fwtab[] = {
+ BWFM_FW_ENTRY(BRCM_CC_43602_CHIP_ID,
+ BWFM_FWSEL_ALLREVS, "brcmfmac43602-pcie"),
+
+ BWFM_FW_ENTRY(BRCM_CC_43465_CHIP_ID,
+ BWFM_FWSEL_REV_GE(4), "brcmfmac4366c-pcie"),
+
+ BWFM_FW_ENTRY(BRCM_CC_4350_CHIP_ID,
+ BWFM_FWSEL_REV_LE(7), "brcmfmac4350c2-pcie"),
Home |
Main Index |
Thread Index |
Old Index