diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2020-05-15 14:09:15 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2020-05-15 14:09:15 +0000 |
commit | 4784011b1e948f83361f2ad8d5a5eac50ecb32a5 (patch) | |
tree | 22a2a8ed760ed8d719ab13eac907f70e54784313 /sys | |
parent | 1d4dcc75c6c88f9d2b6578ff786009da0467bf42 (diff) |
Some newer bwfm(4) chips from Cypress hold their regulatory
constraints in a separate blob, instead of in the firmware.
This .clm_blob needs to be loaded as well.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ic/bwfm.c | 49 | ||||
-rw-r--r-- | sys/dev/ic/bwfmreg.h | 16 | ||||
-rw-r--r-- | sys/dev/ic/bwfmvar.h | 5 | ||||
-rw-r--r-- | sys/dev/sdmmc/if_bwfm_sdio.c | 13 |
4 files changed, 79 insertions, 4 deletions
diff --git a/sys/dev/ic/bwfm.c b/sys/dev/ic/bwfm.c index a8b0ca0becd..93564fa3482 100644 --- a/sys/dev/ic/bwfm.c +++ b/sys/dev/ic/bwfm.c @@ -1,4 +1,4 @@ -/* $OpenBSD: bwfm.c,v 1.70 2020/03/06 08:41:57 patrick Exp $ */ +/* $OpenBSD: bwfm.c,v 1.71 2020/05/15 14:09:14 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> @@ -64,6 +64,8 @@ void bwfm_update_nodes(struct bwfm_softc *); int bwfm_ioctl(struct ifnet *, u_long, caddr_t); int bwfm_media_change(struct ifnet *); +void bwfm_process_clm_blob(struct bwfm_softc *); + int bwfm_chip_attach(struct bwfm_softc *); int bwfm_chip_detach(struct bwfm_softc *, int); struct bwfm_core *bwfm_chip_get_core(struct bwfm_softc *, int); @@ -255,6 +257,8 @@ bwfm_preinit(struct bwfm_softc *sc) printf("%s: address %s\n", DEVNAME(sc), ether_sprintf(ic->ic_myaddr)); + bwfm_process_clm_blob(sc); + if (bwfm_fwvar_var_get_int(sc, "nmode", &nmode)) nmode = 0; if (bwfm_fwvar_var_get_int(sc, "vhtmode", &vhtmode)) @@ -2749,3 +2753,46 @@ bwfm_nvram_convert(u_char *buf, size_t len, size_t *newlenp) *newlenp = count; return 0; } + +void +bwfm_process_clm_blob(struct bwfm_softc *sc) +{ + struct bwfm_dload_data *data; + size_t off, remain, len; + + if (sc->sc_clm == NULL || sc->sc_clmsize == 0) + return; + + off = 0; + remain = sc->sc_clmsize; + data = malloc(sizeof(*data) + BWFM_DLOAD_MAX_LEN, M_TEMP, M_WAITOK); + + while (remain) { + len = min(remain, BWFM_DLOAD_MAX_LEN); + + data->flag = htole16(BWFM_DLOAD_FLAG_HANDLER_VER_1); + if (off == 0) + data->flag |= htole16(BWFM_DLOAD_FLAG_BEGIN); + if (remain < BWFM_DLOAD_MAX_LEN) + data->flag |= htole16(BWFM_DLOAD_FLAG_END); + data->type = htole16(BWFM_DLOAD_TYPE_CLM); + data->len = htole32(len); + data->crc = 0; + memcpy(data->data, sc->sc_clm + off, len); + + if (bwfm_fwvar_var_set_data(sc, "clmload", data, + sizeof(*data) + len)) { + printf("%s: could not load CLM blob\n", DEVNAME(sc)); + goto out; + } + + off += len; + remain -= len; + } + +out: + free(data, M_TEMP, sizeof(*data) + BWFM_DLOAD_MAX_LEN); + free(sc->sc_clm, M_DEVBUF, sc->sc_clmsize); + sc->sc_clm = NULL; + sc->sc_clmsize = 0; +} diff --git a/sys/dev/ic/bwfmreg.h b/sys/dev/ic/bwfmreg.h index 0824ad1fd0b..04fcd752b93 100644 --- a/sys/dev/ic/bwfmreg.h +++ b/sys/dev/ic/bwfmreg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bwfmreg.h,v 1.18 2019/11/09 20:53:55 patrick Exp $ */ +/* $OpenBSD: bwfmreg.h,v 1.19 2020/05/15 14:09:14 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> @@ -752,3 +752,17 @@ struct bwfm_event { struct bwfm_ethhdr hdr; struct bwfm_event_msg msg; } __packed; + +struct bwfm_dload_data { + uint16_t flag; +#define BWFM_DLOAD_FLAG_BEGIN (1 << 1) +#define BWFM_DLOAD_FLAG_END (1 << 2) +#define BWFM_DLOAD_FLAG_HANDLER_VER_1 (1 << 12) +#define BWFM_DLOAD_FLAG_HANDLER_VER_MASK (0xf << 12) + uint16_t type; +#define BWFM_DLOAD_TYPE_CLM 2 + uint32_t len; +#define BWFM_DLOAD_MAX_LEN 1400 + uint32_t crc; + uint8_t data[]; +} __packed; diff --git a/sys/dev/ic/bwfmvar.h b/sys/dev/ic/bwfmvar.h index a5d567203bc..7c0ccfcdc11 100644 --- a/sys/dev/ic/bwfmvar.h +++ b/sys/dev/ic/bwfmvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: bwfmvar.h,v 1.19 2020/03/13 15:30:58 patrick Exp $ */ +/* $OpenBSD: bwfmvar.h,v 1.20 2020/05/15 14:09:14 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> @@ -169,6 +169,9 @@ struct bwfm_softc { int sc_bcdc_reqid; TAILQ_HEAD(, bwfm_proto_bcdc_ctl) sc_bcdc_rxctlq; + + u_char *sc_clm; + size_t sc_clmsize; }; void bwfm_attach(struct bwfm_softc *); diff --git a/sys/dev/sdmmc/if_bwfm_sdio.c b/sys/dev/sdmmc/if_bwfm_sdio.c index b8b6ae4b94c..7b1e534017e 100644 --- a/sys/dev/sdmmc/if_bwfm_sdio.c +++ b/sys/dev/sdmmc/if_bwfm_sdio.c @@ -1,4 +1,4 @@ -/* $OpenBSD: if_bwfm_sdio.c,v 1.36 2020/04/19 21:40:21 stsp Exp $ */ +/* $OpenBSD: if_bwfm_sdio.c,v 1.37 2020/05/15 14:09:14 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation * Copyright (c) 2016,2017 Patrick Wildt <patrick@blueri.se> @@ -489,6 +489,17 @@ bwfm_sdio_preinit(struct bwfm_softc *bwfm) goto err; } + if (sysname != NULL) { + r = snprintf(name, sizeof(name), "brcmfmac%s-sdio.%s.clm_blob", + chip, sysname); + if (r > 0 && r < sizeof(name)) + loadfirmware(name, &bwfm->sc_clm, &bwfm->sc_clmsize); + } + if (bwfm->sc_clmsize == 0) { + snprintf(name, sizeof(name), "brcmfmac%s-sdio.clm_blob", chip); + loadfirmware(name, &bwfm->sc_clm, &bwfm->sc_clmsize); + } + sc->sc_alp_only = 1; if (bwfm_sdio_load_microcode(sc, ucode, size, nvram, nvlen) != 0) { |