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);

Reply via email to