Module Name: src Committed By: mlelstv Date: Sun Sep 1 05:40:40 UTC 2019
Modified Files: src/sys/dev/ic: bwfm.c bwfmreg.h bwfmvar.h Log Message: >From OpenBSD: - move event handling to workqueue - check for save/restore capability Tag work queue as MPsafe and increase length. Juse use bpf_mtap(), the 802.11 encapsulation is handled by firmware. To generate a diff of this commit: cvs rdiff -u -r1.14 -r1.15 src/sys/dev/ic/bwfm.c cvs rdiff -u -r1.3 -r1.4 src/sys/dev/ic/bwfmreg.h src/sys/dev/ic/bwfmvar.h 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.14 src/sys/dev/ic/bwfm.c:1.15 --- src/sys/dev/ic/bwfm.c:1.14 Sun Sep 2 19:46:53 2018 +++ src/sys/dev/ic/bwfm.c Sun Sep 1 05:40:39 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: bwfm.c,v 1.14 2018/09/02 19:46:53 maya Exp $ */ +/* $NetBSD: bwfm.c,v 1.15 2019/09/01 05:40:39 mlelstv Exp $ */ /* $OpenBSD: bwfm.c,v 1.5 2017/10/16 22:27:16 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation @@ -114,7 +114,8 @@ void bwfm_scan(struct bwfm_softc *); void bwfm_connect(struct bwfm_softc *); void bwfm_rx(struct bwfm_softc *, struct mbuf *); -void bwfm_rx_event(struct bwfm_softc *, char *, size_t); +void bwfm_rx_event(struct bwfm_softc *, struct mbuf *); +void bwfm_rx_event_cb(struct bwfm_softc *, struct mbuf *); void bwfm_scan_node(struct bwfm_softc *, struct bwfm_bss_info *, size_t); uint8_t bwfm_2ghz_channels[] = { @@ -142,7 +143,7 @@ bwfm_attach(struct bwfm_softc *sc) int i, j, error; error = workqueue_create(&sc->sc_taskq, DEVNAME(sc), - bwfm_task, sc, PRI_NONE, IPL_NET, 0); + bwfm_task, sc, PRI_NONE, IPL_NET, WQ_MPSAFE); if (error != 0) { printf("%s: could not create workqueue\n", DEVNAME(sc)); return; @@ -304,9 +305,6 @@ bwfm_start(struct ifnet *ifp) /* TODO: return if no link? */ for (;;) { - struct ieee80211_node *ni; - struct ether_header *eh; - /* Discard management packets (fw handles this for us) */ IF_DEQUEUE(&ic->ic_mgtq, m); if (m != NULL) { @@ -323,36 +321,19 @@ bwfm_start(struct ifnet *ifp) if (m == NULL) break; - eh = mtod(m, struct ether_header *); - ni = ieee80211_find_txnode(ic, eh->ether_dhost); - if (ni == NULL) { - ifp->if_oerrors++; - m_freem(m); - continue; - } - - if (ieee80211_classify(ic, m, ni) != 0) { - ifp->if_oerrors++; - m_freem(m); - ieee80211_free_node(ni); - continue; - } - error = sc->sc_bus_ops->bs_txdata(sc, &m); if (error == ENOBUFS) { IF_PREPEND(&ifp->if_snd, m); ifp->if_flags |= IFF_OACTIVE; break; } - if (error != 0) { ifp->if_oerrors++; m_freem(m); - if (ni != NULL) - ieee80211_free_node(ni); - } else { - bpf_mtap3(ic->ic_rawbpf, m, BPF_D_OUT); + continue; } + + bpf_mtap(ifp, m, BPF_D_OUT); } } @@ -770,6 +751,9 @@ bwfm_task(struct work *wk, void *arg) case BWFM_TASK_KEY_DELETE: bwfm_key_delete_cb(sc, &t->t_key); break; + case BWFM_TASK_RX_EVENT: + bwfm_rx_event_cb(sc, t->t_mbuf); + break; default: panic("bwfm: unknown task command %d", t->t_cmd); } @@ -1261,6 +1245,52 @@ bwfm_chip_cm3_set_passive(struct bwfm_so } } +int +bwfm_chip_sr_capable(struct bwfm_softc *sc) +{ + struct bwfm_core *core; + uint32_t reg; + + if (sc->sc_chip.ch_pmurev < 17) + return 0; + + switch (sc->sc_chip.ch_chip) { + case BRCM_CC_4345_CHIP_ID: + case BRCM_CC_4354_CHIP_ID: + case BRCM_CC_4356_CHIP_ID: + core = bwfm_chip_get_pmu(sc); + sc->sc_buscore_ops->bc_write(sc, core->co_base + + BWFM_CHIP_REG_CHIPCONTROL_ADDR, 3); + reg = sc->sc_buscore_ops->bc_read(sc, core->co_base + + BWFM_CHIP_REG_CHIPCONTROL_DATA); + return (reg & (1 << 2)) != 0; + case BRCM_CC_43241_CHIP_ID: + case BRCM_CC_4335_CHIP_ID: + case BRCM_CC_4339_CHIP_ID: + core = bwfm_chip_get_pmu(sc); + sc->sc_buscore_ops->bc_write(sc, core->co_base + + BWFM_CHIP_REG_CHIPCONTROL_ADDR, 3); + reg = sc->sc_buscore_ops->bc_read(sc, core->co_base + + BWFM_CHIP_REG_CHIPCONTROL_DATA); + return reg != 0; + case BRCM_CC_43430_CHIP_ID: + core = bwfm_chip_get_core(sc, BWFM_AGENT_CORE_CHIPCOMMON); + reg = sc->sc_buscore_ops->bc_read(sc, core->co_base + + BWFM_CHIP_REG_SR_CONTROL1); + return reg != 0; + default: + core = bwfm_chip_get_pmu(sc); + reg = sc->sc_buscore_ops->bc_read(sc, core->co_base + + BWFM_CHIP_REG_PMUCAPABILITIES_EXT); + if ((reg & BWFM_CHIP_REG_PMUCAPABILITIES_SR_SUPP) == 0) + return 0; + reg = sc->sc_buscore_ops->bc_read(sc, core->co_base + + BWFM_CHIP_REG_RETENTION_CTL); + return (reg & (BWFM_CHIP_REG_RETENTION_CTL_MACPHY_DIS | + BWFM_CHIP_REG_RETENTION_CTL_LOGIC_DIS)) == 0; + } +} + /* RAM size helpers */ void bwfm_chip_socram_ramsize(struct bwfm_softc *sc, struct bwfm_core *core) @@ -1455,8 +1485,6 @@ bwfm_proto_bcdc_query_dcmd(struct bwfm_s } if (buf) { - if (size > *len) - size = *len; if (size < *len) *len = size; memcpy(buf, dcmd->buf, *len); @@ -1772,39 +1800,59 @@ bwfm_rx(struct bwfm_softc *sc, struct mb ntohs(e->ehdr.ether_type) == BWFM_ETHERTYPE_LINK_CTL && memcmp(BWFM_BRCM_OUI, e->hdr.oui, sizeof(e->hdr.oui)) == 0 && ntohs(e->hdr.usr_subtype) == BWFM_BRCM_SUBTYPE_EVENT) { - bwfm_rx_event(sc, mtod(m, char *), m->m_len); - m_freem(m); + bwfm_rx_event(sc, m); + // m_freem(m); return; } s = splnet(); - if ((ifp->if_flags & IFF_RUNNING) != 0) { + //if ((ifp->if_flags & IFF_RUNNING) != 0) { m_set_rcvif(m, ifp); if_percpuq_enqueue(ifp->if_percpuq, m); - } + //} splx(s); } void -bwfm_rx_event(struct bwfm_softc *sc, char *buf, size_t len) +bwfm_rx_event(struct bwfm_softc *sc, struct mbuf *m) +{ + struct bwfm_task *t; + + t = pcq_get(sc->sc_freetask); + if (t == NULL) { + m_freem(m); + printf("%s: no free tasks\n", DEVNAME(sc)); + return; + } + + t->t_cmd = BWFM_TASK_RX_EVENT; + t->t_mbuf = m; + workqueue_enqueue(sc->sc_taskq, (struct work*)t, NULL); +} + +void +bwfm_rx_event_cb(struct bwfm_softc *sc, struct mbuf *m) { struct ieee80211com *ic = &sc->sc_ic; - struct bwfm_event *e = (void *)buf; + struct bwfm_event *e = mtod(m, void *); + size_t len = m->m_len; int s; - DPRINTF(("%s: buf %p len %lu datalen %u code %u status %u" - " reason %u\n", __func__, buf, len, ntohl(e->msg.datalen), + DPRINTF(("%s: event %p len %lu datalen %u code %u status %u" + " reason %u\n", __func__, e, len, ntohl(e->msg.datalen), ntohl(e->msg.event_type), ntohl(e->msg.status), ntohl(e->msg.reason))); - if (ntohl(e->msg.event_type) >= BWFM_E_LAST) + if (ntohl(e->msg.event_type) >= BWFM_E_LAST) { + m_freem(m); return; + } switch (ntohl(e->msg.event_type)) { case BWFM_E_ESCAN_RESULT: { - struct bwfm_escan_results *res = (void *)(buf + sizeof(*e)); + struct bwfm_escan_results *res = (void *)&e[1]; struct bwfm_bss_info *bss; int i; if (ntohl(e->msg.status) != BWFM_E_STATUS_PARTIAL) { @@ -1817,11 +1865,13 @@ bwfm_rx_event(struct bwfm_softc *sc, cha } len -= sizeof(*e); if (len < sizeof(*res) || len < le32toh(res->buflen)) { + m_freem(m); printf("%s: results too small\n", DEVNAME(sc)); return; } len -= sizeof(*res); if (len < le16toh(res->bss_count) * sizeof(struct bwfm_bss_info)) { + m_freem(m); printf("%s: results too small\n", DEVNAME(sc)); return; } @@ -1874,6 +1924,8 @@ bwfm_rx_event(struct bwfm_softc *sc, cha default: break; } + + m_freem(m); } void Index: src/sys/dev/ic/bwfmreg.h diff -u src/sys/dev/ic/bwfmreg.h:1.3 src/sys/dev/ic/bwfmreg.h:1.4 --- src/sys/dev/ic/bwfmreg.h:1.3 Fri May 11 07:41:11 2018 +++ src/sys/dev/ic/bwfmreg.h Sun Sep 1 05:40:39 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: bwfmreg.h,v 1.3 2018/05/11 07:41:11 maya Exp $ */ +/* $NetBSD: bwfmreg.h,v 1.4 2019/09/01 05:40:39 mlelstv Exp $ */ /* $OpenBSD: bwfmreg.h,v 1.16 2018/02/07 21:44:09 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation @@ -644,3 +644,4 @@ 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.3 src/sys/dev/ic/bwfmvar.h:1.4 --- src/sys/dev/ic/bwfmvar.h:1.3 Sat Sep 1 22:01:03 2018 +++ src/sys/dev/ic/bwfmvar.h Sun Sep 1 05:40:39 2019 @@ -1,4 +1,4 @@ -/* $NetBSD: bwfmvar.h,v 1.3 2018/09/01 22:01:03 riastradh Exp $ */ +/* $NetBSD: bwfmvar.h,v 1.4 2019/09/01 05:40:39 mlelstv Exp $ */ /* $OpenBSD: bwfmvar.h,v 1.1 2017/10/11 17:19:50 patrick Exp $ */ /* * Copyright (c) 2010-2016 Broadcom Corporation @@ -57,7 +57,7 @@ #define BWFM_DEFAULT_SCAN_UNASSOC_TIME 40 #define BWFM_DEFAULT_SCAN_PASSIVE_TIME 120 -#define BWFM_TASK_COUNT 32 +#define BWFM_TASK_COUNT 256 struct bwfm_softc; @@ -119,6 +119,7 @@ enum bwfm_task_cmd { BWFM_TASK_NEWSTATE, BWFM_TASK_KEY_SET, BWFM_TASK_KEY_DELETE, + BWFM_TASK_RX_EVENT, }; struct bwfm_cmd_newstate { @@ -138,9 +139,11 @@ struct bwfm_task { union { struct bwfm_cmd_newstate newstate; struct bwfm_cmd_key key; + struct mbuf *mbuf; } t_u; #define t_newstate t_u.newstate #define t_key t_u.key +#define t_mbuf t_u.mbuf }; struct bwfm_softc { @@ -178,6 +181,7 @@ int bwfm_detach(struct bwfm_softc *, int int bwfm_chip_attach(struct bwfm_softc *); int bwfm_chip_set_active(struct bwfm_softc *, uint32_t); void bwfm_chip_set_passive(struct bwfm_softc *); +int bwfm_chip_sr_capable(struct bwfm_softc *); 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);