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/941301b3b607
branches:  trunk
changeset: 746222:941301b3b607
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 01148a383c17 -r 941301b3b607 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 01148a383c17 -r 941301b3b607 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 01148a383c17 -r 941301b3b607 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