Module Name: src
Committed By: mlelstv
Date: Mon Oct 28 06:37:52 UTC 2019
Modified Files:
src/sys/dev/ic: bwfm.c bwfmreg.h bwfmvar.h
src/sys/dev/sdmmc: if_bwfm_sdio.c
Log Message:
More code from OpenBSD
no need to splnet() when enqueing packets
explicit structure padding
make internal functions static
also prepare for GPIO interrupts.
To generate a diff of this commit:
cvs rdiff -u -r1.17 -r1.18 src/sys/dev/ic/bwfm.c
cvs rdiff -u -r1.5 -r1.6 src/sys/dev/ic/bwfmreg.h
cvs rdiff -u -r1.4 -r1.5 src/sys/dev/ic/bwfmvar.h
cvs rdiff -u -r1.8 -r1.9 src/sys/dev/sdmmc/if_bwfm_sdio.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.17 src/sys/dev/ic/bwfm.c:1.18
--- src/sys/dev/ic/bwfm.c:1.17 Thu Oct 3 14:42:20 2019
+++ src/sys/dev/ic/bwfm.c Mon Oct 28 06:37:51 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: bwfm.c,v 1.17 2019/10/03 14:42:20 jmcneill Exp $ */
+/* $NetBSD: bwfm.c,v 1.18 2019/10/28 06:37:51 mlelstv Exp $ */
/* $OpenBSD: bwfm.c,v 1.5 2017/10/16 22:27:16 patrick Exp $ */
/*
* Copyright (c) 2010-2016 Broadcom Corporation
@@ -345,6 +345,7 @@ bwfm_init(struct ifnet *ifp)
struct ieee80211com *ic = &sc->sc_ic;
uint8_t evmask[BWFM_EVENT_MASK_LEN];
struct bwfm_join_pref_params join_pref[2];
+ int pm;
if (bwfm_fwvar_var_set_int(sc, "mpc", 1)) {
printf("%s: could not set mpc\n", DEVNAME(sc));
@@ -370,10 +371,31 @@ bwfm_init(struct ifnet *ifp)
#define ENABLE_EVENT(e) evmask[(e) / 8] |= 1 << ((e) % 8)
/* Events used to drive the state machine */
- ENABLE_EVENT(BWFM_E_ASSOC);
- ENABLE_EVENT(BWFM_E_ESCAN_RESULT);
- ENABLE_EVENT(BWFM_E_SET_SSID);
- ENABLE_EVENT(BWFM_E_LINK);
+ switch (ic->ic_opmode) {
+ case IEEE80211_M_STA:
+ ENABLE_EVENT(BWFM_E_IF);
+ ENABLE_EVENT(BWFM_E_LINK);
+ ENABLE_EVENT(BWFM_E_AUTH);
+ ENABLE_EVENT(BWFM_E_ASSOC);
+ ENABLE_EVENT(BWFM_E_DEAUTH);
+ ENABLE_EVENT(BWFM_E_DISASSOC);
+ ENABLE_EVENT(BWFM_E_SET_SSID);
+ ENABLE_EVENT(BWFM_E_ESCAN_RESULT);
+ break;
+#ifndef IEEE80211_STA_ONLY
+ case IEEE80211_M_HOSTAP:
+ ENABLE_EVENT(BWFM_E_AUTH_IND);
+ ENABLE_EVENT(BWFM_E_ASSOC_IND);
+ ENABLE_EVENT(BWFM_E_REASSOC_IND);
+ ENABLE_EVENT(BWFM_E_DEAUTH_IND);
+ ENABLE_EVENT(BWFM_E_DISASSOC_IND);
+ ENABLE_EVENT(BWFM_E_ESCAN_RESULT);
+ ENABLE_EVENT(BWFM_E_ESCAN_RESULT);
+ break;
+#endif
+ default:
+ break;
+ }
#undef ENABLE_EVENT
#ifdef BWFM_DEBUG
@@ -401,7 +423,16 @@ bwfm_init(struct ifnet *ifp)
return EIO;
}
- if (bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_PM, 2)) {
+ /*
+ * Use CAM (constantly awake) when we are running as AP
+ * otherwise use fast power saving.
+ */
+ pm = BWFM_PM_FAST_PS;
+#ifndef IEEE80211_STA_ONLY
+ if (ic->ic_opmode == IEEE80211_M_HOSTAP)
+ pm = BWFM_PM_CAM;
+#endif
+ if (bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_PM, pm)) {
printf("%s: could not set power\n", DEVNAME(sc));
return EIO;
}
@@ -448,15 +479,25 @@ bwfm_stop(struct ifnet *ifp, int disable
{
struct bwfm_softc *sc = ifp->if_softc;
struct ieee80211com *ic = &sc->sc_ic;
+ struct bwfm_join_params join;
sc->sc_tx_timer = 0;
ifp->if_timer = 0;
ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE);
+ memset(&join, 0, sizeof(join));
+ bwfm_fwvar_cmd_set_data(sc, BWFM_C_SET_SSID, &join, sizeof(join));
bwfm_fwvar_cmd_set_int(sc, BWFM_C_DOWN, 1);
bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_PM, 0);
+ bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_AP, 0);
+ bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_INFRA, 0);
+ bwfm_fwvar_cmd_set_int(sc, BWFM_C_UP, 1);
+ bwfm_fwvar_cmd_set_int(sc, BWFM_C_SET_PM, BWFM_PM_FAST_PS);
ieee80211_new_state(ic, IEEE80211_S_INIT, -1);
+
+ if (sc->sc_bus_ops->bs_stop)
+ sc->sc_bus_ops->bs_stop(sc);
}
void
@@ -606,7 +647,7 @@ bwfm_key_set_cb(struct bwfm_softc *sc, s
wsec_key.len = htole32(wk->wk_keylen);
memcpy(wsec_key.data, wk->wk_key, sizeof(wsec_key.data));
if (!ext_key)
- wsec_key.flags = htole32(BWFM_PRIMARY_KEY);
+ wsec_key.flags = htole32(BWFM_WSEC_PRIMARY_KEY);
switch (wk->wk_cipher->ic_cipher) {
case IEEE80211_CIPHER_WEP:
@@ -670,7 +711,7 @@ bwfm_key_delete_cb(struct bwfm_softc *sc
memset(&wsec_key, 0, sizeof(wsec_key));
wsec_key.index = htole32(wk->wk_keyix);
- wsec_key.flags = htole32(BWFM_PRIMARY_KEY);
+ wsec_key.flags = htole32(BWFM_WSEC_PRIMARY_KEY);
if (bwfm_fwvar_var_set_data(sc, "wsec_key", &wsec_key, sizeof(wsec_key)))
return;
@@ -1452,10 +1493,10 @@ bwfm_proto_bcdc_query_dcmd(struct bwfm_s
{
struct bwfm_proto_bcdc_dcmd *dcmd;
size_t size = sizeof(dcmd->hdr) + *len;
- static int reqid = 0;
+ int reqid;
int ret = 1;
- reqid++;
+ reqid = sc->sc_bcdc_reqid++;
dcmd = kmem_zalloc(sizeof(*dcmd), KM_SLEEP);
if (*len > sizeof(dcmd->buf))
@@ -1512,10 +1553,9 @@ bwfm_proto_bcdc_set_dcmd(struct bwfm_sof
{
struct bwfm_proto_bcdc_dcmd *dcmd;
size_t size = sizeof(dcmd->hdr) + len;
- int reqid = 0;
- int ret = 1;
+ int ret = 1, reqid;
- reqid++;
+ reqid = sc->sc_bcdc_reqid++;
dcmd = kmem_zalloc(sizeof(*dcmd), KM_SLEEP);
if (len > sizeof(dcmd->buf))
@@ -1845,7 +1885,6 @@ bwfm_rx(struct bwfm_softc *sc, struct mb
struct ieee80211com *ic = &sc->sc_ic;
struct ifnet *ifp = ic->ic_ifp;
struct bwfm_event *e = mtod(m, struct bwfm_event *);
- int s;
if (m->m_len >= sizeof(e->ehdr) &&
ntohs(e->ehdr.ether_type) == BWFM_ETHERTYPE_LINK_CTL &&
@@ -1856,14 +1895,8 @@ bwfm_rx(struct bwfm_softc *sc, struct mb
return;
}
- s = splnet();
-
- //if ((ifp->if_flags & IFF_RUNNING) != 0) {
- m_set_rcvif(m, ifp);
- if_percpuq_enqueue(ifp->if_percpuq, m);
- //}
-
- splx(s);
+ m_set_rcvif(m, ifp);
+ if_percpuq_enqueue(ifp->if_percpuq, m);
}
void
Index: src/sys/dev/ic/bwfmreg.h
diff -u src/sys/dev/ic/bwfmreg.h:1.5 src/sys/dev/ic/bwfmreg.h:1.6
--- src/sys/dev/ic/bwfmreg.h:1.5 Thu Oct 3 14:42:20 2019
+++ src/sys/dev/ic/bwfmreg.h Mon Oct 28 06:37:51 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: bwfmreg.h,v 1.5 2019/10/03 14:42:20 jmcneill Exp $ */
+/* $NetBSD: bwfmreg.h,v 1.6 2019/10/28 06:37:51 mlelstv Exp $ */
/* $OpenBSD: bwfmreg.h,v 1.16 2018/02/07 21:44:09 patrick Exp $ */
/*
* Copyright (c) 2010-2016 Broadcom Corporation
@@ -372,21 +372,26 @@ struct bwfm_bss_info {
uint16_t capability;
uint8_t ssid_len;
uint8_t ssid[BWFM_MAX_SSID_LEN];
+ uint8_t pad0;
uint32_t nrates;
uint8_t rates[16];
uint16_t chanspec;
uint16_t atim_window;
uint8_t dtim_period;
+ uint8_t pad1;
uint16_t rssi;
uint8_t phy_noise;
uint8_t n_cap;
+ uint16_t pad2;
uint32_t nbss_cap;
uint8_t ctl_ch;
+ uint8_t pad3[3];
uint32_t reserved32[1];
uint8_t flags;
uint8_t reserved[3];
uint8_t basic_mcs[BWFM_MCSSET_LEN];
uint16_t ie_offset;
+ uint16_t pad4;
uint32_t ie_length;
uint16_t snr;
};
@@ -572,6 +577,7 @@ struct bwfm_escan_results {
struct bwfm_assoc_params {
uint8_t bssid[ETHER_ADDR_LEN];
+ uint16_t pad;
uint32_t chanspec_num;
uint16_t chanspec_list[];
};
@@ -599,6 +605,7 @@ struct bwfm_join_params {
struct bwfm_join_scan_params {
uint8_t scan_type;
+ uint8_t pad[3];
uint32_t nprobes;
uint32_t active_time;
uint32_t passive_time;
@@ -633,15 +640,18 @@ struct bwfm_wsec_key {
#define BWFM_CRYPTO_ALGO_AES_RESERVED1 5
#define BWFM_CRYPTO_ALGO_AES_RESERVED2 6
uint32_t flags;
-#define BWFM_PRIMARY_KEY (1 << 1)
+#define BWFM_WSEC_PRIMARY_KEY (1 << 1)
+#define BWFM_PRIMARY_KEY BWFM_WSEC_PRIMARY_KEY
uint32_t pad_2[3];
uint32_t iv_initialized;
uint32_t pad_3;
+ /* Rx IV */
struct {
uint32_t hi;
uint16_t lo;
+ uint16_t pad_4;
} rxiv;
- uint32_t pad_4[2];
+ uint32_t pad_5[2];
uint8_t ea[IEEE80211_ADDR_LEN];
};
@@ -753,7 +763,7 @@ struct bwfm_ethhdr {
#define BWFM_BRCM_OUI "\x00\x10\x18"
uint16_t usr_subtype;
#define BWFM_BRCM_SUBTYPE_EVENT 1
-};
+} __packed;
struct bwfm_event_msg {
uint16_t version;
@@ -767,7 +777,7 @@ struct bwfm_event_msg {
char ifname[IFNAMSIZ];
uint8_t ifidx;
uint8_t bsscfgidx;
-};
+} __packed;
struct bwfm_event {
struct ether_header ehdr;
@@ -775,4 +785,3 @@ struct bwfm_event {
struct bwfm_ethhdr hdr;
struct bwfm_event_msg msg;
} __packed;
-
Index: src/sys/dev/ic/bwfmvar.h
diff -u src/sys/dev/ic/bwfmvar.h:1.4 src/sys/dev/ic/bwfmvar.h:1.5
--- src/sys/dev/ic/bwfmvar.h:1.4 Sun Sep 1 05:40:39 2019
+++ src/sys/dev/ic/bwfmvar.h Mon Oct 28 06:37:51 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: bwfmvar.h,v 1.4 2019/09/01 05:40:39 mlelstv Exp $ */
+/* $NetBSD: bwfmvar.h,v 1.5 2019/10/28 06:37:51 mlelstv Exp $ */
/* $OpenBSD: bwfmvar.h,v 1.1 2017/10/11 17:19:50 patrick Exp $ */
/*
* Copyright (c) 2010-2016 Broadcom Corporation
@@ -169,6 +169,8 @@ struct bwfm_softc {
int (*sc_newstate)(struct ieee80211com *,
enum ieee80211_state, int);
+
+ int sc_bcdc_reqid;
};
void bwfm_attach(struct bwfm_softc *);
Index: src/sys/dev/sdmmc/if_bwfm_sdio.c
diff -u src/sys/dev/sdmmc/if_bwfm_sdio.c:1.8 src/sys/dev/sdmmc/if_bwfm_sdio.c:1.9
--- src/sys/dev/sdmmc/if_bwfm_sdio.c:1.8 Mon Oct 28 06:20:01 2019
+++ src/sys/dev/sdmmc/if_bwfm_sdio.c Mon Oct 28 06:37:52 2019
@@ -1,4 +1,4 @@
-/* $NetBSD: if_bwfm_sdio.c,v 1.8 2019/10/28 06:20:01 mlelstv Exp $ */
+/* $NetBSD: if_bwfm_sdio.c,v 1.9 2019/10/28 06:37:52 mlelstv Exp $ */
/* $OpenBSD: if_bwfm_sdio.c,v 1.1 2017/10/11 17:19:50 patrick Exp $ */
/*
* Copyright (c) 2010-2016 Broadcom Corporation
@@ -36,6 +36,9 @@
#include <netinet/in.h>
+#include <dev/ofw/openfirm.h>
+#include <dev/fdt/fdtvar.h>
+
#include <dev/firmload.h>
#include <net80211/ieee80211_var.h>
@@ -80,6 +83,7 @@ struct bwfm_sdio_softc {
bool sc_sr_enabled;
bool sc_alp_only;
bool sc_sleeping;
+ bool sc_rxskip;
struct sdmmc_task sc_task;
bool sc_task_queued;
@@ -102,78 +106,86 @@ struct bwfm_sdio_softc {
char *sc_console_buf;
size_t sc_console_buf_size;
uint32_t sc_console_readidx;
+
+ int sc_phandle;
+ void *sc_fdtih;
};
-int bwfm_sdio_match(device_t, cfdata_t, void *);
-void bwfm_sdio_attach(device_t, struct device *, void *);
-int bwfm_sdio_detach(device_t, int);
-void bwfm_sdio_attachhook(device_t);
-
-void bwfm_sdio_backplane(struct bwfm_sdio_softc *, uint32_t);
-uint8_t bwfm_sdio_read_1(struct bwfm_sdio_softc *, uint32_t);
-uint32_t bwfm_sdio_read_4(struct bwfm_sdio_softc *, uint32_t);
-void bwfm_sdio_write_1(struct bwfm_sdio_softc *, uint32_t,
+static int bwfm_sdio_match(device_t, cfdata_t, void *);
+static void bwfm_sdio_attach(device_t, device_t, void *);
+static int bwfm_sdio_detach(device_t, int);
+static void bwfm_sdio_attachhook(device_t);
+static int bwfm_fdt_find_phandle(device_t, device_t);
+
+static void bwfm_sdio_backplane(struct bwfm_sdio_softc *, uint32_t);
+static uint8_t bwfm_sdio_read_1(struct bwfm_sdio_softc *, uint32_t);
+static uint32_t bwfm_sdio_read_4(struct bwfm_sdio_softc *, uint32_t);
+static void bwfm_sdio_write_1(struct bwfm_sdio_softc *, uint32_t,
uint8_t);
-void bwfm_sdio_write_4(struct bwfm_sdio_softc *, uint32_t,
+static void bwfm_sdio_write_4(struct bwfm_sdio_softc *, uint32_t,
uint32_t);
-uint32_t bwfm_sdio_dev_read(struct bwfm_sdio_softc *, uint32_t);
-void bwfm_sdio_dev_write(struct bwfm_sdio_softc *, uint32_t,
+static uint32_t bwfm_sdio_dev_read(struct bwfm_sdio_softc *, uint32_t);
+static void bwfm_sdio_dev_write(struct bwfm_sdio_softc *, uint32_t,
uint32_t);
-uint32_t bwfm_sdio_buscore_read(struct bwfm_softc *, uint32_t);
-void bwfm_sdio_buscore_write(struct bwfm_softc *, uint32_t,
+static uint32_t bwfm_sdio_buscore_read(struct bwfm_softc *, uint32_t);
+static void bwfm_sdio_buscore_write(struct bwfm_softc *, uint32_t,
uint32_t);
-int bwfm_sdio_buscore_prepare(struct bwfm_softc *);
-void bwfm_sdio_buscore_activate(struct bwfm_softc *, uint32_t);
+static int bwfm_sdio_buscore_prepare(struct bwfm_softc *);
+static void bwfm_sdio_buscore_activate(struct bwfm_softc *, uint32_t);
-int bwfm_sdio_buf_read(struct bwfm_sdio_softc *,
+static int bwfm_sdio_buf_read(struct bwfm_sdio_softc *,
struct sdmmc_function *, uint32_t, char *, size_t);
-int bwfm_sdio_buf_write(struct bwfm_sdio_softc *,
+static int bwfm_sdio_buf_write(struct bwfm_sdio_softc *,
struct sdmmc_function *, uint32_t, char *, size_t);
-struct mbuf *bwfm_sdio_newbuf(void);
-void bwfm_qput(struct mbuf **, struct mbuf *);
-struct mbuf *bwfm_qget(struct mbuf **);
+static struct mbuf *bwfm_sdio_newbuf(void);
+static void bwfm_qput(struct mbuf **, struct mbuf *);
+static struct mbuf *bwfm_qget(struct mbuf **);
-uint32_t bwfm_sdio_ram_read_write(struct bwfm_sdio_softc *,
+static uint32_t bwfm_sdio_ram_read_write(struct bwfm_sdio_softc *,
uint32_t, char *, size_t, int);
-uint32_t bwfm_sdio_frame_read_write(struct bwfm_sdio_softc *,
+static uint32_t bwfm_sdio_frame_read_write(struct bwfm_sdio_softc *,
char *, size_t, int);
-int bwfm_sdio_intr(void *);
-void bwfm_sdio_task(void *);
-void bwfm_sdio_task1(struct bwfm_sdio_softc *);
+static int bwfm_sdio_intr1(void *, const char *);
+static int bwfm_sdio_intr(void *);
+static void bwfm_sdio_task(void *);
+static void bwfm_sdio_task1(struct bwfm_sdio_softc *);
-int bwfm_nvram_convert(u_char *, size_t, size_t *);
-int bwfm_sdio_load_microcode(struct bwfm_sdio_softc *,
+static int bwfm_nvram_convert(u_char *, size_t, size_t *);
+static int bwfm_sdio_load_microcode(struct bwfm_sdio_softc *,
u_char *, size_t, u_char *, size_t);
-void bwfm_sdio_clkctl(struct bwfm_sdio_softc *,
+static void bwfm_sdio_clkctl(struct bwfm_sdio_softc *,
enum bwfm_sdio_clkstate, bool);
-void bwfm_sdio_htclk(struct bwfm_sdio_softc *, bool, bool);
+static void bwfm_sdio_htclk(struct bwfm_sdio_softc *, bool, bool);
-int bwfm_sdio_bus_sleep(struct bwfm_sdio_softc *, bool, bool);
-void bwfm_sdio_readshared(struct bwfm_sdio_softc *);
+#ifdef notyet
+static int bwfm_sdio_bus_sleep(struct bwfm_sdio_softc *, bool, bool);
+#endif
+static void bwfm_sdio_drivestrength(struct bwfm_sdio_softc *, unsigned);
+static void bwfm_sdio_readshared(struct bwfm_sdio_softc *);
-int bwfm_sdio_txcheck(struct bwfm_softc *);
-int bwfm_sdio_txdata(struct bwfm_softc *, struct mbuf **);
-int bwfm_sdio_txctl(struct bwfm_softc *, char *, size_t);
-int bwfm_sdio_rxctl(struct bwfm_softc *, char *, size_t *);
-
-int bwfm_sdio_tx_ok(struct bwfm_sdio_softc *);
-void bwfm_sdio_tx_frames(struct bwfm_sdio_softc *);
-void bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *,
+static int bwfm_sdio_txcheck(struct bwfm_softc *);
+static int bwfm_sdio_txdata(struct bwfm_softc *, struct mbuf **);
+static int bwfm_sdio_txctl(struct bwfm_softc *, char *, size_t);
+static int bwfm_sdio_rxctl(struct bwfm_softc *, char *, size_t *);
+
+static int bwfm_sdio_tx_ok(struct bwfm_sdio_softc *);
+static void bwfm_sdio_tx_frames(struct bwfm_sdio_softc *);
+static void bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *,
struct mbuf *);
-void bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *,
+static void bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *,
struct mbuf *);
-void bwfm_sdio_rx_frames(struct bwfm_sdio_softc *);
-void bwfm_sdio_rx_glom(struct bwfm_sdio_softc *,
+static void bwfm_sdio_rx_frames(struct bwfm_sdio_softc *);
+static void bwfm_sdio_rx_glom(struct bwfm_sdio_softc *,
uint16_t *, int, uint16_t *);
-#ifdef BWFM_DEBUG
-void bwfm_sdio_debug_console(struct bwfm_sdio_softc *);
-#endif
+#ifdef BWFM_DEBUG
+static void bwfm_sdio_debug_console(struct bwfm_sdio_softc *);
+#endif
struct bwfm_bus_ops bwfm_sdio_bus_ops = {
.bs_init = NULL,
@@ -203,27 +215,32 @@ static const struct bwfm_sdio_product {
} bwfm_sdio_products[] = {
{
SDMMC_VENDOR_BROADCOM,
- SDMMC_PRODUCT_BROADCOM_BCM4330,
+ SDMMC_PRODUCT_BROADCOM_BCM4330,
SDMMC_CIS_BROADCOM_BCM4330
},
{
SDMMC_VENDOR_BROADCOM,
- SDMMC_PRODUCT_BROADCOM_BCM4334,
+ SDMMC_PRODUCT_BROADCOM_BCM4334,
SDMMC_CIS_BROADCOM_BCM4334
},
{
SDMMC_VENDOR_BROADCOM,
- SDMMC_PRODUCT_BROADCOM_BCM43143,
+ SDMMC_PRODUCT_BROADCOM_BCM43143,
SDMMC_CIS_BROADCOM_BCM43143
},
{
SDMMC_VENDOR_BROADCOM,
- SDMMC_PRODUCT_BROADCOM_BCM43430,
+ SDMMC_PRODUCT_BROADCOM_BCM43430,
SDMMC_CIS_BROADCOM_BCM43430
},
};
-int
+static const char *compatible[] = {
+ "brcm,bcm4329-fmac",
+ NULL
+};
+
+static int
bwfm_sdio_match(device_t parent, cfdata_t match, void *aux)
{
struct sdmmc_attach_args *saa = aux;
@@ -257,7 +274,7 @@ bwfm_sdio_match(device_t parent, cfdata_
return 1;
}
-void
+static void
bwfm_sdio_attach(device_t parent, device_t self, void *aux)
{
struct bwfm_sdio_softc *sc = device_private(self);
@@ -271,6 +288,8 @@ bwfm_sdio_attach(device_t parent, device
aprint_naive("\n");
aprint_normal("\n");
+ sc->sc_phandle = bwfm_fdt_find_phandle(self, parent);
+
mutex_init(&sc->sc_lock, MUTEX_DEFAULT, IPL_NONE);
cv_init(&sc->sc_rxctl_cv, "bwfmctl");
mutex_init(&sc->sc_intr_lock, MUTEX_DEFAULT, IPL_NONE);
@@ -293,7 +312,7 @@ bwfm_sdio_attach(device_t parent, device
sc->sc_sf[sf->number] = sf;
}
- sdmmc_io_set_blocklen(sc->sc_sf[1], 64);
+ sdmmc_io_set_blocklen(sc->sc_sf[1], 64);
sdmmc_io_set_blocklen(sc->sc_sf[2], 512);
/* Enable Function 1. */
@@ -331,7 +350,8 @@ bwfm_sdio_attach(device_t parent, device
}
}
- /* TODO: drive strength */
+ /* Default, override from "brcm,drive-strength" */
+ bwfm_sdio_drivestrength(sc, 6);
bwfm_sdio_write_1(sc, BWFM_SDIO_CCCR_CARDCTRL,
bwfm_sdio_read_1(sc, BWFM_SDIO_CCCR_CARDCTRL) |
@@ -351,7 +371,7 @@ bwfm_sdio_attach(device_t parent, device
config_mountroot(self, bwfm_sdio_attachhook);
}
-void
+static void
bwfm_sdio_attachhook(device_t self)
{
struct bwfm_sdio_softc *sc = device_private(self);
@@ -389,6 +409,7 @@ bwfm_sdio_attachhook(device_t self)
} 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:
@@ -472,6 +493,8 @@ bwfm_sdio_attachhook(device_t self)
firmware_free(nvram, nvlen);
firmware_free(ucode, size);
+ 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",
@@ -490,8 +513,9 @@ bwfm_sdio_attachhook(device_t self)
goto err;
}
- bwfm_sdio_dev_write(sc, SDPCMD_HOSTINTMASK,
- SDPCMD_INTSTATUS_HMB_SW_MASK | SDPCMD_INTSTATUS_CHIPACTIVE);
+// bwfm_sdio_dev_write(sc, SDPCMD_HOSTINTMASK,
+// SDPCMD_INTSTATUS_HMB_SW_MASK | SDPCMD_INTSTATUS_CHIPACTIVE);
+ bwfm_sdio_dev_write(sc, SDPCMD_HOSTINTMASK, 0xffffffff);
bwfm_sdio_write_1(sc, BWFM_SDIO_WATERMARK, 8);
if (bwfm_chip_sr_capable(bwfm)) {
@@ -508,15 +532,28 @@ bwfm_sdio_attachhook(device_t self)
bwfm_sdio_write_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR, clk);
}
- sc->sc_ih = sdmmc_intr_establish(sc->sc_sc.sc_dev->dv_parent,
- bwfm_sdio_intr, sc, DEVNAME(sc));
- if (sc->sc_ih == NULL) {
+#ifdef notyet
+ if (sc->sc_phandle >= 0) {
+ sc->sc_fdtih = fdtbus_intr_establish(sc->sc_phandle,
+ 0, IPL_SDMMC, IST_LEVEL, bwfm_sdio_intr, sc);
+ }
+#endif
+ if (sc->sc_fdtih != NULL) {
+ aprint_normal_dev(self, "enabling GPIO interrupt\n");
+ } else {
+ sc->sc_ih = sdmmc_intr_establish(device_parent(self),
+ bwfm_sdio_intr, sc, DEVNAME(sc));
+ }
+
+ if (sc->sc_ih == NULL && sc->sc_fdtih == NULL) {
aprint_error_dev(self, "could not establish interrupt\n");
bwfm_sdio_clkctl(sc, CLK_NONE, false);
return;
}
sdmmc_intr_enable(sc->sc_sf[1]);
+ sdmmc_pause(100000, NULL);
+
sc->sc_sc.sc_bus_ops = &bwfm_sdio_bus_ops;
sc->sc_sc.sc_proto_ops = &bwfm_proto_bcdc_ops;
bwfm_attach(&sc->sc_sc);
@@ -532,8 +569,42 @@ err:
return;
}
-int
-bwfm_sdio_detach(struct device *self, int flags)
+static int
+bwfm_fdt_find_phandle(device_t self, device_t parent)
+{
+ prop_dictionary_t dict;
+ device_t dev;
+ const char *str;
+ int phandle;
+
+ /* locate in FDT */
+ dict = device_properties(self);
+ if (prop_dictionary_get_cstring_nocopy(dict, "fdt-path", &str)) {
+ /* search in FDT */
+ phandle = OF_finddevice(str);
+ } else {
+
+ /* parent parent is sdhc controller */
+ dev = device_parent(parent);
+ if (dev == NULL)
+ return -1;
+ /* locate in FDT */
+ dict = device_properties(dev);
+ if (!prop_dictionary_get_cstring_nocopy(dict, "fdt-path", &str))
+ return -1;
+
+ /* are we the only FDT child ? */
+ phandle = OF_child(OF_finddevice(str));
+ }
+
+ if (!of_match_compatible(phandle, compatible))
+ return -1;
+
+ return phandle;
+}
+
+static int
+bwfm_sdio_detach(device_t self, int flags)
{
struct bwfm_sdio_softc *sc = (struct bwfm_sdio_softc *)self;
@@ -541,9 +612,12 @@ bwfm_sdio_detach(struct device *self, in
bwfm_sdio_debug_console(sc);
#endif
- if (sc->sc_ih) {
+ if (sc->sc_ih || sc->sc_fdtih) {
sdmmc_intr_disable(sc->sc_sf[1]);
- sdmmc_intr_disestablish(sc->sc_ih);
+ if (sc->sc_ih)
+ sdmmc_intr_disestablish(sc->sc_ih);
+ if (sc->sc_fdtih)
+ fdtbus_intr_disestablish(sc->sc_phandle, sc->sc_fdtih);
}
if (sc->sc_bwfm_attached)
bwfm_detach(&sc->sc_sc, flags);
@@ -558,7 +632,7 @@ bwfm_sdio_detach(struct device *self, in
return 0;
}
-void
+static void
bwfm_sdio_backplane(struct bwfm_sdio_softc *sc, uint32_t addr)
{
uint32_t bar0 = addr & ~BWFM_SDIO_SB_OFT_ADDR_MASK;
@@ -575,7 +649,7 @@ bwfm_sdio_backplane(struct bwfm_sdio_sof
sc->sc_bar0 = bar0;
}
-uint8_t
+static uint8_t
bwfm_sdio_read_1(struct bwfm_sdio_softc *sc, uint32_t addr)
{
struct sdmmc_function *sf;
@@ -596,7 +670,7 @@ bwfm_sdio_read_1(struct bwfm_sdio_softc
return rv;
}
-uint32_t
+static uint32_t
bwfm_sdio_read_4(struct bwfm_sdio_softc *sc, uint32_t addr)
{
struct sdmmc_function *sf;
@@ -622,7 +696,7 @@ bwfm_sdio_read_4(struct bwfm_sdio_softc
return rv;
}
-void
+static void
bwfm_sdio_write_1(struct bwfm_sdio_softc *sc, uint32_t addr, uint8_t data)
{
struct sdmmc_function *sf;
@@ -641,7 +715,7 @@ bwfm_sdio_write_1(struct bwfm_sdio_softc
sdmmc_io_write_1(sf, addr, data);
}
-void
+static void
bwfm_sdio_write_4(struct bwfm_sdio_softc *sc, uint32_t addr, uint32_t data)
{
struct sdmmc_function *sf;
@@ -665,7 +739,7 @@ bwfm_sdio_write_4(struct bwfm_sdio_softc
sdmmc_io_write_4(sf, addr, data);
}
-int
+static int
bwfm_sdio_buf_read(struct bwfm_sdio_softc *sc, struct sdmmc_function *sf,
uint32_t reg, char *data, size_t size)
{
@@ -685,7 +759,7 @@ bwfm_sdio_buf_read(struct bwfm_sdio_soft
return err;
}
-int
+static int
bwfm_sdio_buf_write(struct bwfm_sdio_softc *sc, struct sdmmc_function *sf,
uint32_t reg, char *data, size_t size)
{
@@ -702,7 +776,7 @@ bwfm_sdio_buf_write(struct bwfm_sdio_sof
return err;
}
-uint32_t
+static uint32_t
bwfm_sdio_ram_read_write(struct bwfm_sdio_softc *sc, uint32_t reg,
char *data, size_t left, int write)
{
@@ -738,10 +812,13 @@ bwfm_sdio_ram_read_write(struct bwfm_sdi
left -= size;
}
+ if (err)
+ printf("%s: error %d\n", __func__, err);
+
return err;
}
-uint32_t
+static uint32_t
bwfm_sdio_frame_read_write(struct bwfm_sdio_softc *sc,
char *data, size_t size, int write)
{
@@ -759,10 +836,13 @@ bwfm_sdio_frame_read_write(struct bwfm_s
else
err = bwfm_sdio_buf_read(sc, sc->sc_sf[2], addr, data, size);
+ if (err)
+ printf("%s: error %d\n", __func__, err);
+
return err;
}
-uint32_t
+static uint32_t
bwfm_sdio_dev_read(struct bwfm_sdio_softc *sc, uint32_t reg)
{
struct bwfm_core *core;
@@ -775,7 +855,7 @@ bwfm_sdio_dev_read(struct bwfm_sdio_soft
return val;
}
-void
+static void
bwfm_sdio_dev_write(struct bwfm_sdio_softc *sc, uint32_t reg, uint32_t val)
{
struct bwfm_core *core;
@@ -784,7 +864,7 @@ bwfm_sdio_dev_write(struct bwfm_sdio_sof
bwfm_sdio_write_4(sc, core->co_base + reg, val);
}
-uint32_t
+static uint32_t
bwfm_sdio_buscore_read(struct bwfm_softc *bwfm, uint32_t reg)
{
struct bwfm_sdio_softc *sc = (void *)bwfm;
@@ -798,7 +878,7 @@ bwfm_sdio_buscore_read(struct bwfm_softc
return val;
}
-void
+static void
bwfm_sdio_buscore_write(struct bwfm_softc *bwfm, uint32_t reg, uint32_t val)
{
struct bwfm_sdio_softc *sc = (void *)bwfm;
@@ -808,7 +888,7 @@ bwfm_sdio_buscore_write(struct bwfm_soft
mutex_exit(&sc->sc_lock);
}
-int
+static int
bwfm_sdio_buscore_prepare(struct bwfm_softc *bwfm)
{
struct bwfm_sdio_softc *sc = (void *)bwfm;
@@ -858,7 +938,7 @@ done:
return error;
}
-void
+static void
bwfm_sdio_buscore_activate(struct bwfm_softc *bwfm, uint32_t rstvec)
{
struct bwfm_sdio_softc *sc = (void *)bwfm;
@@ -875,7 +955,7 @@ bwfm_sdio_buscore_activate(struct bwfm_s
mutex_exit(&sc->sc_lock);
}
-struct mbuf *
+static struct mbuf *
bwfm_sdio_newbuf(void)
{
struct mbuf *m;
@@ -894,7 +974,7 @@ bwfm_sdio_newbuf(void)
return m;
}
-struct mbuf *
+static struct mbuf *
bwfm_qget(struct mbuf **q)
{
struct mbuf *m = NULL;
@@ -908,7 +988,7 @@ bwfm_qget(struct mbuf **q)
return m;
}
-void
+static void
bwfm_qput(struct mbuf **q, struct mbuf *m)
{
@@ -918,7 +998,7 @@ bwfm_qput(struct mbuf **q, struct mbuf *
m_cat(*q, m);
}
-int
+static int
bwfm_sdio_txcheck(struct bwfm_softc *bwfm)
{
struct bwfm_sdio_softc *sc = (void *)bwfm;
@@ -933,7 +1013,7 @@ bwfm_sdio_txcheck(struct bwfm_softc *bwf
}
-int
+static int
bwfm_sdio_txdata(struct bwfm_softc *bwfm, struct mbuf **mp)
{
struct bwfm_sdio_softc *sc = (void *)bwfm;
@@ -948,12 +1028,12 @@ bwfm_sdio_txdata(struct bwfm_softc *bwfm
MBUFQ_ENQUEUE(&sc->sc_tx_queue, *mp);
mutex_exit(&sc->sc_lock);
- bwfm_sdio_intr(sc);
+ bwfm_sdio_intr1(sc, "sdio_txdata");
return 0;
}
-int
+static int
bwfm_sdio_txctl(struct bwfm_softc *bwfm, char *buf, size_t len)
{
struct bwfm_sdio_softc *sc = (void *)bwfm;
@@ -978,7 +1058,7 @@ bwfm_sdio_txctl(struct bwfm_softc *bwfm,
MBUFQ_ENQUEUE(&sc->sc_tx_queue, m);
mutex_exit(&sc->sc_lock);
- bwfm_sdio_intr(sc);
+ bwfm_sdio_intr1(sc, "sdio_txctl");
return 0;
@@ -986,7 +1066,7 @@ fail:
return ENOBUFS;
}
-int
+static int
bwfm_nvram_convert(u_char *buf, size_t len, size_t *newlenp)
{
u_char *src, *dst, *end = buf + len;
@@ -1036,7 +1116,7 @@ bwfm_nvram_convert(u_char *buf, size_t l
return 0;
}
-int
+static int
bwfm_sdio_load_microcode(struct bwfm_sdio_softc *sc, u_char *ucode, size_t size,
u_char *nvram, size_t nvlen)
{
@@ -1096,7 +1176,7 @@ out:
return err;
}
-void
+static void
bwfm_sdio_clkctl(struct bwfm_sdio_softc *sc, enum bwfm_sdio_clkstate newstate,
bool pendok)
{
@@ -1134,7 +1214,7 @@ bwfm_sdio_clkctl(struct bwfm_sdio_softc
sc->sc_clkstate));
}
-void
+static void
bwfm_sdio_htclk(struct bwfm_sdio_softc *sc, bool on, bool pendok)
{
uint32_t clkctl, devctl, req;
@@ -1169,16 +1249,15 @@ bwfm_sdio_htclk(struct bwfm_sdio_softc *
bwfm_sdio_write_1(sc, BWFM_SDIO_DEVICE_CTL, devctl);
}
- for (i = 0; i < 5000; i++) {
+ for (i = 0; i < 50; i++) {
if (BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl,
sc->sc_alp_only))
break;
clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR
);
- delay(1000);
+ sdmmc_pause(100000, NULL);
}
- if (!BWFM_SDIO_FUNC1_CHIPCLKCSR_CLKAV(clkctl, sc->sc_alp_only))
-{
+ if (i >= 50) {
printf("%s: HT avail timeout\n", DEVNAME(sc));
return;
}
@@ -1195,8 +1274,91 @@ bwfm_sdio_htclk(struct bwfm_sdio_softc *
}
}
+struct bwfm_sdio_dstab {
+ uint8_t milli;
+ uint8_t val;
+};
+
+static struct bwfm_sdio_dstab pmu11_1v8[] = {
+ {32, 0x6},
+ {26, 0x7},
+ {22, 0x4},
+ {16, 0x5},
+ {12, 0x2},
+ {8, 0x3},
+ {4, 0x0},
+ {0, 0x1}
+}, pmu13_1v8[] = {
+ {6, 0x7},
+ {5, 0x6},
+ {4, 0x5},
+ {3, 0x4},
+ {2, 0x2},
+ {1, 0x1},
+ {0, 0x0}
+}, pmu17_1v8[] = {
+ {3, 0x3},
+ {2, 0x2},
+ {1, 0x1},
+ {0, 0x0}
+}, pmu17_3v3[] = {
+ {16, 0x7},
+ {12, 0x5},
+ {8, 0x3},
+ {4, 0x1},
+ {0, 0x0}
+};
+
+static void
+bwfm_sdio_drivestrength(struct bwfm_sdio_softc *sc, unsigned milli)
+{
+ struct bwfm_softc *bwfm = &sc->sc_sc;
+ struct bwfm_core *core;
+ struct bwfm_sdio_dstab *tab;
+ uint32_t tmp, mask;
+ unsigned i;
+
+ if ((bwfm->sc_chip.ch_cc_caps & BWFM_CHIP_REG_CAPABILITIES_PMU) == 0)
+ return;
+
+ switch (bwfm->sc_chip.ch_chip) {
+ case BRCM_CC_4330_CHIP_ID:
+ tab = pmu11_1v8;
+ mask = __BITS(11,13);
+ break;
+ case BRCM_CC_4334_CHIP_ID:
+ tab = pmu17_1v8;
+ mask = __BITS(11,12);
+ break;
+ case BRCM_CC_43143_CHIP_ID:
+ tab = pmu17_3v3;
+ mask = __BITS(0,3);
+ break;
+ case BRCM_CC_43362_CHIP_ID:
+ tab = pmu13_1v8;
+ mask = __BITS(11,13);
+ break;
+ default:
+ return;
+ }
+
+ for (i=0; tab[i].milli != 0; ++i) {
+ if (milli >= tab[i].milli)
+ break;
+ }
+ if (tab[i].milli == 0)
+ return;
+
+ core = bwfm_chip_get_pmu(&sc->sc_sc);
+ tmp = bwfm_sdio_read_4(sc, core->co_base + BWFM_CHIP_REG_CHIPCONTROL_ADDR);
+ tmp &= mask;
+ tmp |= __SHIFTIN(tab[i].val, mask);
+ bwfm_sdio_write_4(sc, core->co_base + BWFM_CHIP_REG_CHIPCONTROL_ADDR, tmp);
+}
+
+
#if notyet
-int
+static int
bwfm_sdio_bus_sleep(struct bwfm_sdio_softc *sc, bool sleep, bool pendok)
{
uint32_t clkctl;
@@ -1226,7 +1388,7 @@ bwfm_sdio_bus_sleep(struct bwfm_sdio_sof
}
#endif
-void
+static void
bwfm_sdio_readshared(struct bwfm_sdio_softc *sc)
{
struct bwfm_softc *bwfm = &sc->sc_sc;
@@ -1259,12 +1421,12 @@ bwfm_sdio_readshared(struct bwfm_sdio_so
sc->sc_console_addr = le32toh(sdpcm.console_addr);
}
-int
-bwfm_sdio_intr(void *v)
+static int
+bwfm_sdio_intr1(void *v, const char *name)
{
struct bwfm_sdio_softc *sc = (void *)v;
- DPRINTF(("%s: sdio_intr\n", DEVNAME(sc)));
+ DPRINTF(("%s: %s\n", DEVNAME(sc), name));
mutex_enter(&sc->sc_intr_lock);
if (!sdmmc_task_pending(&sc->sc_task))
@@ -1274,13 +1436,25 @@ bwfm_sdio_intr(void *v)
return 1;
}
-void
+static int
+bwfm_sdio_intr(void *v)
+{
+ return bwfm_sdio_intr1(v, "sdio_intr");
+}
+
+static void
bwfm_sdio_task(void *v)
{
struct bwfm_sdio_softc *sc = (void *)v;
+#ifdef BWFM_DEBUG
+ unsigned count = 0;
+#endif
mutex_enter(&sc->sc_intr_lock);
while (sc->sc_task_queued) {
+#ifdef BWFM_DEBUG
+ ++count;
+#endif
sc->sc_task_queued = false;
mutex_exit(&sc->sc_intr_lock);
@@ -1294,12 +1468,18 @@ bwfm_sdio_task(void *v)
mutex_enter(&sc->sc_intr_lock);
}
mutex_exit(&sc->sc_intr_lock);
+
+#ifdef BWFM_DEBUG
+ if (count > 1)
+ DPRINTF(("%s: finished %u tasks\n", DEVNAME(sc), count));
+#endif
}
-void
+static void
bwfm_sdio_task1(struct bwfm_sdio_softc *sc)
{
uint32_t clkctl, devctl, intstat, hostint;
+ bool dorecv, dosend;
if (!sc->sc_sr_enabled && sc->sc_clkstate == CLK_PENDING) {
clkctl = bwfm_sdio_read_1(sc, BWFM_SDIO_FUNC1_CHIPCLKCSR);
@@ -1311,41 +1491,64 @@ bwfm_sdio_task1(struct bwfm_sdio_softc *
}
}
+ dorecv = dosend = sc->sc_clkstate == CLK_AVAIL;
+
intstat = bwfm_sdio_dev_read(sc, BWFM_SDPCMD_INTSTATUS);
DPRINTF(("%s: intstat 0x%" PRIx32 "\n", DEVNAME(sc), intstat));
intstat &= (SDPCMD_INTSTATUS_HMB_SW_MASK|SDPCMD_INTSTATUS_CHIPACTIVE);
- /* XXX fc state */
if (intstat)
bwfm_sdio_dev_write(sc, BWFM_SDPCMD_INTSTATUS, intstat);
+ if (intstat & SDPCMD_INTSTATUS_CHIPACTIVE)
+ printf("%s: CHIPACTIVE\n", DEVNAME(sc));
+
if (intstat & SDPCMD_INTSTATUS_HMB_HOST_INT) {
hostint = bwfm_sdio_dev_read(sc, SDPCMD_TOHOSTMAILBOXDATA);
DPRINTF(("%s: hostint 0x%" PRIx32 "\n", DEVNAME(sc), hostint));
bwfm_sdio_dev_write(sc, SDPCMD_TOSBMAILBOX,
SDPCMD_TOSBMAILBOX_INT_ACK);
if (hostint & SDPCMD_TOHOSTMAILBOXDATA_NAKHANDLED)
- intstat |= SDPCMD_INTSTATUS_HMB_FRAME_IND;
+ sc->sc_rxskip = false;
if (hostint & SDPCMD_TOHOSTMAILBOXDATA_DEVREADY ||
hostint & SDPCMD_TOHOSTMAILBOXDATA_FWREADY)
bwfm_sdio_readshared(sc);
}
- /* FIXME: Might stall if we don't when not set. */
- if (intstat & SDPCMD_INTSTATUS_HMB_FRAME_IND)
- bwfm_sdio_rx_frames(sc);
+ if (intstat & SDPCMD_INTSTATUS_HMB_FRAME_IND) {
+ /* ignore receive indications while recovering */
+ if (dorecv && !sc->sc_rxskip) {
+ DPRINTF(("%s: recv\n", DEVNAME(sc)));
+ bwfm_sdio_rx_frames(sc);
+ }
+ }
- if (MBUFQ_FIRST(&sc->sc_tx_queue))
+ if (intstat & SDPCMD_INTSTATUS_HMB_FC_STATE)
+ dosend = false;
+
+ if (intstat & SDPCMD_INTSTATUS_HMB_FC_CHANGE) {
+ if (dosend) {
+ intstat = bwfm_sdio_dev_read(sc, BWFM_SDPCMD_INTSTATUS);
+ DPRINTF(("%s: intstat2 0x%" PRIx32 "\n", DEVNAME(sc), intstat));
+ if (intstat & (SDPCMD_INTSTATUS_HMB_FC_STATE | SDPCMD_INTSTATUS_HMB_FC_CHANGE))
+ dosend = false;
+ }
+ }
+
+if (!dosend && MBUFQ_FIRST(&sc->sc_tx_queue)) printf("%s: flowctl\n", DEVNAME(sc));
+ if (dosend && MBUFQ_FIRST(&sc->sc_tx_queue)) {
+ DPRINTF(("%s: xmit\n", DEVNAME(sc)));
bwfm_sdio_tx_frames(sc);
+ }
}
-int
+static int
bwfm_sdio_tx_ok(struct bwfm_sdio_softc *sc)
{
return (uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq) != 0 &&
((uint8_t)(sc->sc_tx_max_seq - sc->sc_tx_seq) & 0x80) == 0;
}
-void
+static void
bwfm_sdio_tx_frames(struct bwfm_sdio_softc *sc)
{
struct mbuf *m;
@@ -1365,7 +1568,7 @@ bwfm_sdio_tx_frames(struct bwfm_sdio_sof
if (m->m_type == MT_CONTROL)
bwfm_sdio_tx_ctrlframe(sc, m);
else {
- bwfm_sdio_tx_dataframe(sc, m);
+ bwfm_sdio_tx_dataframe(sc, m);
ifp->if_opackets++;
ifstart = true;
}
@@ -1379,13 +1582,13 @@ bwfm_sdio_tx_frames(struct bwfm_sdio_sof
}
}
-void
+static void
bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_softc *sc, struct mbuf *m)
{
struct bwfm_sdio_hwhdr *hwhdr;
struct bwfm_sdio_swhdr *swhdr;
size_t len, roundto;
-
+
len = sizeof(*hwhdr) + sizeof(*swhdr) + m->m_len;
/* Zero-pad to either block-size or 4-byte alignment. */
@@ -1395,29 +1598,29 @@ bwfm_sdio_tx_ctrlframe(struct bwfm_sdio_
roundto = 4;
KASSERT(roundup(len, roundto) <= sc->sc_bounce_size);
-
+
hwhdr = (void *)sc->sc_bounce_buf;
hwhdr->frmlen = htole16(len);
hwhdr->cksum = htole16(~len);
-
+
swhdr = (void *)&hwhdr[1];
swhdr->seqnr = sc->sc_tx_seq++;
swhdr->chanflag = BWFM_SDIO_SWHDR_CHANNEL_CONTROL;
swhdr->nextlen = 0;
swhdr->dataoff = sizeof(*hwhdr) + sizeof(*swhdr);
swhdr->maxseqnr = 0;
-
+
m_copydata(m, 0, m->m_len, &swhdr[1]);
-
+
if (roundup(len, roundto) != len)
memset(sc->sc_bounce_buf + len, 0,
roundup(len, roundto) - len);
-
+
bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf,
roundup(len, roundto), 1);
}
-void
+static void
bwfm_sdio_tx_dataframe(struct bwfm_sdio_softc *sc, struct mbuf *m)
{
struct bwfm_sdio_hwhdr *hwhdr;
@@ -1465,7 +1668,7 @@ bwfm_sdio_tx_dataframe(struct bwfm_sdio_
sc->sc_tx_count--;
}
-int
+static int
bwfm_sdio_rxctl(struct bwfm_softc *bwfm, char *buf, size_t *lenp)
{
struct bwfm_sdio_softc *sc = (void *)bwfm;
@@ -1475,7 +1678,7 @@ bwfm_sdio_rxctl(struct bwfm_softc *bwfm,
mutex_enter(&sc->sc_lock);
while ((m = bwfm_qget(&sc->sc_rxctl_queue)) == NULL) {
err = cv_timedwait(&sc->sc_rxctl_cv, &sc->sc_lock,
- mstohz(5000));
+ mstohz(5000));
if (err == EWOULDBLOCK)
break;
}
@@ -1495,49 +1698,52 @@ bwfm_sdio_rxctl(struct bwfm_softc *bwfm,
return 0;
}
-void
+static void
bwfm_sdio_rx_frames(struct bwfm_sdio_softc *sc)
-{
+{
struct bwfm_sdio_hwhdr *hwhdr;
struct bwfm_sdio_swhdr *swhdr;
struct bwfm_proto_bcdc_hdr *bcdc;
- uint16_t *sublen, nextlen = 0;
+ uint16_t *sublen, nextlen = 0;
struct mbuf *m;
size_t flen, off, hoff;
char *data;
int nsub;
+ size_t subsize;
hwhdr = (struct bwfm_sdio_hwhdr *)sc->sc_bounce_buf;
swhdr = (struct bwfm_sdio_swhdr *)&hwhdr[1];
data = (char *)&swhdr[1];
-
+
for (;;) {
/* If we know the next size, just read ahead. */
if (nextlen) {
if (bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf,
nextlen, 0))
break;
+ nextlen = 0;
} else {
if (bwfm_sdio_frame_read_write(sc, sc->sc_bounce_buf,
sizeof(*hwhdr) + sizeof(*swhdr), 0))
- break;
+ break;
}
-
+
hwhdr->frmlen = le16toh(hwhdr->frmlen);
hwhdr->cksum = le16toh(hwhdr->cksum);
-
- if (hwhdr->frmlen == 0 && hwhdr->cksum == 0)
+
+ if (hwhdr->frmlen == 0 && hwhdr->cksum == 0) {
break;
+ }
if ((hwhdr->frmlen ^ hwhdr->cksum) != 0xffff) {
printf("%s: checksum error\n", DEVNAME(sc));
- break;
+ break;
}
if (hwhdr->frmlen < sizeof(*hwhdr) + sizeof(*swhdr)) {
printf("%s: length error\n", DEVNAME(sc));
break;
- }
+ }
if (nextlen && hwhdr->frmlen > nextlen) {
printf("%s: read ahead length error (%u > %u)\n",
@@ -1557,8 +1763,11 @@ bwfm_sdio_rx_frames(struct bwfm_sdio_sof
KASSERT(roundup(flen, 4) <= sc->sc_bounce_size -
(sizeof(*hwhdr) + sizeof(*swhdr)));
if (bwfm_sdio_frame_read_write(sc, data,
- roundup(flen, 4), 0))
+ roundup(flen, 4), 0)) {
+ printf("%s: I/O error roundup(%zu, 4) bytes\n",
+ DEVNAME(sc), flen);
break;
+ }
}
if (swhdr->dataoff < (sizeof(*hwhdr) + sizeof(*swhdr))) {
@@ -1628,10 +1837,16 @@ bwfm_sdio_rx_frames(struct bwfm_sdio_sof
break;
}
nsub = flen / sizeof(uint16_t);
- sublen = kmem_zalloc(nsub * sizeof(uint16_t), KM_SLEEP);
- memcpy(sublen, data, nsub * sizeof(uint16_t));
- bwfm_sdio_rx_glom(sc, sublen, nsub, &nextlen);
- kmem_free(sublen, nsub * sizeof(uint16_t));
+ subsize = nsub * sizeof(uint16_t);
+ sublen = NULL;
+ nextlen = 0;
+ if (subsize > 0)
+ sublen = kmem_zalloc(subsize, KM_NOSLEEP);
+ if (sublen != NULL) {
+ memcpy(sublen, data, subsize);
+ bwfm_sdio_rx_glom(sc, sublen, nsub, &nextlen);
+ kmem_free(sublen, subsize);
+ }
break;
default:
printf("%s: unknown channel\n", DEVNAME(sc));
@@ -1640,7 +1855,7 @@ bwfm_sdio_rx_frames(struct bwfm_sdio_sof
}
}
-void
+static void
bwfm_sdio_rx_glom(struct bwfm_sdio_softc *sc, uint16_t *sublen, int nsub,
uint16_t *nextlen)
{
@@ -1664,11 +1879,13 @@ bwfm_sdio_rx_glom(struct bwfm_sdio_softc
bwfm_qput(&m0, m);
if (le16toh(sublen[i]) > m->m_len) {
m_freem(m0);
+ printf("%s: header larger than mbuf\n", DEVNAME(sc));
return;
}
if (bwfm_sdio_frame_read_write(sc, mtod(m, char *),
le16toh(sublen[i]), 0)) {
m_freem(m0);
+ printf("%s: frame I/O error\n", DEVNAME(sc));
return;
}
m->m_len = m->m_pkthdr.len = le16toh(sublen[i]);
@@ -1776,11 +1993,12 @@ bwfm_sdio_rx_glom(struct bwfm_sdio_softc
drop:
printf("rx dropped %p len %d\n",mtod(m, char *),m->m_pkthdr.len);
m_free(m);
+ break;
}
}
#ifdef BWFM_DEBUG
-void
+static void
bwfm_sdio_debug_console(struct bwfm_sdio_softc *sc)
{
struct bwfm_sdio_console c;
@@ -1793,8 +2011,8 @@ bwfm_sdio_debug_console(struct bwfm_sdio
err = bwfm_sdio_ram_read_write(sc, sc->sc_console_addr,
(char *)&c, sizeof(c), 0);
if (err)
- return;
-
+ return;
+
c.log_buf = le32toh(c.log_buf);
c.log_bufsz = le32toh(c.log_bufsz);
c.log_idx = le32toh(c.log_idx);