summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2020-05-15 14:09:15 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2020-05-15 14:09:15 +0000
commit4784011b1e948f83361f2ad8d5a5eac50ecb32a5 (patch)
tree22a2a8ed760ed8d719ab13eac907f70e54784313 /sys
parent1d4dcc75c6c88f9d2b6578ff786009da0467bf42 (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.c49
-rw-r--r--sys/dev/ic/bwfmreg.h16
-rw-r--r--sys/dev/ic/bwfmvar.h5
-rw-r--r--sys/dev/sdmmc/if_bwfm_sdio.c13
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) {