Module Name: src Committed By: thorpej Date: Wed Mar 25 03:44:45 UTC 2020
Modified Files: src/sys/dev/ic: bwfm.c bwfmvar.h src/sys/dev/pci: if_bwfm_pci.c src/sys/dev/sdmmc: if_bwfm_sdio.c src/sys/dev/usb: if_bwfm_usb.c Log Message: - 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. To generate a diff of this commit: cvs rdiff -u -r1.20 -r1.21 src/sys/dev/ic/bwfm.c cvs rdiff -u -r1.6 -r1.7 src/sys/dev/ic/bwfmvar.h cvs rdiff -u -r1.6 -r1.7 src/sys/dev/pci/if_bwfm_pci.c cvs rdiff -u -r1.13 -r1.14 src/sys/dev/sdmmc/if_bwfm_sdio.c cvs rdiff -u -r1.10 -r1.11 src/sys/dev/usb/if_bwfm_usb.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/sys/dev/ic/bwfm.c diff -u src/sys/dev/ic/bwfm.c:1.20 src/sys/dev/ic/bwfm.c:1.21 --- src/sys/dev/ic/bwfm.c:1.20 Wed Jan 29 14:14:55 2020 +++ src/sys/dev/ic/bwfm.c Wed Mar 25 03:44:44 2020 @@ -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 @@ struct bwfm_proto_ops bwfm_proto_bcdc_op .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) { Index: src/sys/dev/ic/bwfmvar.h diff -u src/sys/dev/ic/bwfmvar.h:1.6 src/sys/dev/ic/bwfmvar.h:1.7 --- src/sys/dev/ic/bwfmvar.h:1.6 Sun Mar 22 23:38:47 2020 +++ src/sys/dev/ic/bwfmvar.h Wed Mar 25 03:44:44 2020 @@ -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,9 +63,47 @@ #define BWFM_TASK_COUNT 256 - 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; uint16_t co_rev; @@ -190,3 +229,13 @@ int bwfm_chip_sr_capable(struct bwfm_sof 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); Index: src/sys/dev/pci/if_bwfm_pci.c diff -u src/sys/dev/pci/if_bwfm_pci.c:1.6 src/sys/dev/pci/if_bwfm_pci.c:1.7 --- src/sys/dev/pci/if_bwfm_pci.c:1.6 Sun Dec 9 11:14:02 2018 +++ src/sys/dev/pci/if_bwfm_pci.c Wed Mar 25 03:44:45 2020 @@ -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 @@ struct bwfm_proto_ops bwfm_pci_msgbuf_op 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"), + BWFM_FW_ENTRY(BRCM_CC_4350_CHIP_ID, + BWFM_FWSEL_REV_GE(8), "brcmfmac4350-pcie"), + + BWFM_FW_ENTRY(BRCM_CC_43525_CHIP_ID, + BWFM_FWSEL_REV_GE(4), "brcmfmac4365c-pcie"), + + BWFM_FW_ENTRY(BRCM_CC_4356_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac4356-pcie"), + + BWFM_FW_ENTRY(BRCM_CC_43567_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac43570-pcie"), + BWFM_FW_ENTRY(BRCM_CC_43569_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac43570-pcie"), + BWFM_FW_ENTRY(BRCM_CC_43570_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac43570-pcie"), + + BWFM_FW_ENTRY(BRCM_CC_4358_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac4358-pcie"), + + BWFM_FW_ENTRY(BRCM_CC_4359_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac4359-pcie"), + + BWFM_FW_ENTRY(BRCM_CC_4365_CHIP_ID, + BWFM_FWSEL_REV_LE(3), "brcmfmac4365b-pcie"), + BWFM_FW_ENTRY(BRCM_CC_4365_CHIP_ID, + BWFM_FWSEL_REV_GE(4), "brcmfmac4365c-pcie"), + + BWFM_FW_ENTRY(BRCM_CC_4366_CHIP_ID, + BWFM_FWSEL_REV_LE(3), "brcmfmac4366b-pcie"), + BWFM_FW_ENTRY(BRCM_CC_4366_CHIP_ID, + BWFM_FWSEL_REV_GE(4), "brcmfmac4366c-pcie"), + BWFM_FW_ENTRY(BRCM_CC_43664_CHIP_ID, + BWFM_FWSEL_REV_GE(4), "brcmfmac4366c-pcie"), + + BWFM_FW_ENTRY(BRCM_CC_4371_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac4371-pcie"), + + BWFM_FW_ENTRY_END +}; + static const struct bwfm_pci_matchid { pci_vendor_id_t bwfm_vendor; pci_product_id_t bwfm_product; @@ -426,18 +473,17 @@ bwfm_pci_attachhook(device_t self) struct bwfm_pci_softc *sc = device_private(self); struct bwfm_softc *bwfm = (void *)sc; struct bwfm_pci_ringinfo ringinfo; - const char *name = NULL; - firmware_handle_t fwh; - u_char *ucode; size_t size; + struct bwfm_firmware_context fwctx; + uint8_t *ucode; + size_t ucsize; uint32_t d2h_w_idx_ptr, d2h_r_idx_ptr; uint32_t h2d_w_idx_ptr, h2d_r_idx_ptr; uint32_t idx_offset, reg; int i; - int error; sc->sc_sc.sc_buscore_ops = &bwfm_pci_buscore_ops; if (bwfm_chip_attach(&sc->sc_sc) != 0) { - printf("%s: cannot attach chip\n", DEVNAME(sc)); + aprint_error_dev(bwfm->sc_dev, "cannot attach chip\n"); return; } @@ -449,68 +495,39 @@ bwfm_pci_attachhook(device_t self) bus_space_write_4(sc->sc_reg_iot, sc->sc_reg_ioh, BWFM_PCI_PCIE2REG_CONFIGDATA, reg); - switch (bwfm->sc_chip.ch_chip) - { - case BRCM_CC_4350_CHIP_ID: - if (bwfm->sc_chip.ch_chiprev > 7) - name = "brcmfmac4350-pcie.bin"; - else - name = "brcmfmac4350c2-pcie.bin"; - break; - case BRCM_CC_43602_CHIP_ID: - name = "brcmfmac43602-pcie.bin"; - break; - default: - printf("%s: unknown firmware for chip %s\n", - DEVNAME(sc), bwfm->sc_chip.ch_name); - return; + bwfm_firmware_context_init(&fwctx, + bwfm->sc_chip.ch_chip, bwfm->sc_chip.ch_chiprev, NULL, + BWFM_FWREQ(BWFM_FILETYPE_UCODE)); + + if (!bwfm_firmware_open(bwfm, bwfm_pci_fwtab, &fwctx)) { + /* Error message already displayed. */ + goto err; } - if (firmware_open("if_bwfm", name, &fwh) != 0) { - printf("%s: failed firmware_open of file %s\n", - DEVNAME(sc), name); - return; - } - size = firmware_get_size(fwh); - ucode = firmware_malloc(size); - if (ucode == NULL) { - printf("%s: failed to allocate firmware memory\n", - DEVNAME(sc)); - firmware_close(fwh); - return; - } - error = firmware_read(fwh, 0, ucode, size); - firmware_close(fwh); - if (error != 0) { - printf("%s: failed to read firmware (error %d)\n", - DEVNAME(sc), error); - firmware_free(ucode, size); - return; - } + ucode = bwfm_firmware_data(&fwctx, BWFM_FILETYPE_UCODE, &ucsize); + KASSERT(ucode != NULL); /* Retrieve RAM size from firmware. */ - if (size >= BWFM_RAMSIZE + 8) { + if (ucsize >= BWFM_RAMSIZE + 8) { uint32_t *ramsize = (uint32_t *)&ucode[BWFM_RAMSIZE]; if (letoh32(ramsize[0]) == BWFM_RAMSIZE_MAGIC) bwfm->sc_chip.ch_ramsize = letoh32(ramsize[1]); } - if (bwfm_pci_load_microcode(sc, ucode, size) != 0) { - printf("%s: could not load microcode\n", - DEVNAME(sc)); - kmem_free(ucode, size); - return; + if (bwfm_pci_load_microcode(sc, ucode, ucsize) != 0) { + aprint_error_dev(bwfm->sc_dev, "could not load microcode\n"); + goto err; } - firmware_free(ucode, size); + bwfm_firmware_close(&fwctx); sc->sc_shared_flags = bus_space_read_4(sc->sc_tcm_iot, sc->sc_tcm_ioh, sc->sc_shared_address + BWFM_SHARED_INFO); sc->sc_shared_version = sc->sc_shared_flags; if (sc->sc_shared_version > BWFM_SHARED_INFO_MAX_VERSION || sc->sc_shared_version < BWFM_SHARED_INFO_MIN_VERSION) { - printf("%s: PCIe version %d unsupported\n", - DEVNAME(sc), sc->sc_shared_version); + aprint_error_dev(bwfm->sc_dev, + "PCIe version %d unsupported\n", sc->sc_shared_version); return; } @@ -580,8 +597,8 @@ bwfm_pci_attachhook(device_t self) sc->sc_dma_idx_bufsz, 8); if (sc->sc_dma_idx_buf == NULL) { /* XXX: Fallback to TCM? */ - printf("%s: cannot allocate idx buf\n", - DEVNAME(sc)); + aprint_error_dev(bwfm->sc_dev, + "cannot allocate idx buf\n"); return; } @@ -763,6 +780,9 @@ cleanup: bwfm_pci_dmamem_free(sc, sc->sc_ctrl_submit.ring); if (sc->sc_dma_idx_buf) bwfm_pci_dmamem_free(sc, sc->sc_dma_idx_buf); + + err: + bwfm_firmware_close(&fwctx); } int Index: src/sys/dev/sdmmc/if_bwfm_sdio.c diff -u src/sys/dev/sdmmc/if_bwfm_sdio.c:1.13 src/sys/dev/sdmmc/if_bwfm_sdio.c:1.14 --- src/sys/dev/sdmmc/if_bwfm_sdio.c:1.13 Wed Jan 29 06:00:27 2020 +++ src/sys/dev/sdmmc/if_bwfm_sdio.c Wed Mar 25 03:44:45 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: if_bwfm_sdio.c,v 1.13 2020/01/29 06:00:27 thorpej Exp $ */ +/* $NetBSD: if_bwfm_sdio.c,v 1.14 2020/03/25 03:44:45 thorpej Exp $ */ /* $OpenBSD: if_bwfm_sdio.c,v 1.1 2017/10/11 17:19:50 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation @@ -39,8 +39,6 @@ #include <dev/ofw/openfirm.h> #include <dev/fdt/fdtvar.h> -#include <dev/firmload.h> - #include <net80211/ieee80211_var.h> #include <dev/sdmmc/sdmmcdevs.h> @@ -188,6 +186,66 @@ static void bwfm_sdio_rx_glom(struct bwf static void bwfm_sdio_debug_console(struct bwfm_sdio_softc *); #endif +static const struct bwfm_firmware_selector bwfm_sdio_fwtab[] = { + BWFM_FW_ENTRY(BRCM_CC_43143_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac43143-sdio"), + + BWFM_FW_ENTRY(BRCM_CC_43241_CHIP_ID, + BWFM_FWSEL_REV_LE(4), "brcmfmac43241b0-sdio"), + BWFM_FW_ENTRY(BRCM_CC_43241_CHIP_ID, + BWFM_FWSEL_REV_EQ(5), "brcmfmac43241b4-sdio"), + BWFM_FW_ENTRY(BRCM_CC_43241_CHIP_ID, + BWFM_FWSEL_REV_GE(6), "brcmfmac43241b5-sdio"), + + BWFM_FW_ENTRY(BRCM_CC_4329_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac4329-sdio"), + + BWFM_FW_ENTRY(BRCM_CC_4330_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac4330-sdio"), + + BWFM_FW_ENTRY(BRCM_CC_4334_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac4334-sdio"), + + BWFM_FW_ENTRY(BRCM_CC_43340_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac43340-sdio"), + BWFM_FW_ENTRY(BRCM_CC_43341_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac43340-sdio"), + + BWFM_FW_ENTRY(BRCM_CC_4335_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac4335-sdio"), + + BWFM_FW_ENTRY(BRCM_CC_43362_CHIP_ID, + BWFM_FWSEL_REV_GE(1), "brcmfmac43362-sdio"), + + BWFM_FW_ENTRY(BRCM_CC_4339_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac4339-sdio"), + + BWFM_FW_ENTRY(BRCM_CC_43430_CHIP_ID, + BWFM_FWSEL_REV_EQ(0), "brcmfmac43430a0-sdio"), + BWFM_FW_ENTRY(BRCM_CC_43430_CHIP_ID, + BWFM_FWSEL_REV_GE(1), "brcmfmac43430-sdio"), + + BWFM_FW_ENTRY(BRCM_CC_4345_CHIP_ID, + BWFM_FWSEL_REV_EQ(9), "brcmfmac43456-sdio"), + BWFM_FW_ENTRY(BRCM_CC_4345_CHIP_ID, + BWFM_FWSEL_REV_LE(8) + BWFM_FWSEL_REV_GE(10), + "brcmfmac43455-sdio"), + + BWFM_FW_ENTRY(BRCM_CC_4354_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac4354-sdio"), + + BWFM_FW_ENTRY(BRCM_CC_4356_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac4356-sdio"), + + BWFM_FW_ENTRY(CY_CC_4373_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac4373-sdio"), + + BWFM_FW_ENTRY(CY_CC_43012_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac43012-sdio"), + + BWFM_FW_ENTRY_END +}; + struct bwfm_bus_ops bwfm_sdio_bus_ops = { .bs_init = NULL, .bs_stop = NULL, @@ -382,153 +440,55 @@ bwfm_sdio_attachhook(device_t self) { struct bwfm_sdio_softc *sc = device_private(self); struct bwfm_softc *bwfm = &sc->sc_sc; - firmware_handle_t fwh; - const char *name, *nvname, *model; - char *nvnamebuf; - u_char *ucode, *nvram; - size_t size, nvlen, nvsize; + struct bwfm_firmware_context fwctx; + size_t ucsize = 0, nvlen = 0, nvsize = 0; + uint8_t *ucode, *nvram; uint32_t reg, clk; - int error; DPRINTF(("%s: chip 0x%08x rev %u\n", DEVNAME(sc), bwfm->sc_chip.ch_chip, bwfm->sc_chip.ch_chiprev)); - switch (bwfm->sc_chip.ch_chip) { - case BRCM_CC_4330_CHIP_ID: - name = "brcmfmac4330-sdio.bin"; - nvname = "brcmfmac4330-sdio.txt"; - break; - case BRCM_CC_4334_CHIP_ID: - name = "brcmfmac4334-sdio.bin"; - nvname = "brcmfmac4334-sdio.txt"; - break; - case BRCM_CC_4345_CHIP_ID: - if ((0x200 & __BIT(bwfm->sc_chip.ch_chiprev)) != 0) { - name = "brcmfmac43456-sdio.bin"; - nvname = "brcmfmac43456-sdio.txt"; - } else { - name = "brcmfmac43455-sdio.bin"; - nvname = "brcmfmac43455-sdio.txt"; - } - break; - case BRCM_CC_43340_CHIP_ID: - name = "brcmfmac43340-sdio.bin"; - nvname = "brcmfmac43340-sdio.txt"; - break; - case BRCM_CC_4335_CHIP_ID: - if (bwfm->sc_chip.ch_chiprev < 2) { - name = "brcmfmac4335-sdio.bin"; - nvname = "brcmfmac4335-sdio.txt"; - } else { - name = "brcmfmac4339-sdio.bin"; - nvname = "brcmfmac4339-sdio.txt"; - bwfm->sc_chip.ch_chip = BRCM_CC_4339_CHIP_ID; - } - break; - case BRCM_CC_4339_CHIP_ID: - name = "brcmfmac4339-sdio.bin"; - nvname = "brcmfmac4339-sdio.txt"; - break; - case BRCM_CC_43430_CHIP_ID: - if (bwfm->sc_chip.ch_chiprev == 0) { - name = "brcmfmac43430a0-sdio.bin"; - nvname = "brcmfmac43430a0-sdio.txt"; - } else { - name = "brcmfmac43430-sdio.bin"; - nvname = "brcmfmac43430-sdio.txt"; - } - break; - case BRCM_CC_4356_CHIP_ID: - name = "brcmfmac4356-sdio.bin"; - nvname = "brcmfmac4356-sdio.txt"; - break; - default: - printf("%s: unknown firmware for chip %s\n", - DEVNAME(sc), bwfm->sc_chip.ch_name); - goto err; - } - /* compute a model specific filename for the NV config */ - nvnamebuf = NULL; - model = bwfm_fdt_get_model(); - if (model != NULL) { - /* assume nvname ends in ".txt" */ - nvnamebuf = kmem_asprintf("%.*s.%s.txt", - (int)(strlen(nvname) - 4), - nvname, model); - } - - aprint_verbose_dev(self, "Firmware %s\n", name); - aprint_verbose_dev(self, "Default Config %s\n", nvname); - if (nvnamebuf != NULL) - aprint_verbose_dev(self, "Model Config %s\n", nvnamebuf); - - if (firmware_open("if_bwfm", name, &fwh) != 0) { - printf("%s: failed firmware_open of file %s\n", - DEVNAME(sc), name); - goto err; - } - size = firmware_get_size(fwh); - ucode = firmware_malloc(size); - if (ucode == NULL) { - printf("%s: failed firmware_open of file %s\n", - DEVNAME(sc), name); - firmware_close(fwh); + /* + * 4335s >= rev 2 are considered 4339s. + */ + if (bwfm->sc_chip.ch_chip == BRCM_CC_4335_CHIP_ID && + bwfm->sc_chip.ch_chiprev >= 2) + bwfm->sc_chip.ch_chip = BRCM_CC_4339_CHIP_ID; + + bwfm_firmware_context_init(&fwctx, + bwfm->sc_chip.ch_chip, bwfm->sc_chip.ch_chiprev, + bwfm_fdt_get_model(), + BWFM_FWREQ(BWFM_FILETYPE_UCODE) | BWFM_FWREQ(BWFM_FILETYPE_NVRAM)); + + if (!bwfm_firmware_open(bwfm, bwfm_sdio_fwtab, &fwctx)) { + /* Error message already displayed. */ goto err; } - error = firmware_read(fwh, 0, ucode, size); - firmware_close(fwh); - if (error != 0) { - printf("%s: failed to read firmware (error %d)\n", - DEVNAME(sc), error); - goto err1; - } - - if ((nvnamebuf == NULL || firmware_open("if_bwfm", nvnamebuf, &fwh) != 0) - && firmware_open("if_bwfm", nvname, &fwh) != 0) { - printf("%s: failed firmware_open of file %s\n", - DEVNAME(sc), nvname); - goto err1; - } - nvlen = firmware_get_size(fwh); - nvram = firmware_malloc(nvlen); - if (nvram == NULL) { - printf("%s: failed firmware_open of file %s\n", - DEVNAME(sc), name); - firmware_close(fwh); - goto err1; - } - error = firmware_read(fwh, 0, nvram, nvlen); - firmware_close(fwh); - if (error != 0) { - printf("%s: failed to read firmware (error %d)\n", - DEVNAME(sc), error); - goto err2; - } + + ucode = bwfm_firmware_data(&fwctx, BWFM_FILETYPE_UCODE, &ucsize); + KASSERT(ucode != NULL); + nvram = bwfm_firmware_data(&fwctx, BWFM_FILETYPE_NVRAM, &nvlen); + KASSERT(nvram != NULL); if (bwfm_nvram_convert(nvram, nvlen, &nvsize)) { - printf("%s: failed to convert nvram\n", DEVNAME(sc)); - goto err2; + aprint_error_dev(bwfm->sc_dev, + "unable to convert %s file\n", + bwfm_firmware_description(BWFM_FILETYPE_NVRAM)); + goto err; } sc->sc_alp_only = true; - if (bwfm_sdio_load_microcode(sc, ucode, size, nvram, nvsize) != 0) { - printf("%s: could not load microcode\n", - DEVNAME(sc)); - goto err2; + if (bwfm_sdio_load_microcode(sc, ucode, ucsize, nvram, nvsize) != 0) { + aprint_error_dev(bwfm->sc_dev, "could not load microcode\n"); + goto err; } sc->sc_alp_only = false; - firmware_free(nvram, nvlen); - firmware_free(ucode, size); - if (nvnamebuf != NULL) - kmem_free(nvnamebuf, strlen(nvnamebuf)+1); - sdmmc_pause(hztoms(1)*1000, NULL); bwfm_sdio_clkctl(sc, CLK_AVAIL, false); if (sc->sc_clkstate != CLK_AVAIL) { - printf("%s: could not access clock\n", - DEVNAME(sc)); + aprint_error_dev(bwfm->sc_dev, "could not access clock\n"); goto err; } @@ -539,7 +499,7 @@ bwfm_sdio_attachhook(device_t self) bwfm_sdio_dev_write(sc, SDPCMD_TOSBMAILBOXDATA, SDPCM_PROT_VERSION << SDPCM_PROT_VERSION_SHIFT); if (sdmmc_io_function_enable(sc->sc_sf[2])) { - printf("%s: cannot enable function 2\n", DEVNAME(sc)); + aprint_error_dev(bwfm->sc_dev, "cannot enable function 2\n"); goto err; } @@ -589,16 +549,8 @@ bwfm_sdio_attachhook(device_t self) bwfm_attach(&sc->sc_sc); sc->sc_bwfm_attached = true; - return; - -err2: - firmware_free(nvram, nvlen); -err1: - firmware_free(ucode, size); - if (nvnamebuf != NULL) - kmem_free(nvnamebuf, strlen(nvnamebuf)+1); -err: - return; + err: + bwfm_firmware_close(&fwctx); } static int @@ -1129,7 +1081,7 @@ bwfm_nvram_convert(u_char *buf, size_t l skip = true; continue; } - if (*src == '\r') + if (*src == '\r' || *src == ' ') continue; *dst++ = *src; ++count; @@ -1152,7 +1104,7 @@ bwfm_nvram_convert(u_char *buf, size_t l memcpy(dst, &token, sizeof(token)); count += sizeof(token); - *newlenp = count ; + *newlenp = count; return 0; } Index: src/sys/dev/usb/if_bwfm_usb.c diff -u src/sys/dev/usb/if_bwfm_usb.c:1.10 src/sys/dev/usb/if_bwfm_usb.c:1.11 --- src/sys/dev/usb/if_bwfm_usb.c:1.10 Wed Jan 29 06:26:32 2020 +++ src/sys/dev/usb/if_bwfm_usb.c Wed Mar 25 03:44:45 2020 @@ -1,4 +1,4 @@ -/* $NetBSD: if_bwfm_usb.c,v 1.10 2020/01/29 06:26:32 thorpej Exp $ */ +/* $NetBSD: if_bwfm_usb.c,v 1.11 2020/03/25 03:44:45 thorpej Exp $ */ /* $OpenBSD: if_bwfm_usb.c,v 1.2 2017/10/15 14:55:13 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation @@ -18,7 +18,7 @@ */ #include <sys/cdefs.h> -__KERNEL_RCSID(0, "$NetBSD: if_bwfm_usb.c,v 1.10 2020/01/29 06:26:32 thorpej Exp $"); +__KERNEL_RCSID(0, "$NetBSD: if_bwfm_usb.c,v 1.11 2020/03/25 03:44:45 thorpej Exp $"); #include <sys/param.h> #include <sys/systm.h> @@ -42,8 +42,6 @@ __KERNEL_RCSID(0, "$NetBSD: if_bwfm_usb. #include <net80211/ieee80211_var.h> -#include <dev/firmload.h> - #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> #include <dev/usb/usbdi_util.h> @@ -53,6 +51,31 @@ __KERNEL_RCSID(0, "$NetBSD: if_bwfm_usb. #include <dev/ic/bwfmvar.h> #include <dev/ic/bwfmreg.h> +static const struct bwfm_firmware_selector bwfm_usb_fwtab[] = { + BWFM_FW_ENTRY(BRCM_CC_43143_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac43143"), + + BWFM_FW_ENTRY(BRCM_CC_43235_CHIP_ID, + BWFM_FWSEL_REV_EQ(3), "brcmfmac43236b"), + BWFM_FW_ENTRY(BRCM_CC_43236_CHIP_ID, + BWFM_FWSEL_REV_EQ(3), "brcmfmac43236b"), + BWFM_FW_ENTRY(BRCM_CC_43238_CHIP_ID, + BWFM_FWSEL_REV_EQ(3), "brcmfmac43236b"), + + BWFM_FW_ENTRY(BRCM_CC_43242_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac43242a"), + + BWFM_FW_ENTRY(BRCM_CC_43566_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac43569"), + BWFM_FW_ENTRY(BRCM_CC_43569_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac43569"), + + BWFM_FW_ENTRY(CY_CC_4373_CHIP_ID, + BWFM_FWSEL_ALLREVS, "brcmfmac4373"), + + BWFM_FW_ENTRY_END +}; + /* * Various supported device vendors/products. */ @@ -310,13 +333,13 @@ void bwfm_usb_attachhook(device_t self) { struct bwfm_usb_softc *sc = device_private(self); + struct bwfm_softc *bwfm = &sc->sc_sc; struct bwfm_usb_rx_data *data; - const char *name = NULL; struct bootrom_id brom; - firmware_handle_t fwh; + struct bwfm_firmware_context fwctx; usbd_status error; u_char *ucode; - size_t size; + size_t ucsize; int i; /* Read chip id and chip rev to check the firmware. */ @@ -329,76 +352,41 @@ bwfm_usb_attachhook(device_t self) error = usbd_open_pipe(sc->sc_iface, sc->sc_rx_no, USBD_EXCLUSIVE_USE, &sc->sc_rx_pipeh); if (error != 0) { - printf("%s: could not open rx pipe: %s\n", - DEVNAME(sc), usbd_errstr(error)); + aprint_error_dev(bwfm->sc_dev, "could not open rx pipe: %s\n", + usbd_errstr(error)); return; } error = usbd_open_pipe(sc->sc_iface, sc->sc_tx_no, USBD_EXCLUSIVE_USE, &sc->sc_tx_pipeh); if (error != 0) { - printf("%s: could not open tx pipe: %s\n", - DEVNAME(sc), usbd_errstr(error)); + aprint_error_dev(bwfm->sc_dev, "could not open tx pipe: %s\n", + usbd_errstr(error)); return; } /* Firmware not yet loaded? */ if (sc->sc_chip != BRCMF_POSTBOOT_ID) { - switch (sc->sc_chip) - { - case BRCM_CC_43143_CHIP_ID: - name = "brcmfmac43143.bin"; - break; - case BRCM_CC_43235_CHIP_ID: - case BRCM_CC_43236_CHIP_ID: - case BRCM_CC_43238_CHIP_ID: - if (sc->sc_chiprev == 3) - name = "brcmfmac43236b.bin"; - break; - case BRCM_CC_43242_CHIP_ID: - name = "brcmfmac43242a.bin"; - break; - case BRCM_CC_43566_CHIP_ID: - case BRCM_CC_43569_CHIP_ID: - name = "brcmfmac43569.bin"; - break; - default: - break; - } + bwfm_firmware_context_init(&fwctx, + sc->sc_chip, sc->sc_chiprev, NULL, + BWFM_FWREQ(BWFM_FILETYPE_UCODE)); - if (name == NULL) { - printf("%s: unknown firmware\n", DEVNAME(sc)); + if (!bwfm_firmware_open(bwfm, bwfm_usb_fwtab, &fwctx)) { + /* Error message already displayed. */ return; } - if (firmware_open("if_bwfm", name, &fwh) != 0) { - printf("%s: failed firmware_open of file %s\n", - DEVNAME(sc), name); - return; - } - size = firmware_get_size(fwh); - ucode = firmware_malloc(size); - if (ucode == NULL) { - printf("%s: failed to allocate firmware memory\n", - DEVNAME(sc)); - firmware_close(fwh); - return; - } - error = firmware_read(fwh, 0, ucode, size); - firmware_close(fwh); - if (error != 0) { - printf("%s: failed to read firmware (error %d)\n", - DEVNAME(sc), error); - firmware_free(ucode, size); + ucode = bwfm_firmware_data(&fwctx, BWFM_FILETYPE_UCODE, + &ucsize); + KASSERT(ucode != NULL); + + if (bwfm_usb_load_microcode(sc, ucode, ucsize) != 0) { + aprint_error_dev(bwfm->sc_dev, + "could not load microcode\n"); + bwfm_firmware_close(&fwctx); return; } - if (bwfm_usb_load_microcode(sc, ucode, size) != 0) { - printf("%s: could not load microcode\n", - DEVNAME(sc)); - return; - } - - firmware_free(ucode, size); + bwfm_firmware_close(&fwctx); for (i = 0; i < 10; i++) { delay(100 * 1000); @@ -409,14 +397,13 @@ bwfm_usb_attachhook(device_t self) } if (le32toh(brom.chip) != BRCMF_POSTBOOT_ID) { - printf("%s: firmware did not start up\n", - DEVNAME(sc)); + aprint_error_dev(bwfm->sc_dev, + "firmware did not start up\n"); return; } sc->sc_chip = le32toh(brom.chip); sc->sc_chiprev = le32toh(brom.chiprev); - printf("%s: firmware loaded\n", DEVNAME(sc)); } bwfm_usb_dl_cmd(sc, DL_RESETCFG, &brom, sizeof(brom)); @@ -436,8 +423,9 @@ bwfm_usb_attachhook(device_t self) bwfm_usb_rxeof); error = usbd_transfer(data->xfer); if (error != 0 && error != USBD_IN_PROGRESS) - printf("%s: could not set up new transfer: %s\n", - DEVNAME(sc), usbd_errstr(error)); + aprint_error_dev(bwfm->sc_dev, + "could not set up new transfer: %s\n", + usbd_errstr(error)); } }