svn commit: r288532 - head/sys/dev/usb/wlan

Adrian Chadd adrian at FreeBSD.org
Sat Oct 3 05:46:36 UTC 2015


Author: adrian
Date: Sat Oct  3 05:46:35 2015
New Revision: 288532
URL: https://svnweb.freebsd.org/changeset/base/288532

Log:
  rum(4): add command queue for running sleepable tasks in non-sleepable contexts
  
  Tested:
  
  * Tested on WUSB54GC, STA mode.
  * rum0: MAC/BBP RT2573 (rev 0x2573a), RF RT2528
  
  Submitted by:	<s3erios at gmail.com>
  Differential Revision:	https://reviews.freebsd.org/D3629

Modified:
  head/sys/dev/usb/wlan/if_rum.c
  head/sys/dev/usb/wlan/if_rumvar.h

Modified: head/sys/dev/usb/wlan/if_rum.c
==============================================================================
--- head/sys/dev/usb/wlan/if_rum.c	Sat Oct  3 05:44:05 2015	(r288531)
+++ head/sys/dev/usb/wlan/if_rum.c	Sat Oct  3 05:46:35 2015	(r288532)
@@ -158,6 +158,9 @@ static struct ieee80211vap *rum_vap_crea
 			    int, const uint8_t [IEEE80211_ADDR_LEN],
 			    const uint8_t [IEEE80211_ADDR_LEN]);
 static void		rum_vap_delete(struct ieee80211vap *);
+static void		rum_cmdq_cb(void *, int);
+static int		rum_cmd_sleepable(struct rum_softc *, const void *,
+			    size_t, uint8_t, uint8_t, CMD_FUNC_PROTO);
 static void		rum_tx_free(struct rum_tx_data *, int);
 static void		rum_setup_tx_list(struct rum_softc *);
 static void		rum_unsetup_tx_list(struct rum_softc *);
@@ -438,8 +441,8 @@ rum_attach(device_t self)
 	sc->sc_udev = uaa->device;
 	sc->sc_dev = self;
 
-	mtx_init(&sc->sc_mtx, device_get_nameunit(self),
-	    MTX_NETWORK_LOCK, MTX_DEF);
+	RUM_LOCK_INIT(sc);
+	RUM_CMDQ_LOCK_INIT(sc);
 	mbufq_init(&sc->sc_snd, ifqmaxlen);
 
 	iface_index = RT2573_IFACE_INDEX;
@@ -516,6 +519,8 @@ rum_attach(device_t self)
 	    &sc->sc_rxtap.wr_ihdr, sizeof(sc->sc_rxtap),
 		RT2573_RX_RADIOTAP_PRESENT);
 
+	TASK_INIT(&sc->cmdq_task, 0, rum_cmdq_cb, sc);
+
 	if (bootverbose)
 		ieee80211_announce(ic);
 
@@ -545,10 +550,15 @@ rum_detach(device_t self)
 	rum_unsetup_tx_list(sc);
 	RUM_UNLOCK(sc);
 
-	if (ic->ic_softc == sc)
+	if (ic->ic_softc == sc) {
+		ieee80211_draintask(ic, &sc->cmdq_task);
 		ieee80211_ifdetach(ic);
+	}
+
 	mbufq_drain(&sc->sc_snd);
-	mtx_destroy(&sc->sc_mtx);
+	RUM_CMDQ_LOCK_DESTROY(sc);
+	RUM_LOCK_DESTROY(sc);
+
 	return (0);
 }
 
@@ -625,6 +635,57 @@ rum_vap_delete(struct ieee80211vap *vap)
 }
 
 static void
+rum_cmdq_cb(void *arg, int pending)
+{
+	struct rum_softc *sc = arg;
+	struct rum_cmdq *rc;
+
+	RUM_CMDQ_LOCK(sc);
+	while (sc->cmdq[sc->cmdq_first].func != NULL) {
+		rc = &sc->cmdq[sc->cmdq_first];
+		RUM_CMDQ_UNLOCK(sc);
+
+		RUM_LOCK(sc);
+		rc->func(sc, &rc->data, rc->rn_id, rc->rvp_id);
+		RUM_UNLOCK(sc);
+
+		RUM_CMDQ_LOCK(sc);
+		memset(rc, 0, sizeof (*rc));
+		sc->cmdq_first = (sc->cmdq_first + 1) % RUM_CMDQ_SIZE;
+	}
+	RUM_CMDQ_UNLOCK(sc);
+}
+
+static int
+rum_cmd_sleepable(struct rum_softc *sc, const void *ptr, size_t len,
+    uint8_t rn_id, uint8_t rvp_id, CMD_FUNC_PROTO)
+{
+	struct ieee80211com *ic = &sc->sc_ic;
+
+	KASSERT(len <= sizeof(union sec_param), ("buffer overflow"));
+
+	RUM_CMDQ_LOCK(sc);
+	if (sc->cmdq[sc->cmdq_last].func != NULL) {
+		device_printf(sc->sc_dev, "%s: cmdq overflow\n", __func__);
+		RUM_CMDQ_UNLOCK(sc);
+
+		return EAGAIN;
+	}
+
+	if (ptr != NULL)
+		memcpy(&sc->cmdq[sc->cmdq_last].data, ptr, len);
+	sc->cmdq[sc->cmdq_last].rn_id = rn_id;
+	sc->cmdq[sc->cmdq_last].rvp_id = rvp_id;
+	sc->cmdq[sc->cmdq_last].func = func;
+	sc->cmdq_last = (sc->cmdq_last + 1) % RUM_CMDQ_SIZE;
+	RUM_CMDQ_UNLOCK(sc);
+
+	ieee80211_runtask(ic, &sc->cmdq_task);
+
+	return 0;
+}
+
+static void
 rum_tx_free(struct rum_tx_data *data, int txerr)
 {
 	struct rum_softc *sc = data->sc;

Modified: head/sys/dev/usb/wlan/if_rumvar.h
==============================================================================
--- head/sys/dev/usb/wlan/if_rumvar.h	Sat Oct  3 05:44:05 2015	(r288531)
+++ head/sys/dev/usb/wlan/if_rumvar.h	Sat Oct  3 05:46:35 2015	(r288532)
@@ -67,6 +67,25 @@ struct rum_tx_data {
 };
 typedef STAILQ_HEAD(, rum_tx_data) rum_txdhead;
 
+union sec_param {
+	struct ieee80211_key		key;
+	uint8_t				macaddr[IEEE80211_ADDR_LEN];
+	struct ieee80211vap		*vap;
+};
+#define CMD_FUNC_PROTO			void (*func)(struct rum_softc *, \
+					    union sec_param *, uint8_t, \
+					    uint8_t)
+
+struct rum_cmdq {
+	union sec_param			data;
+
+	uint8_t				rn_id;
+	uint8_t				rvp_id;
+
+	CMD_FUNC_PROTO;
+};
+#define RUM_CMDQ_SIZE			16
+
 struct rum_vap {
 	struct ieee80211vap		vap;
 	struct ieee80211_beacon_offsets	bo;
@@ -103,6 +122,12 @@ struct rum_softc {
 
 	struct mtx			sc_mtx;
 
+	struct rum_cmdq			cmdq[RUM_CMDQ_SIZE];
+	struct mtx			cmdq_mtx;
+	struct task			cmdq_task;
+	uint8_t				cmdq_first;
+	uint8_t				cmdq_last;
+
 	uint32_t			sta[6];
 	uint32_t			rf_regs[4];
 	uint8_t				txpow[44];
@@ -128,6 +153,16 @@ struct rum_softc {
 	struct rum_tx_radiotap_header	sc_txtap;
 };
 
-#define RUM_LOCK(sc)		mtx_lock(&(sc)->sc_mtx)
-#define RUM_UNLOCK(sc)		mtx_unlock(&(sc)->sc_mtx)
-#define RUM_LOCK_ASSERT(sc)	mtx_assert(&(sc)->sc_mtx, MA_OWNED)
+#define RUM_LOCK_INIT(sc) \
+	mtx_init(&(sc)->sc_mtx, device_get_nameunit((sc)->sc_dev), \
+	    MTX_NETWORK_LOCK, MTX_DEF);
+#define RUM_LOCK(sc)			mtx_lock(&(sc)->sc_mtx)
+#define RUM_UNLOCK(sc)			mtx_unlock(&(sc)->sc_mtx)
+#define RUM_LOCK_ASSERT(sc)		mtx_assert(&(sc)->sc_mtx, MA_OWNED)
+#define RUM_LOCK_DESTROY(sc)		mtx_destroy(&(sc)->sc_mtx)
+
+#define RUM_CMDQ_LOCK_INIT(sc) \
+	mtx_init(&(sc)->cmdq_mtx, "cmdq lock", NULL, MTX_DEF)
+#define RUM_CMDQ_LOCK(sc)		mtx_lock(&(sc)->cmdq_mtx)
+#define RUM_CMDQ_UNLOCK(sc)		mtx_unlock(&(sc)->cmdq_mtx)
+#define RUM_CMDQ_LOCK_DESTROY(sc)	mtx_destroy(&(sc)->cmdq_mtx)


More information about the svn-src-head mailing list